为了确保数据的正确性,我们必须认识到这一点:在多个客户端同时处理相同的数据时,不谨慎的操作很容易会导致数据出错。本节将介绍使用Redis事务来防止数据出错的方法,以及在某些情况下,使用事务来提升性能的方法。
Redis的事务和传统关系数据库的事务并不相同。在关系数据库中,用户首先向数据库服务器发送begin,然后执行各个相互一致的写操作和读操作,最后,用户可以选择发送commit来确认之前所做的修改,后者发送rollback来放弃那些修改。
在Redis里面也有简单的方法可以处理一连串相互一致的读操作和写操作。正如之前介绍的那样,Redis的事务以特殊命令multi为开始,之后跟着用户传入的多个命令,最后以exec为结束。但是由于这种简单的事务在exec命令被调用之前不会执行任何实际操作,所以用户将没办法根据读取到的数据来做决定。这个问题看上去似乎无足轻重,但实际上无法以一致的形式读取数据将导致某一类型的问题变得难以解决,除此之外,因为在多个事务同时处理同一个对象时通常需要用到二阶提交,所以如果事务不能以一致的形式读取数据,那么二阶提交将无法实现,从未导致一些原本可以成功执行的事务沦落至失败的地步。比如说:在市场里面购买一件商品,就是其中一个会因为无法以一致的形式读取数据而变得难以解决的问题,本节接下来将在实际环境中对这个问题进行介绍。
延迟执行事务有助于提升性能
因为Redis在执行事务的过程中,会延迟执行已入队的命令知道客户端发送exec命令为止。因此,包括本书使用的Python客户端在内的很多Redis客户端都会等到事务包含的所有命令都出现了之后,才一次性地将multi命令、要在事务中执行的一系列命令,以及exec命令全部发送给Redis,然后等待知道接受到所有命令的回复为止。这种【一次性发送多个命令,然后等待所有回复出现】的做法通常被成为流水线,它可以通过减少客户端与Redis服务器之间的网络通信次数来提示Redis在执行多个命令时的性能。
最近几个月,Fake Game公司发现他们在一个社交网站上推出的角色扮演网页游戏正在变得越来越受欢迎。因此,关心玩家需求的Fake Game公司决定在游戏里面增加一个商品买卖市场,让玩家们可以在市场里面销售和购买商品。本节接下来的内容将介绍设计和实现这个商品买卖市场的方法,并说明如何按需对这个商品买卖市场进行扩展。