一、Redis 事务实现的过程和原理
第一步:观察数据
客户端在修改数据之前,先使用watch命令观察要修改的数据,这一步相当于记下了数据的版本号
第二步:开启事务
使用 multi 命令开启事务。
开启事务后,所有命令都不会立即发送给Redis,而是先缓存到客户端本地,不会真正执行,直到执行exec命令提交事务的时候,客户端才会一次性把这些命令发送到Redis去执行。
第三步:Redis执行命令
客户端使用exec提交事务,Redis接收到客户端exec的命令后,会先比较数据的版本号,如果版本号一致,则会执行所有客户端提交过来的命令。
如果当前的版本号和被watch时的版本号不一致,则客户端这次提交的所有事务内的命令都不会被执行,相当于该事务执行失败。
二、实际操作
概括过程:使用watch监视数据,然后开启事务,做业务处理,提交命令。
注:什么情况下,会出现版本号不一致的情况?
比如客户端A开启事务,但还没有执行exec提交,这时客户端A对Redis的命令都缓存在了客户端A上,还没有批量提交到Redis执行命令,这时客户端B对该数据进行了写操作,那么这条数据的版本号也就变了,这时,客户端A执行exec命令,就会出现版本号不一致,导致客户端A该事务下的所有命令都执行失败的问题。
三、PHP 伪代码,实现防止商品秒杀超卖
四、说明
Redis通过watch及multi实现了防止超卖的问题,其本质是分为两部分:
第一部分是watch,第二部分是从multi到exec的所有命令。
当客户端watch命令,Redis就开始监视数据,获取数据当前版本号
当客户端exec命令,Redis先比对数据当前版本号和开始监视时的版本号是否一致,如果一致就把从multi到exec的所有命令通通执行,否则multi到exec的所有命令通通不执行。