一.Redis自带事务机制
Redis事务通过MULTI 、 EXEC 、 DISCARD 、WATCH和UNWATCH命令操作,过程如下:
通过MULTI 开启事务,然后添加任意条命令到队列,通过EXEC 执行队列命令,通过DISCARD 放弃事务,通过WATCH提供锁机制,通过UNWATCH取消对key的监控。
例1:普通用法
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr aaa
QUEUED
127.0.0.1:6379> incr bbb
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
例2:放弃事务
127.0.0.1:6379> set aaa 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr aaa
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get aaa
"1"
例3:WATCH锁机制(如下,如果被监控的key在exec前被修改了,则事务失败)
127.0.0.1:6379> watch aaa
OK
127.0.0.1:6379> set aaa 100
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set aaa 200
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get aaa
"100"
例4:Redis会忽略入队失败的命令或错误的命令
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr b
QUEUED
127.0.0.1:6379> set c 1 2
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (error) ERR syntax error
127.0.0.1:6379> get b
"1"
127.0.0.1:6379> get c
(nil)
如上可见,Redis为了保证高效和快速并不支持回滚(rollback),但提供了脚本实现事务
。
二.使用Lua脚本实现事务
Redis可调用Lua解析器去运行脚本,Redis会保证脚本以原子性方式运行,执行多条命令还可减少网络开销,但是执行运行时间很长脚本可不是什么好主意。
通过EVAL命令去执行Lua脚本,通过redis.call()函数来调用redis命令。(详情见redis文档)
例1:eval和redis.call使用
127.0.0.1:6379> eval "return redis.call('set',KEYS[1],'bar')" 1 foo
OK
127.0.0.1:6379> get foo
"bar"