redis事务

来源:互联网 发布:网络机房整改方案 编辑:程序博客网 时间:2024/06/05 21:11

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 -vRedis server v=3.0.6 sha=00000000:0 malloc=libc bits=64 build=df1dc433a1cb5ac8//事务一127.0.0.1:6379> MULTIOK127.0.0.1:6379> set a cQUEUED127.0.0.1:6379> set b a a       //语法错误,命令不存在或者参数数量不匹配QUEUED127.0.0.1:6379> set b cQUEUED127.0.0.1:6379> EXEC1) OK2) (error) ERR syntax error3) OK//事务二127.0.0.1:6379> MULTIOK127.0.0.1:6379> set a aQUEUED127.0.0.1:6379> SADD a 1    //运行错误QUEUED127.0.0.1:6379> set az zaQUEUED127.0.0.1:6379> EXEC1) OK2) (error) WRONGTYPE Operation against a key holding the wrong kind of value3) 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 aOK127.0.0.1:6379> set a p         //在事务开始前修改了键aOK127.0.0.1:6379> MULTIOK127.0.0.1:6379> set b zQUEUED127.0.0.1:6379> set a k         //在事务中继续修改键 aQUEUED127.0.0.1:6379> set c qwertQUEUED127.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];
0 0