redis(三)Redis的事务和锁机制

5 篇文章 0 订阅

redis(三)Redis的事务和锁机制

事务

Redis中的事务可以用来一次执行多条指令,并且有如下两个性质:

  • 事务是一个单独隔离的操作,事务中的所有命令都会被序列化,并顺序执行,事务在执行的过程中不会被其他客户端发送过来的命令请求所打断。
  • 事务是一个原子操作,要么全部执行,要么全都不执行(不管执行成功与否)。这与mysql中的有所区别。

相关命令:

命令作用
multi开启一个事务,并将之后的命令放到事务队列中 – 组队阶段
exec执行一个事务,按照顺序执行 – 执行阶段
discard取消事务的组队,中断multi命令

例如

127.0.0.1:6379> set grade 90
QUEUED
127.0.0.1:6379> incr grade
QUEUED
127.0.0.1:6379> incr grade
QUEUED
127.0.0.1:6379> get grade
QUEUED
127.0.0.1:6379> exec
1) OK
2) (integer) 91
3) (integer) 92
4) "92"

当客户端处于事务状态时,所有传入的正确命令都会被返回一个"queue"状态作为回复,当在exec命令执行时返回的是一个数组,数组中每个元素都是执行事务中命令所产生的返回值,先后顺序一致。

如果要中断事务的进行的话

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set number 20
QUEUED
127.0.0.1:6379> incr number
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI

直接使用discard命令就会将当前的multi的事务组队命令中断,后面的exec命令就不能执行成功了。

事务的出错机制

Redis中事务的出错的处理方式和mysql中的事务出错处理方式不同,不会采用回滚的方式进行处理。一般redis事务中有如下两种错误:

  1. 在multi组队阶段命令出错,此时的错误是因为组队的命令语法错误,或者内存不足等造成的。

    对于这种错误redis会直接中断事务的组队,相当于discard命令。

  2. 在exec阶段命令出错,这种一般都是用法错误,只有在执行期间才会被法相。

    对于这种错误的出现redis不会回滚整个事务,只是会跳过这条出错命令,继续执行所有的命令。

锁机制

事务冲突问题:

当有多个客户端同时操作同一个数据的时候,可能就会导致数据不一致,不合法的问题。例如(例子来自官网)

val = GET mykey
val = val + 1
SET mykey $val

对于上述操作,如果有两个客户端同时获取到了mykey的值为10,执行完毕之后mykey的值只会变成11而不会变成正确的12。

这种并发问题可以用两种锁来解决

乐观锁(check-and-set CSA)

通过给数据加上版本号标志位的方式,在操作之前不会给数据加上锁,如果数据修改了就更新当前数据的版本号。在每次修改之前都会判断自己的版本号和数据的版本号是否一致,如果不一致则不能进行修改,一致则允许对数据进行修改。

Redis使用了watch命令来便捷的实现乐观锁。

在执行multi之前,可以用watch key1 … keyxx命令来对多个key进行监视,如果在事务执行之前key被改动了,则事务不能被执行。

客户端1:

localhost:6379> watch money
localhost:6379> multi
localhost:6379>incrby money 10					# 给money+10
localhost:6379>exec
# 执行结果假设money = 110

客户端2:

localhost:6379> watch money
localhost:6379> multi
localhost:6379>incrby money 20					# 给money+20
localhost:6379>exec
(nil)											

这里的nil表示执行结果为空,执行失败,因为使用watch会将数据加上乐观锁,客户端1改了数据了版本号就会变。

对于键的监视从watch命令到exec命令执行之前生效,当exec命令执行之后,不管事务执行成功与否,对所有键的监视都会消失。另外,客户端断开连接之后,该客户端对键的监视也会消失。

同时可以使用unwatch命令手动取消监视。

乐观锁可以提供吞吐量,例如用在抢票场景中。

悲观锁

在每次有一个客户端拿到数据的时候都会给数据加锁,有其他的客户端要读取该数据的时候就会阻塞到锁被释放。类似于很多数据库中行锁表锁读锁写锁,在操作之前先加上锁。

效率比较低

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值