Redis中的事务(二)

news2025/1/13 15:34:46

事务

事务的实现

执行事务

当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行,服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。

例子

在这里插入图片描述

  • 举个例子。对于如图所示的事务队列来说,服务器会先执行命令:
SET "name" "Practical Common Lisp"

之后执行命令:

GET "name"

在之后执行命令:

GET "author"

最后,服务器会将执行这四个命令所得的回复返回给客户端:

127.0.0.1:6379> EXEC
1) OK
2) "Practical Common Lisp"
3) OK
4) "Peter Seibel"
EXEC命令的实现原理

可以用以下伪代码来描述:

def EXEC():
# 创建空白的回复队列
reply_queue =[]
# 遍历事务队列中的每个项
# 读取命令的参数,参数的个数,以及要执行的命令
for argv, argc, cmd in client.mstate.commands:
# 执行命令,并取得命令的返回值
reply = execute_command(cmd, argv, argc)

# 将返回值追加到回复队列末尾
reply_queue.append(reply)

# 移除REDIS_MULTI标识,让客户端回到非事务状态
client.flags &= ~REDIS_MULTI

# 清空客户端的事务状态,包括:
# 1.清零入队命令计数器
# 2.释放事务队列
client.mstate.count = 0
release_transaction_queue(client.mstate.commands)

# 将事务的执行结果返回给客户端
send_reply_to_client(client, reply_queue)

WATCH命令的实现

WATCH命令是一个乐观锁(optimistic locking),它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

例子

  • 举个例子。
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> WATCH "name"
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET "name" "vinpink"
QUEUED
127.0.0.1:6379> EXEC
(nil)

如表展示了上述的事务是如何失败的。在时间T4,客户端B修改了"name"键的值,当客户端A在T5执行EXEC命令时,服务器会发现WATCH监视的键"name"已经被修改,因此服务器拒绝执行客户端A的事务,并向客户端A返回空回复
在这里插入图片描述

使用WATCH命令监视数据库键。

在这里插入图片描述

每个Redis数据库都保存着一个watched_keys字典,这个字典的键是某个被WATCH命令监视的数据库键,而字典的值则是一个链表,链表中记录了所有监视相应数据库键的客户端:

typedef struct redisDb {
// ...

// 正在被WATCH命令监视的键
dict *watched_keys;

// ...
}redisDb;

通过watched_keys字典,服务器可以清楚地知道哪些数据库键正在被监视,以及哪些客户端正在监视这些数据库键。

  • 1.客户端c1和c2正在监视键"name"
  • 2.客户端c3正在监视键"age"
  • 3.客户端c2和c4正在监视键"address"
    通过执行WATCH命令,客户端可以在watched_keys字典中与被监视的键进行关联
例子
  • 举个例子。如果当前客户端为c10086,那么客户端执行以下WATCH命令之后:
redis>WATCH "name" "age"
OK

上图展示的wathced_keys字典将被更新为如图所示的状态,其中用虚线包围的两个c10086节点就是由刚刚执行的WATCH命令添加到字典中的。
在这里插入图片描述

监视机制的触发

所有对数据库进行修改的命令,比如SET、LPUSH、SADD、ZREM、DEL、FLUSHDB等等,在执行之后都会调用multi.c/touchWatchKey
函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有的话,那么touchWatchKey函数
会将监视被修改键的客户端的REDIS_DIRTY_CAS标识打开,标识客户端的事务安全性已经被破坏。touchWatchKey函数的定义额可以用以下伪代码来描述

def touchWatchKey(db, key) :
# 如果键key存在于数据库的watched_keys字典中
# 那么说明至少有一个客户端在监视这个key
if key in db.watched_keys:
# 遍历所有监视键key的客户端
for client in db.watched_keys[key]:
# 打开标识
client.flags |= REDIS_DIRTY_CAS
例子
  • 举个例子。如图所示的watched_keys字典来说:
    1.如果键"name"被修改,那么c1、c2、c10086三个客户端的REDIS_DIRTY_CAS标识将被打开
    2.如果键"age"被修改,那么c3和c10086两个客户端的REDIS_DIRTY_CAS标识将被打开
    3.如果键"address"被修改,那么c2和c4两个客户端的REDIS_DIRTY_CAS标识将被打开
    在这里插入图片描述

