通过使用 MULTI 和 EXEC , 我们可以将多条命令放到一个事 务里面执行, 确保事务里面的命令要么全部都被执行, 要么就一个都不执行, 从而防止数据出错。但是有时候只使用事务还是无法保证数据的正确性, 这时候就需要使用 Redis 提供的乐观锁功能(Optimistic Locking)
命令
-
WATCH key [key …]
如果被监视的键在事务提交之前(也即是 EXEC 命令执行之前), 已经被其他客户端抢先修改了, 那么服务器将拒绝执行客户端提交的事务, 并返回nil作为事务的回复127.0.0.1:6379> watch msg OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> set msg haha QUEUED 127.0.0.1:6379> exec (nil) 复制代码
在上个事务提交之前已执行:
127.0.0.1:6379> multi OK 127.0.0.1:6379> set msg hehe QUEUED 127.0.0.1:6379> exec 1) OK 复制代码
结果:
127.0.0.1:6379> get msg "hehe" 复制代码
-
UNWATCH
取消对所有键的监视 -
DISCARD
放弃执行事务,并且取消对所有键的监视(相当于执行 UNWATCH)
乐观锁和悲观锁的区别
- 乐观锁会对被加锁的数据进行监视,多个客户端可以同时尝试对数据进行修改,其中最先尝试的客户端会成功,而之后尝试的客户端则会失败
- 悲观锁只让一个客户端对数据进行修改,而其他客户端则需要等待正在进行修改的客户端执行完毕之后,才能尝试获得修改权
- 对于频繁进行读写操作的 Redis 来说,使用乐观锁可以避免客户端被阻塞:当一个客户端修改数据失败之后,它只要重试就可以了,这个过程不需要进行任何的等待
事务和乐观锁的缺陷
- 对于一个的事务,通常需要仔细思考才能知道应该对哪些键进行加锁:锁了不应该锁的键会增加事务失败的机会,甚至可能会造成程序出 错;而忘了对应该锁的键进行加锁的话,程序又会产生竞争条件
- 有时候为了防止竞争条件发生,即使操作本身不需要用到事务,但是为了让乐观锁生效,也会使用事务将命令包裹起来,这增加了实现的复杂度,并且带来了额外的性能损耗
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END