redis> multi
OK
redis> get a
QUEUED
redis> get b
QUEUED
redis> exec
1. "1"
2. "1"
发现问题了吧。假如我们想用事务实现incr操作怎么办?可以这样做吗?
redis> get a
"1"
redis> multi
OK
redis> set a 2
QUEUED
redis> exec
1. OK
redis> get a,
"2"
结论很明显这样是不行的。这样和 get a 然后直接set a是没区别的。很明显由于get a 和set a并不能保证两个命令是连续执行的(get操作不在事务上下文中)。很可能有两个client同时做这个操作。结果我们期望是加两次a从原来的1变成3. 但是很有可能两个client的get a,取到都是1,造成最终加两次结果却是2。主要问题我们没有对共享资源a的访问进行任何的同步
也就是说redis没提供任何的加锁机制来同步对a的访问。
还好redis 2.1后添加了watch命令,可以用来实现乐观锁。看个正确实现incr命令的例子,只是在前面加了watch a
redis> watch a
OK
redis> get a
"1"
redis> multi
OK
redis> set a 2
QUEUED
redis> exec
1. OK
redis> get a,
"2"
redis> set a 5
OK
redis> lpush b 5
(integer) 1
redis> set c 5
OK
redis> multi
OK
redis> incr a
QUEUED
redis> incr b
QUEUED
redis> incr c
QUEUED
redis> exec
1. (integer) 6
2. (error) ERR Operation against a key holding the wrong kind of value
3. (integer) 6