Redis事务和MySQL事务对比(主要是操作流程)
MySQL:
- 开启事务
- 执行事务
- 提交(正常执行)/(出现异常)回滚事务
Redis:
- 开启事务
- 任务入队列(一个先进先出的结构,命令的执行顺序是先进先执行)
- exec/discard事务
机制:事务开启后,每次输入的指令会依次入事务队列,待执行exec执行后,队列中的命令会按照进入顺序,依次执行
命令介绍
- multi:开启事务,事务执行之后不能嵌套执行
- exec:执行事务
- discard:放弃整个事务
- expire:设定过期值(值只能为数字,如
expire key 10
,而expire key 10s
是错误的) - watch:用于在客户端并发中,为事务提供一个乐观锁(也就是CAS,及
Check And Set
),也就是在执行了watch命令并监控了某几个变量,如果变量被并发事务更改,事务就会发生回滚 - unwatch:是否所有变量的乐观锁(在)
事务错误和回滚
- 执行时错误(不回滚),如对于命令
expire k 10s
,本身没有缺少参数,但是参数的类型是错误的,因此在执行的时候会报错 - 指令入队列时错误,并且会终止整个事务(回滚),如对于指令
set k
,因为缺少参数,会在入队列时发生错误,并且会终止整个事务(事务开启后的指令都不会执行) - 指令入队列时错误,不会终止整个事务(不回滚),如:在开启事务后,输入指令
multi
,在事务中嵌套开启事务,不能入队列,发生错误,但是不会影响事务的执行
Redis为什么不支持运行时错误事务回滚
- 作者认为错误通常是编译错误造成的,这些错误通常在开发环境中出现,极少出现在生产环境中
- 与Redis追求简单高效的设计原则不符
watch指令种的事务回滚
- watch执行的时机:在事务开启之前执行
- 即使把原对象的值重新赋值给原对象,watch依然生效
- 在事务中执行watch命令会报错,但不会终止事务
预留问题
是否在队列中如果有指令unwatch的存在,watch就没有用了
总结
事务回滚的情况
- watch监控的变量在事务执行期间被修改
- 指令缺少参数时入队列