Redis 的事务
Redis 的事务处理
与 RDBMS
的事务有一些不同。首先 Redis 不支持事务的回滚机制
,这也就意味着当事务发生了错误(只要不是语法错误),整个事务依然会继续执行下去,直到事务队列中所有命令都执行完毕。在Redis 官方文档中说明了为什么 Redis 不支持事务回滚 -- 只有当编程语法错误的时候,Redis 命令执行才会失败。这种错误通常出现在开发环境中,而很少出现在生产环境中,没有必要开发事务回滚功能。
Redis 的事务处理命令
-
MULTI
:开启一个事务; -
EXEC
:事务执行,将一次性执行事务内的所有命令; -
DISCARD
:取消事务; -
WATCH
:监视一个或多个键,如果事务执行前某个键发生了改动,那么事务也会被打断; -
UNWATCH
:取消WATCH
命令对所有键的监视。
需要说明的是 Redis 实现事务是基于COMMAND 队列
,如果 Redis 没有开启事务,那么任何的 COMMAND
都会立即执行并返回结果。如果 Redis 开启了事务,COMMAND
命令会放到队列中,并且返回排队的状态 QUEUED
,只有调用 EXEC
,才会执行 COMMAND
队列中的命令。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> hmset user:001 name Jay
QUEUED
127.0.0.1:6379> hmset user:002 name JJ
QUEUED
127.0.0.1:6379> exec
1> ok
2> ok
你能看到在 MULTI
和 EXEC
之间的 COMMAND
命令都会被放到 COMMAND 队列
中,并返回排队的状态,只有当 EXEC
调用时才会一次性全部执行。
乐观锁的实现
我们经常使用 Redis 的 WATCH
和 MULTI
命令来处理共享资源的并发操作,比如秒杀,抢票等。实际上 WATCH+MULTI
实现的是乐观锁。
需要说明的是
MULTI
后不能再执行WATCH
命令,否则会返回WATCH inside MULTI is not allowed
错误(因为WATCH
代表的就是在执行事务前观察变量是否发生了改变,如果变量改变了就将事务打断,所以在事务执行之前,也就是MULTI
之前,使用WATCH
)。同时,如果在执行命令过程中有语法错误,Redis 也会报错,整个事务也不会被执行,Redis 会忽略运行时发生的错误,不会影响到后面的执行。
在 Redis 中不存在悲观锁,事务处理要考虑到并发请求的情况,我们需要通过 WATCH+MULTI
的方式来实现乐观锁,如果监视的 KEY
没有发生变化则可以顺利执行事务,否则说明事务的安全性已经受到了破坏,服务器就会放弃执行这个事务,直接向客户端返回空回复nil
,事务执行失败后,我们可以重新进行尝试。
网友评论