13. redis事务操作
13.1事务简介
原子性(Atomicity)
一致性(Consistency)
隔离性(isolation)
持久性(durabiliby)
ACID
13.2 Redis事务
提供了multi、exec命令来完成
- 第一步,客户端使用multi命令显式地开启事务
- 第二步,客户端把事务中要执行的指令发送给服务器端,例如set 、get 、lpush,这些指令不会立即执行,进入一个队列中
- 第三步,客户端向服务器发送一个命令 exec,来完成事务提交。当服务器端收到这个指令后,实际去执行上一步中的命令队列.
multi set k1 v1 set k2 v2 set k3 v3 get k1 exec multi set k4 v4 set k5 v5 discard //取消
13.3 Redis的事务处理机制
13.3.1 原子性
第一种情况
- 在执行exec指令前,客户端发送操作命令有误,redis会报错并记录这个错误。此时,还可以继续发送命令操作,在执行exec命令之后,redis拒绝执行所有提交的指令,返回事务失败的结果。(保证了原子性)
multi set k1 v1 get k1 v1 set k2 v2 exec 整个队列失败
第二种情况
- 向服务器发送指令,其中有指令和操作的数据类型不匹配,放入队列时并没有报错。使用lpop指令操作失败,但get指令成功了。(不能保证原子性)
multi lpop k1 //失败 get k1 //成功 exec
第三种情况
- 在执行事务的exec指令时,redis实例发生了故障,导致事务执行失败
- 如果redis开启了aof日志,可能会有一部分指令被记录到AOF日志中,需要使用redis-check-aof 去检查aof文件,将未完成事务操作从aof清除,从而保证原子性
13.3.2 一致性
- 第一种情况,指令进入队列时就报错,整个事务全部被放弃执行,可以保证数据的一致性。
- 第二种情况,进入队列时没有报错,实际执行时报错,有错误的指令不去执行,正确的指令可以正常执行,可以保证数据的一致性
- 第三种情况,exec指令时redis实例发生故障,根据RDB和AOF情况来做判断
- 如果没有开启rdb和aof,数据在重启后没有,一致的
- 如果使用了rdb方式,rdb不会在事务执行的时候去保存数据,数据库也是一致的
- 使用aof日志,如果事务队列操作记录没有进入aof,可以保证一致性。如果已加入了一部分,使用redis-check-aof清除事务中已完成的操作,保证事务的一致性
13.3.3 隔离性
提交exec指令去执行事务,分成exec之前和exec之后两种情况
并发操作在exec指令前,要实现隔离性的保证 ,需要使用watch机制,否则不能保证隔离性
在事务执行前,相当于有一个监控器,在监控key是否已经被修改过了,如果已修改,则放弃事务执行,避免了事务的隔离性被破坏。如果客户再次执行,此时,没有其他客户端去修改数据,则执行成功。
悲观锁:synchronized
乐观锁:Atomic原子操作
使用unwatch取消watch命令对所有key的监控。
13.3.4 持久性
redis内存数据库,取决于持久化配置模式
不开启rdb和aof,只当作缓存使用,是不能保证持久性
使用rdb,如果在一个事务执行后,下一次的rdb快照还未执行前,redis实例发生故障了,不能保证持久性
使用aof, 配置选项 everysec、always、no,也不能保证持久性
不管redis采用什么配置模式,都不能保证事务的持久性