IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 深入理解redis之事务与乐观锁的实现 -> 正文阅读

[大数据]深入理解redis之事务与乐观锁的实现

事务:要么同时成功,要么同时失败。

事务的特性:

  • 一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行。且不会被其他事务所打断。
  • 一组事务中的所有操作,要么全部被执行,要么全部不执行。

redis单条命令保证原子性,但不保证事务原子性。

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接执行,只有发起执行命令的时候才会执行!

redis的事务流程:

  • 开启事务( )
  • 命令入队( )
  • 执行事务( )

multi:开启事务:进入事务状态,之后输入的所有命令都会被放入队列中,但暂时都不会被执行。

exec:执行事务:触发并执行事务中的所有命令。

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)> get k1 
QUEUED
127.0.0.1:6379(TX)> set k3 v3 
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) "v1"
4) OK
事务中出错的两种情况

对于发生在 EXEC 执行之前的错误,客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回 QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,那么大部分客户端都会停止并取消这个事务。

不过,从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务。

至于那些在 EXEC 命令执行之后所产生的错误, 并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。

  1. 如果程序出错,是由于编译问题(语法错误) 则事务中的其他命令都不会执行
#编译问题
127.0.0.1:6379> flushdb
OK
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)> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k2
(nil)

(error) EXECABORT Transaction discarded because of previous errors表示事务被取消

  1. 如果程序出错,是由于运行时的问题(比如get一个不存在的值、给不存在的key的值执行自增操作),则事务中的其他命令会正常执行。
#运行时出错
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 "v1"
QUEUED
127.0.0.1:6379(TX)> incr k1 
QUEUE
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2 
"v2"
127.0.0.1:6379> get k3
"v3"

? 简单来说,如同过安检的人一样一个接着一个排队过安检,而安检只检查你看起来像不像一个坏人,如果从开始安检的所有人里面有一个看起来像坏人,那么刚才案件的所有人都不能进站。如果安检的时候没发现有坏人,但是进站之后坏人开始做坏事被发现了,可是和坏人一起进站的其他人已经进站了,没办法再让他们出去了,于是只能让坏人一个人出去。

redis不支持回滚

redis官方文档给出了一下两点原因:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

redis认为这是程序员应该避免的事情,而不应该由redis的开发者承担这份责任,况且大多数情况下回滚也无法挽回错误。正是因为不需要支持回滚,redis才能保持高效。

ie:不该我干的事情我一分钱也不会干,我只负责保持高效。

放弃事务:discard

执行此命令后,事务将被放弃,队列将被清空,且将会从事务状态中退出

127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> multi 
OK
127.0.0.1:6379(TX)> set k4 v4 
QUEUED
127.0.0.1:6379(TX)> get v4
QUEUED
127.0.0.1:6379(TX)> discard
OK
127.0.0.1:6379> get k4
(nil)

实现乐观锁:

? watch命令可以为redis事务提供乐观锁行为。

? 如果只有一个客户端对redis-server进行操作的情况下,那么无论我们做什么操作基本都能够保证操作的正确性,但如果有若个客户端一起对redis-server发起操作请求,那么就有可能会出现资源的争夺问题。

? 举个简单的例子来说,假设key1对应的值为10,现在两个程序同时执行如下程序:

multi
var = get key1
var = var + 1 
set key1 $val

? 如果碰巧两个程序在同一时刻执行了get key1的命令,那么他们所读取到到的值都是10,然后分别对10+1的到11,然后又将11 set 给了key1 ,这样key1最终的值将会是11,而不是正确的12。

所以我们要做的就是派一个人来替我们监视key1的值有没有发生变化。

watch命令就是这个人

我们首先执行命令watch key1,让key1处于被监视的状态,然后我们执行multi命令开启一个事务,在我们执行exec命令执行此事务之前,一旦发现key1的值发生了任何改变,那么我们当前的事务会立即取消,然后进行不断的尝试,知道成功执行当前的事务为止。

  • watch可以多次被执行,对键的监视从watch命令执行开始,到exec命令执行结束
  • 用户还可以在单个watch命令中监视任意多个键,比如:
watch key1 key2 key3
ok

用户还可以使用无参数的unwatch命令取消对所有键的监视。

watch何时被取消?

  1. 调用exec命令后,不管是否执行成功,对键的监视都会被取消
  2. 客户端断开连接,对键的监视也会被取消
  3. 使用unwatch命令手动取消

参考:redis官方文档

若有不足之处,还请指正

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:44:36  更:2021-09-22 14:46:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:56:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码