导读
乐观锁介绍:
watch指令在redis事物中提供了CAS的行为。为了检测被watch的keys在是否有多个clients同时改变引起冲突,这些keys将会被监控。如果至少有一个被监控的key在执行exec命令前被修改,整个事物将会回滚,不执行任何动作,从而保证原子性操作,并且执行exec会得到null的回复。
乐观锁工作机制:
watch 命令会监视给定的每一个key,当exec时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令,及客户端连接关闭都会清除连接中的所有监视。还有,如果watch一个不稳定(有生命周期)的key并且此key自然过期,exec仍然会执行事务队列的指令。
示例
原理
- WATCH监控:每个Redis数据库都保存着一个watched_keys字典来保存被监控的健,字典值是一个链表,链表中记录了所有监视相应键的客户端
- 监控机制触发:所有对数据库进行修改的命令,如SET、LPUSH、SADD、ZREM、DEL、FLUSHDB等,在执行之后都会调用multi.c/touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的key,有的话touchWatchKey函数会将监视的客户端的REDIS_DIRTY_CAS标识打开,表示该客户端事物安全性已经被破坏。
- 判断事物是否安全 :当服务器接收到一个客户端发来的EXEC命令时,服务器将会根据这个客户端是否打开REDIS_DIRTY_CAS标识来决定是否执行事物
-
总结
- 事务提供了一种将多个命令打包,然后一次性有序(FIFO)执行的机制
- 事务执行过程不会被中断
- 带WATCH命令的事务会将客户端和被监视的键在数据库watched_keys字典中进行关联,当键被修改程序会将所有监视键的客户端REDIS_DIRTY_CAS标识打开
- 在客户端提交EXEC命令时,会检查REDIS_DIRTY_CAS标识,标识打开事物将不会被执行
- Redis事务具有ACID的特性(当服务器运行在AOF模式下,并且appendfsync选项值为always时才具有持久性)