详解Redis之事务
目录
Redis事务
概念
特性
常用命令
MULTI
EXEC
DISCARD
WATCH
UNWATCH
使用演示
使用场景
注意事项
Redis事务
概念
Redis事务和MySQL的事务在概念上是类似的,都是把一系列操作绑定成一组,让这一组能够批量执行。但是,Redis事务和MySQL事务在特性上有所不同,Redis事务没有回滚机制,只能保证这些操作批量执行,不能做到“一个失败就恢复到初始状态”。
Redis 事务本质上是在服务器上搞了⼀个 "事务队列". 每次客⼾端在事务中进⾏⼀个操作, 都会把命令先发给服务器, 放到 "事务队列" 中(但是并不会⽴即执⾏)
⽽是会在真正收到 EXEC 命令之后, 才真正执⾏队列中的所有操作.
特性
1.弱化的原子性:
Redis事务中的所有命令都会序列化、按顺序地执行,执行过程中不会被其他客户端的命令请求打断。
但是,Redis事务没有回滚机制。如果事务中的某个命令执行失败,其他命令仍然会继续执行,事务不会因为一个命令的失败而回滚到初始状态。
2.不保证一致性:
由于Redis事务没有回滚机制,且没有涉及“约束”,因此事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况。
3.不需要隔离性:
Redis是单线程处理请求的,因此不需要隔离级别,也不会并发执行事务。
4.不需要持久性:
Redis事务是保存在内存中的,是否开启持久化是redis-server自己的事情,和事务无关。
常用命令
MULTI
功能:开启一个事务。
执行成功返回OK。当开启事务后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中。当EXEC命令被调用时,所有队列中的命令才会被执行。
EXEC
功能:真正执行事务。
每次添加一个操作,都会提示“QUEUED”,说明命令已经进入服务端的队列。当执行EXEC命令时,服务器才会真正执行这些命令。
EXEC命令的回复是一个数组,数组中的每个元素都是执行事务中的命令所产生的回复。回复元素的先后顺序和命令发送的先后顺序一致。
DISCARD
功能:放弃当前事务。
直接清空事务队列,之前的操作都不会真正执行。
WATCH
一定要在开启事务之前使用!!!
功能:监控一个或多个键。
当开启事务时,如果对WATCH的键进行修改(在EXEC命令执行之前),就会记录当前键的“版本号”。在真正提交事务时(执行EXEC命令时),如果发现当前服务器上的键的版本号已经超过了事务开始时的版本号,就会让事务执行失败。
WATCH命令本质上是给EXEC加了个判定条件,属于“乐观锁”。
UNWATCH
功能:取消对键的监控。
相当于WATCH的逆操作。
使用演示
没开启事务,一方修改,另一方能实时看到
开启事务,一方修改,另一方看不到,直到事务执行完毕
开启事务,一方修改,另一方针对同一Key修改,最终value为执行事务设置的value
WATCH只能在开启事务前使用
使用WATCH,开启事务,在事务中修改Key之前,Key被修改,在事务中修改Key,当执行EXEC会提示(nil),Key的value依旧是另一方设置的value
使用场景
Redis事务适用于需要把多个操作打包进行的情况。例如,在商品抢购场景中,如果使用Redis事务,可以避免多线程下的线程安全问题。通过Redis事务,可以确保一系列操作(如检查库存、扣减库存等)的原子性执行,从而避免数据不一致的问题。
注意事项
1.锁的释放:
在使用WATCH命令进行乐观锁控制时,需要注意在事务执行完毕后及时释放锁(即取消对键的监控)。如果忘记释放锁或因为异常导致锁无法释放,则可能会导致死锁问题。
2.事务的失败处理:
由于Redis事务没有回滚机制,因此需要在设计业务逻辑时考虑到事务失败的处理方式。例如,可以通过检查命令的返回值来判断命令是否执行成功,并采取相应的处理措施。
3.避免事务过大:
如果事务过大(包含过多的命令),可能会导致Redis服务器的性能下降。因此,需要合理控制事务的大小,避免将过多的命令放入一个事务中执行。