一、前言
引入Redis事务的现实需求:redis 的单个命令都是原子,比如set get,但是多个redis命令如何做到原子性呢? 答案是两种实现方式:要么是Redis事务,要么是Lua脚本。
二、Redis事务特性
Redis事务特性 1、按进入队列的顺序执行,先进入先执行 2、不会受到其他客户端的请求的影响 3、事务不能嵌套,多个multi命令效果一样
三、事务命令基本使用
3.1 事务的四条命令
事务命令: multi:开启事务,multi表示多条,就是开启事务的意思 exec:执行事务 discard:取消事务/回滚事务 watch:监视key,如果被监视的key在exec之前被修改,事务会取消(凡是进入到事务里面就被watch了,只有修改,事务队列里这个就不能执行成功)
watch 命令的底层原理类似 cas 乐观锁(compare and set),为什么是乐观锁呢?其实还是为了保证 redis 的速度
3.2 转账(开启事务并执行事务)
set tom 1000
set mic 1000
multi
decrby tom 100
incrby mic 100
exec
get tom
get mic
3.3 事务的取消和watch
事务的取消和watch
discard:取消事务 watch:监视key,如果被监视的key在exec之前被修改,事务会取消(凡是进入到事务里面就被watch了,只有修改,事务队列里这个就不能执行成功)
watch 命令的底层原理类似 cas 乐观锁(compare and set),为什么是乐观锁呢?其实还是为了保证 redis 的速度
四、事务发生异常
事务发生异常包括两种:执行事务之前 + 执行事务之后
如果执行exec事务之前出现错误,可以回滚 如果执行exec事务之后出现错误,不可以回滚
对于执行exec事务之后出现错误,Redis的设计不可以回滚,这样设计的理由是:
(1) 一般来说,执行exec事务之后发生的都是语法错误,这种错误如果已经在测试环境中执行了,在生产环境中不会犯这样的错误; (2) 如果向 mysql 一样,提供一个 undo log 日志,会对redis速度产生影响。
Redis 为了性能考虑,不做 undolog 日志,就无法回滚执行 exec事务 之后的错误,这也是 Redis 事务的局限性,所以开发中解决多个redis命令的原子性问题,基本都会才有 lua脚本 实现,而不是 Redis 事务。
五、尾声
Redis事务,完成了。
|