Redis和MySQL一样,也支持简单的事物,并且redis还可以对key进行加锁,防止同时对某一key操作而导致数据错误
二、 redis事物模拟:
1、 正确执行的事物
127.0.0.1:6379> set ticket 10 #设置初始值 OK 127.0.0.1:6379> set money 500 #设置初始值 OK 127.0.0.1:6379> multi #事物开始 OK 127.0.0.1:6379> decr ticket #命令操作,ticket减1 QUEUED # 加入队列 127.0.0.1:6379> decrby money 100 #命令操作,money减100 QUEUED # 加入队列 127.0.0.1:6379> exec # 执行事物,保证原子性 1) (integer) 9 2) (integer) 400
2、 事物执行过程中,若语句出现语法错误,则事物操作失败
127.0.0.1:6379> mget ticket money 1) "9" 2) "400" 127.0.0.1:6379> multi OK 127.0.0.1:6379> decr ticket QUEUED 127.0.0.1:6379> wrong-conmmand # 错误的命令 (error) ERR unknown command 'wrong-conmmand' 127.0.0.1:6379> decrby money 100 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. # 事物取消 127.0.0.1:6379> mget ticket money 1) "9" # 结果不变 2) "400"
3、如果事物中的语句没有语法错误,但是有不适当的语句,比如与事物不相关的语句,exec之后,会执行正确的语句,并跳过有不适当的语句.
127.0.0.1:6379> multi OK 127.0.0.1:6379> decr ticket QUEUED 127.0.0.1:6379> lpush tmp_list 123 # 语法没有错 QUEUED # 正常加入队列 127.0.0.1:6379> exec 1) (integer) 8 2) (integer) 1 127.0.0.1:6379> mget ticket money 1) "8" # 执行后对原有结果有影响 2) "400"
三、Redis的事物锁机制
当Redis事物语句中操作了一个key的值,在exec之前,如果有其他原因导致该key的值改变就会引起数据不同步或其他错误(如秒杀导致商品数量为负数),对于这种问题,Redis提供了锁机制(watch),Redis事物中启用的是乐观锁,只负责检测key的值有没有被改动
redis 127.0.0.1:6379> watch ticket # 对ticket进行监控 OK redis 127.0.0.1:6379> multi OK redis 127.0.0.1:6379> decr ticket QUEUED redis 127.0.0.1:6379> decrby money 100 QUEUED redis 127.0.0.1:6379> exec # 执行前我们启动了另一个终端,并且改变了ticket的值 (nil) # 返回nil,说明监视的ticket已经改变了,事务就取消了.