Redis事务

redis 是单进程单线程的,客户端可以是多线程的,服务端采用队列将并发访问命令排队执行,因此单个命令是原子的。

一 事务

某一个客户端A的一批命令请求,进入服务端队列时中间可能会被穿插进客户端B的命令,因此客户端B的命令与A的命令可能会产生竞态条件。

 

如果希望原子的执行一批命令,可以使用Redis的事务。 

 

localhost:6379[1]> multi //标记以下N个命令(直到exec命令)是一个事务
OK
localhost:6379[1]> incrby count 5 //事务中的命令
QUEUED //添加到队列中,先不执行
localhost:6379[1]> get count//事务中的命令
QUEUED//添加到队列中,先不执行
localhost:6379[1]> exec //执行事务中所有命令,并依次返回每个命令的执行结果
1) (integer) 6
2) "6"

 

 multi命令告诉redis以下所有命令是一个事务,先缓存它们,直到接到exec命令再原子的执行,因此保证了所有命令要么都执行,要么都不执行(断网而后继命令未发给redis)。 

 

 

Redis没有类似于关系数据库的回滚功能,如事务中某有5个命令,其中一个命令出错,其它的也会执行完成。

 

localhost:6379> hmset person:1 name liying sex girl
OK
localhost:6379> multi
OK
localhost:6379> set index 1
QUEUED
localhost:6379> incr person:1 //命令错误
QUEUED
localhost:6379> incr index
QUEUED
localhost:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 2
localhost:6379> get index//虽然事务中incr person:1出错了,但index相关的命令还是被执行了。
"2"

 

 

 

二 Watch命令

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键

值)

 

如在redis中保存一个数值,数值范围 为1-100,当值达到100时再回到1. 

伪代码如下:

1.var val = setnx index 1//index不存在则设值为1
2.if(val ==0){//已经存在index了
3.val = get index //获取index值
4.if(val ==100){//
5.set index 1//值等于100了 -->设置值为1
6.}else{i
7.incr index//值小于100了--》增加1
8.}
9.}

 

 由于第3行到第5行不是原子执行的,所以在取得index值之后,可以index被其它的命令修改了,因此再把index置为1,可能就不正确了。 

为了保证第正确性,考虑使事务,在第3行和第5行加入事件,但事务的中的命令是批量执行,执行完再全部返回结果,中间不能获取index值,就不能判断是如何设置index值了。 

这种情况下使用watch命令

 

1.var val = setnx index 1
2.if(val ==0){//已经存在index了
3.watch index 
4.val = get index //获取index值
5.mutl
6.if(val ==100){//
7.set index 1//值等于100了 -->设置值为1
8.}else{i
9.incr index//值小于100了--》增加1
10.}
11.exec
12.}

 

 watch 会监控index的值,当index 有变化时,后面的事务就不执行了。

 

watch 之后事务不执行的示例:

localhost:6379> set index 1
OK
localhost:6379> watch index
OK
localhost:6379> multi
OK
localhost:6379> incrby index 10
QUEUED
localhost:6379> exec//在exec执行之间,在另一个客户端上修改了index值,使其事务不执行
(nill)
 wath 之后事务执行的示例:
localhost:6379>  set index 1
OK
localhost:6379> watch index
OK
localhost:6379> multi
OK
localhost:6379> incrby index 10
QUEUED
localhost:6379>  exec
1) (integer) 11
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值