判断事务是否安全

当服务器接收到一个客户端发来的EXEC命令时,服务器会根据这个客户端是否打开了REDIS_DIRTY_CAS标识
来决定是否执行事务:

  • 1.入股客户端的REDIS_DIRTY_CAS标识已经被打开,那么说明客户端所监视的键当中,至少有一个键已经被修改过了,在这种情况下,客户端提交的事务已经不再安全,所以服务器会拒绝执行客户端提交的事务
  • 2.如果客户端的REDIS_DIRTY_CAS标识没有被打开,那么说明客户端监视的所有键都没有被修改过(或者客户端没有监视任何键),事务仍然是安全的,服务器将执行客户端提交的这个事务。

这个判断是否执行事务的过程可以用流程图来描述
在这里插入图片描述

例子
  • 举个例子。对于上图的watched_keys字典来说,如果某个客户端对"name"进行了修改(比如执行SET “name” “cover”),
    那么c1、c2、c10086三个客户端的REDIS_DIRTY_CAS标识将被打开,当这三个客户端向服务器发送EXEC命令的时候,
    服务器会拒绝执行它们提交的事务,以此来保证事务的安全性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3、MYSQL-一条sql如何在MYSQL中执行的

MySQL的内部组件结构 大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 Server层 主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函…

MIMO(多天线)通信的四种译码算法

目录 一. 介绍 二. 极大似然译码 三. 破零译码算法 四. 最小均方误差算法 五. 球形译码 一. 介绍 发射天线数记为Mt,接收天线数记为Mr。由此发射信号x为向量: 接受信号y为向量: 信道H为矩阵: 利用n代表噪声向量,…

【若依前后端分离】温湿度仪表盘

示例&#xff1a; 代码&#xff1a; TemperatureAndHumidity.vue组件 //温湿度仪表盘 <template><div><!-- 在这里放置你的图表组件 --><div ref"echarts" style"width: 100%; height: 400px;"></div></div> </t…

【C++干货基地】面向对象核心概念 const成员函数 | 初始化列表 | explicit关键字 | 取地址重载

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

数据结构PT1——线性表/链表

1&#xff1a;顺序存储实现(数组实现) Data&#xff1a; a1 a2 .....ai ai1 .... an .... typedef struct LNode *List; //指向LNode的指针&#xff0c;这是typedef的&#xff0c;你可以随时声明&#xff0c;而不加typedef只是创建一个 struct LNode{ //结构体成员ElementT…

Sentinel 流控注解使用

大概原理&#xff1a;通过反射解析注解 SentinelResource信息完成调用&#xff0c;处理方法&#xff0c;类似AOP编程 处理方法的返回类型要保持一致&#xff0c;参数和顺序保持一致&#xff0c; 可以在参数列表最后加 com.alibaba.csp.sentinel.slots.block.BlockException; …

