Redis - 深入理解Redis事务
2019-10-21 本文已影响0人
齐晋
目录
- Redis是如何实现事务的?
- 事务中执行的命令出现错误,会回滚事务吗?
- 同一个连接可以重复开启事务吗?
- 多个客户端同时开启事务会怎样?
- 使用Redis事务只用MULTI和EXEC吗?
- Redis中的WATCH机制是怎么实现的?
Redis是如何实现事务的?
解读
事务要满足ACID四个原则。了解Redis实现事务的机制,就能了解Redis是如何分别保证ACID的。同时,了解了事务实现机制,也能清楚知道Redis事务有何优劣,在使用时如何避免Redis事务缺点。
参考
概要
- Redis通过四个命令实现事务:
WATCH
,MULTI
,EXEC
,DISCARD
- Redis事务以
MULTI
命令开始,EXEC
/DISCARD
命令结束。EXEC
用于提交事务,DISCARD
用于取消事务。- 在开启事务时,Redis操作命令并不会立即执行,而是会先进入事务队列。Redis事务队列是一个FIFO队列
- 当执行
EXEC
命令时,会把事务队列中的命令逐个执行,不会被任何命令中断。
事务中执行的命令出现错误,会回滚事务吗?
解读
通常,一个事务中会有不止一个Redis操作,任何一个操作都有失败的可能。在有操作出错的情况下,会影响事务的执行吗?
参考
概要
- 首先,Redis事务时不支持回滚的。也就是说,如果事务中的命令执行出错,已经执行的命令不会撤回,后续的命令也会继续执行。
- Redis事务的命令分为入队和执行两个阶段。在入队(进入事务队列)时出错,Redis会忽略入队出错的命令,不会影响后续命令入队。执行时出错,出错命令会被Redis忽略,其他没有出错的命令均会执行。
同一个连接可以重复开启事务吗?
解读
本质问题是是否允许事务嵌套。
参考
概要
- Redis事务不能嵌套。如果再收到
MULTI
命令开启事务,会返回错误(redis-cli会返回(error) ERR MULTI calls can not be nested
这样的错误)- 遇到嵌套事务返回错误后,并不会影响事务队列继续接收命令,也不会修改事务队列中的任何数据。
多个客户端同时开启事务会怎样?
解读
在并发情况,很容易出现多个客户端同时开启事务的情况。这时Redis会区分客户端维护事务队列吗?另外,实际工程中为了提升性能,通常会用Redis连接池复用连接,这种情况下,会出现连接复用导致事务嵌套吗?
参考
概要
- Redis事务队列是与连接绑定的,不同的连接中允许同时开启事务,不会相互影响
- 合理的事务管理器中,会在开启事务时绑定连接,防止连接被其他请求复用。不过应用不当,会出现连接不能被归还的问题。(由此可见,一个优秀的事务管理器是多么重要)
使用Redis事务只用MULTI
和EXEC
吗?
解读
使用Redis事务,不能单纯只用MULTI
和EXEC
,因为某些key在事务执行时已经变了。正确的Redis事务需要保证事务执行时,事务涉及的数据没有被修改。
参考
概要
- 在开启事务前,使用
WATCH
命令监视指定的key,形成乐观锁- 事务执行时,如果被
WATCH
的key发生了变化,则事务失效,不能执行。
Redis中的WATCH
机制是怎么实现的?
解读
无他,只是为了了解底层实现原理
参考
概要
- 每个被
WATCH
的key都会维护一个WATCH
这个key的所有client列表- 当被
WATCH
的key发生修改时(执行任意修改命令),所有WATCH
该key的client的REDIS_DIRTY_CAS
字段会被修改为打开状态。- 当执行事务时,如果这个client的
REDIS_DIRTY_CAS
字段被打开,说明有至少一个数据被修改,事务不能执行。