redis事务

MULTI命令

跟其他的事务一样,redis事务可以保证同一个事务内的命令同时都执行或者都不执行【保证事务的原子性】。同时redis事务可以保证事务内的执行操作是连续的,中间不会插入执行其他命令(即,如果客户端A向redis服务发送包含命令1、命令2、命令3的事务,当A发送EXEC命令后,redis服务执行命令1,然后此时若客户端B向redis服务发送命令4,命令4不会插入到命令1、2、3间执行,命令1、2、3是依次连续执行的)。但是Redis事务不保证一致性,因此Redis事务的回滚操作需要客户端自己去是实现处理。
redis事务使用方式:

redis> MULTI                    //开始事务
redis> SADD setone 100          //事务内命令
redis> SADD settwo 200          //事务内命令
redis> EXEC                 //执行事务

redis会维护一个事务队列,将MULTI后的所有命令到放到事务队列中,当redis接收到EXEC命令后,会依次执行事务队列。
但是值得注意的是,不像其他关系数据库的事务,redis事务并没有回滚(rollback)功能【不保证一致性】,事务内命令出错后,需要客户端自己实现回滚操作,将数据库回复到事务执行前的状态。
若事务中有命令出错,redis会继续执行其他有效的命令【redis版本为3.0.6】,
如下示例:

[ojh@localhost redisTest]$ redis-server -v
Redis server v=3.0.6 sha=00000000:0 malloc=libc bits=64 build=df1dc433a1cb5ac8

//事务一
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a c
QUEUED
127.0.0.1:6379> set b a a       //语法错误,命令不存在或者参数数量不匹配
QUEUED
127.0.0.1:6379> set b c
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR syntax error
3) OK
//事务二
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a a
QUEUED
127.0.0.1:6379> SADD a 1    //运行错误
QUEUED
127.0.0.1:6379> set az za
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK

WATCH命令

若被WATCH命令监控的键在事务开始前被修改过(在本客户端连接或者其他客户端连接被修改过),在事务内再一次修改此键,则事务执行失败,事务内所有的命令都不会执行。

如:

127.0.0.1:6379> get b
"c"
127.0.0.1:6379> get a
"c"
127.0.0.1:6379> WATCH a
OK
127.0.0.1:6379> set a p         //在事务开始前修改了键a
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set b z
QUEUED
127.0.0.1:6379> set a k         //在事务中继续修改键 a
QUEUED
127.0.0.1:6379> set c qwert
QUEUED
127.0.0.1:6379> EXEC            //事务返回nil,不执行事务内命令
(nil)
127.0.0.1:6379> get c
(nil)
127.0.0.1:6379> get b
"q"
127.0.0.1:6379> get a
"p"

可以使用WATCH和MULTI命令来模拟实现incr命令的功能
伪代码如下:

String[] result= null;
while(result == null){          //事务执行失败,则进行重试
//模拟实现incr numKeu的功能,【redis(action),括号内action为redis命令】
WATCH numKey        //对键numKey进行监视
int num = redis(get numKey)
if (!num){
    num = 0;
}
num ++              //对原始值进行递增操作
redis(MULTI);           //开始事务,若在事务开始执行前(即本事务的EXEC命令执行前)其他客户端对numKey值进行了修改,则此事务内的命令不会执行,若在执行WATCH numKey命令和执行EXEC命令间numKey的值没有被其他事务或者其他客户端连接修改过,则事务执行成功,将递增后的值写会到numKey中。【执行EXEC、或者UNWATCH命令后,redis会取消本客户端连接对所有键的监控】
redis(set numKey num);          //将递增后的值写回到numKey中
result = redis(EXEC);           //执行事务
}
return result[0];

你可能感兴趣的:(Redis学习笔记)