【Redis】事务和锁机制

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【Redis】事务和锁机制,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、事务的基本操作

1、redis中事务的概念不同于Mysql数据库中的事务
它是一个单独的隔离操作:事务中所有的命令都会序列化、按照顺序依次执行
事务在执行的过程中,不会被其他客户端发送的命令请求打断

Redis事务的主要作用:串联多个命令防止别的命令插队

2、基本命令Multi、Exec、discard

  • Multi:组队命令,将命令依次放入队列中,但是不会执行
  • Exec:执行,redis将之前命令队列中的命令依次执行
  • discard:放弃,可以在组队过程中使用discard放弃组队
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) "v1"
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> discard
OK
127.0.0.1:6379>
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
(nil)
127.0.0.1:6379>

3、事务的错误处理

  • 场景一:使用multi过程中,出现错误,执行时整个队列的命令都会被取消
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)>
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379>
  • 场景二:命令组队过程中没有出错,但是使用exec执行的过程中出错,那么只有出错的命令不会被执行,其他的命令正常执行
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 value1
QUEUED
# 这里key1的value值不是数字,所以执行自增会报错
127.0.0.1:6379(TX)> incr key1
QUEUED
127.0.0.1:6379(TX)> set key2 value2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379>
127.0.0.1:6379> get key2
"value2"
127.0.0.1:6379>

二、事务冲突(悲观锁和乐观锁)

1、悲观锁
悲观锁在操作数据时比较悲观,认为别人会同时修改数据。 因此操作数据时直接把数据锁住,直到操作完成后才会释放锁,上锁期间其他人不能修改数据,从而使这个数据处于一个block的状态

例如Mysql中的行锁与表锁等

2、乐观锁
乐观锁在操作数据时认为别人不会同时修改数据,所以不会对数据进行上锁

但是在更新数据时,会去判断在此期间是否有人修改过此数据,如果有人修改那就放弃更新,可以将这个过程理解为check-and-set

乐观锁大多是基于数据版本( Version )记录机制实现

3、乐观锁演示
在执行事务之前,我们可以使用watch key [key..]命令对可能同时被两个客户端修改的数据做一个监视,如果事务执行之前,这个key的值被修改,那么事务将被打断

执行unwatch取消对所有key的监视

客户端A

127.0.0.1:6379>
127.0.0.1:6379> set price 100
OK
127.0.0.1:6379> watch price
OK
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incrby price 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 120
127.0.0.1:6379>
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379>

客户端B

127.0.0.1:6379> keys *
1) "price"
127.0.0.1:6379>
127.0.0.1:6379> watch price
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)>
127.0.0.1:6379(TX)> incrby price 10
QUEUED
127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379>

可以看到,客户端A对price这个key做了修改,所以客户端B在执行事务时,发现数据被修改了,无法成功执行

三、redis事务特性

1、单独的隔离操作

  • 事务中的所有命令都会序列化、按照顺序依次执行
  • 事务在执行过程中,不会被其他客户端发送的命令请求所打断

2、没有隔离级别的概念

  • 队列中的命令,在提交之前都不会实际被执行

3、不保证原子性

  • 事务执行过程中,如果有一条命令执行失败,其他命令仍然继续执行,不会回滚

如有错误,欢迎指正!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136734.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!