【leetcode面试经典150题】62. K 个一组翻转链表(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

OpenHarmony音视频—opus

简介 Opus是一种用于在互联网上进行交互式语音和音频传输的编解码器。它可以从低比特率窄带语音扩展到非常高的高品质立体声音乐。 下载安装 直接在OpenHarmony-SIG仓中搜索opus并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 将下载的opus库代码存在以下路径&a…

视觉slam14讲-大纲-持续更新

视觉slam入门太难 数学理论编程知识计算机视觉知识 缺一不可&#xff0c;大家一起加油

ACL的基本配置

已经启用&#xff52;&#xff49;&#xff50;实现了全网可达。 这时我们要拒绝R1与R4的路由通信&#xff0c;做标准ACL过滤关注源IP需要尽量靠近目标。则在R4的物理接口G0/0/1的&#xff49;&#xff4e;接口上做&#xff0c;不能在R4的环回接口上做&#xff0c;因为ACL列表…

网络管理和文件传输的工具推荐

在Hadoop及以后的相关学习中 我给大家推荐两款好用的软件 Xshell和Xftp是两款常用于网络管理和文件传输的工具。 首先&#xff0c;让我来介绍一下Xshell。Xshell是一款功能强大的SSH&#xff08;Secure Shell&#xff09;客户端&#xff0c;它允许用户通过安全加密的方式远程…

【web网页制作】html+css旅游家乡山西主题网页制作(3页面)【附源码】

山西旅游网页目录 涉及知识写在前面一、网页主题二、网页效果Page1、景点介绍Page2、酒店精选|出行攻略Page3、景色欣赏 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 四、网页源码4.1 主页模块源码4.2 源码获取方式 作者寄语 涉及知识 山西旅游主题网页制作&am…

idea显示maven或者gradle无法从仓库获取到项目中的jar包,jar包所在仓库无法访问解决方法,百试百灵

**idea显示maven或者gradle无法从仓库获取到项目中的jar包&#xff0c;jar包所在仓库无法访问解决方法&#xff0c;百试百灵** 直接上图&#xff0c;大概的故障问题就是&#xff1a;idea导入新的项目&#xff0c;因为项目中很多的jar需要从远程仓库下载&#xff0c;但是远程仓库…

跟着Carl大佬学leetcode之844 比较含退格的字符串

来点强调&#xff0c;刷题是按照代码随想录的顺序进行的&#xff0c;链接如下https://www.programmercarl.com/本系列是记录一些刷题心得和学习过程&#xff0c;就看到题目自己先上手试试&#xff0c;然后看程序员Carl大佬的解释&#xff0c;自己再敲一遍修修补补&#xff0c;练…

IDM的实用功能介绍+下载地址

下载地址 &#xff1a; 下载到idm 互联网下载管理器&#xff08;IDM&#xff09;实用功能概述 1. 多线程下载 IDM使用多线程技术&#xff0c;将文件分割成多个部分同时下载&#xff0c;显著提高下载速度。 2. 计划任务 用户可以设定下载任务的开始时间&#xff0c;甚至在特…

SSDReporter for Mac:全面检测SSD健康,预防数据丢失,让您的Mac运行更稳定

SSDReporter for Mac是一款专为Mac用户设计的固态硬盘&#xff08;SSD&#xff09;健康状况检测工具&#xff0c;旨在帮助用户全面了解并监控其Mac设备中SSD的工作状态&#xff0c;从而确保数据的完整性和设备的稳定性。 这款软件具有多种强大的功能。首先&#xff0c;它能够定…

DevOps流程的简单总结

DevOps流程图&#xff1a; DevOps流程包含&#xff1a;计划&#xff08;plan&#xff09;、编码(code)、编译(build)、测试(test)、发布(release)、部署(deploy)、运营(operate)、监控&#xff08;monitor&#xff09;&#xff0c;这是一个循环的过程。DevOps是依托容器、自动化…

数据赋能(62)——要求:数据管理部门能力

“要求&#xff1a;数据管理部门能力”是作为标准的参考内容编写的。 在实施数据赋能中&#xff0c;数据管理部门的能力体现在多个方面&#xff0c;关键能力如下图所示。 在实施数据赋能的过程中&#xff0c;数据管理部门应具备的关键能力如下。 数据治理与标准化能力 数据管…

python爬虫-----深入了解 requests 库(第二十五天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

C#控制台相关方法

控制台相关方法 文章目录 控制台输入1、清空2、设置控制台3、设置光标位置&#xff0c;1y 2x4、设置颜色相关5、光标显隐6、关闭控制台思考 移动方块 控制台输入 //如果ReadKey(true)不会把输入的内容显示再控制台上 char c Console.ReadKey(true).KeyChar;1、清空 ​ Cons…