Redis(三) 事务与发布订阅

结合前两期 Redis(一) Redis简介(Redis(一) Redis简介-CSDN博客) Redis(二) 可编程性(Redis(二) 可编程性-CSDN博客)

目录

事务在 Redis 中的运作方式

用法 

事务中的错误

回滚

放弃命令队列

使用检查和设置的乐观锁定

WATCH解释 

使用 WATCH 实现 ZPOP

Redis 发布/订阅 

推送消息的格式

有线协议示例

模式匹配订阅

与模式和频道订阅匹配的消息 

模式匹配的订阅计数的含义

分片发布/订阅


事务在 Redis 中的运作方式

Redis 事务允许执行一组命令 在一个步骤中,它们以 MULTI、EXEC、DISCARD 和 WATCH 命令为中心。 Redis 事务提供两个重要保证:

  • 事务中的所有命令都经过序列化和执行 顺序。其他客户端发送的请求永远不会 在 Redis 事务执行过程中提供服务。 这保证了命令作为单个命令执行 隔离操作。

  • EXEC 命令 触发事务中所有命令的执行,因此 如果客户端在上下文中失去与服务器的连接 调用 EXEC 命令前的事务,无任何操作 ,相反,如果调用 EXEC 命令,则所有 执行操作。使用仅追加文件时,Redis 确保 使用单个 write(2) 系统调用将事务写入磁盘。 但是,如果 Redis 服务器崩溃或被系统管理员杀死 以某种困难的方式,可能只有部分操作 已注册。Redis 将在重新启动时检测到此情况,并退出并显示错误。 使用该工具可以修复 仅附加将删除部分事务的文件,以便 服务器可以重新启动。redis-check-aof   

从版本 2.2 开始,Redis 允许对 在两个以上,以一种非常类似于 检查和设置 (CAS) 操作。 

用法 

使用 MULTI 命令输入 Redis 事务。命令 总是回复 .此时,用户可以发出多个 命令。Redis 不会执行这些命令,而是会排队 他们。调用 EXEC 后,将执行所有命令。OK

改为调用 DISCARD 将刷新事务队列并退出 交易。

以下示例以原子方式递增键。foobar

> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

从上面的会话中可以清楚地看出,EXEC 返回一个 回复数组,其中每个元素都是单个命令的回复 在事务中,命令的发出顺序相同。

当 Redis 连接位于 MULTI 请求的上下文中时, 所有命令都将回复字符串(作为状态回复发送 从Redis协议的角度来看)。排队的命令是 只需在调用 EXEC 时安排执行。QUEUED

事务中的错误

在事务过程中,可能会遇到两种命令错误:

  • 命令可能无法排队,因此在调用 EXEC 之前可能会出现错误。 例如,命令可能在语法上是错误的(参数数量错误, 错误的命令名称,...),或者可能存在一些关键情况,例如 内存条件(如果使用指令将服务器配置为具有内存限制)。maxmemory
  • 调用 EXEC 后,命令可能会失败,例如,由于我们执行了 对具有错误值的键的操作(例如针对字符串值调用列表操作)。

从 Redis 2.6.5 开始,服务器会在命令累积过程中检测到错误。 然后,它将拒绝执行事务,并在 EXEC 期间返回错误,从而丢弃事务。

在 Redis 2.6.5 之前,客户端需要通过检查来检测 EXEC 之前发生的错误 queued 命令的返回值:如果命令回复 QUEUED,则为 正确排队,否则 Redis 返回错误。 如果在对命令进行排队时出现错误,则大多数客户端 将中止并放弃事务。否则,如果客户选择继续交易 EXEC 命令将执行所有成功排队的命令,而不考虑以前的错误。

EXEC 之后发生的错误不会以特殊方式处理: 即使某些命令在事务期间失败,也会执行所有其他命令。

这在协议级别上更为明确。在以下示例中,一个 即使语法正确,命令在执行时也会失败:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
MULTI
+OK
SET a abc
+QUEUED
LPOP a
+QUEUED
EXEC
*2
+OK
-WRONGTYPE Operation against a key holding the wrong kind of value

EXEC 返回了两个元素的批量字符串回复,其中一个是代码和 另一个是错误回复。由客户端库来查找 向用户提供错误的明智方式。OK

需要注意的是,即使命令失败,队列中的所有其他命令也会被处理——Redis 不会停止 命令的处理。

另一个示例,再次使用 wire 协议和 ,显示了如何 语法错误会尽快报告:telnet

MULTI
+OK
INCR a b c
-ERR wrong number of arguments for 'incr' command

这一次,由于语法错误,错误的 INCR 命令未排队 完全。

回滚

Redis 不支持事务回滚,因为支持回滚 将对 Redis 的简单性和性能产生重大影响。

放弃命令队列

DISCARD 可用于中止事务。在这种情况下,不可以 执行命令并将连接状态恢复到 正常。

> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"

使用检查和设置的乐观锁定

WATCH 用于向 Redis 提供检查和设置 (CAS) 行为 交易。

监视 WATCHed 密钥,以检测针对它们的更改。如果 在 EXEC 命令之前,至少修改了一个监视密钥, 整个事务中止,EXEC 返回 Null 回复以通知 事务失败。

例如,假设我们需要以原子方式递增值 键的 1(假设 Redis 没有 INCR)。

第一次尝试可能如下:

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

只有当我们有一个客户端执行 在给定时间内操作。如果多个客户端尝试递增密钥 大约在同一时间,将有一个竞争条件。例如 客户端 A 和 B 将读取旧值,例如 10。该值将 由两个客户端递增到 11,最后 SET 作为值 的键。因此,最终值将是 11 而不是 12。

多亏了 WATCH,我们才能很好地对问题进行建模:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

 使用上面的代码,如果存在竞争条件和另一个客户端 修改 in 我们调用 WATCH 和 我们对 EXEC 的调用,事务将失败。val

我们只需要重复操作,希望这次我们不会得到 新种族。这种锁定形式称为乐观锁定。 在许多用例中,多个客户端将访问不同的密钥, 因此,不太可能发生碰撞 - 通常无需重复操作。

WATCH解释 

那么WATCH到底是什么呢?这是一个命令,将 使 EXEC 有条件:我们要求 Redis 执行 仅当 WATCHed 密钥均未修改时,才进行交易。这包括 客户端所做的修改,如写入命令,以及 Redis 本身, 比如过期或驱逐。如果在监视和接收 EXEC 之间修改了密钥,则整个事务将被中止 相反。

注意:

  • 在 6.0.9 之前的 Redis 版本中,过期的密钥不会导致事务 要中止。
  • 事务中的命令不会触发 WATCH 条件,因为它们 仅在发送 EXEC 之前排队。

WATCH可以多次调用。简单地说,所有的 WATCH 调用都会 从通话开始,可以监视变化的效果,直到 调用 EXEC 的那一刻。您还可以将任意数量的密钥发送到 单次观看通话。

调用 EXEC 时,无论是否 事务是否中止。此外,当客户端连接是 关闭,一切都变得 UNWATCHed。

也可以使用 UNWATCH 命令(不带参数) 为了刷新所有监视的键。有时这很有用,因为我们 乐观地锁定几个键,因为可能需要执行 事务来更改这些键,但在读取当前内容后 我们不想继续的键。发生这种情况时,我们只需调用 UNWATCH,以便该连接已经可以自由地用于新的 交易。

使用 WATCH 实现 ZPOP

一个很好的例子来说明如何使用 WATCH 来创建新的 否则 Redis 不支持的原子操作是实现 ZPOP (仅添加了 ZPOPMIN、ZPOPMAX 及其阻塞变体 在 5.0 版中),这是一个弹出元素的命令,具有较低的 以原子方式从排序集得分。这是最简单的 实现:

WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC

如果 EXEC 失败(即返回 Null 回复),我们只需重复该操作。 

Redis 发布/订阅 

SUBSCRIBE、UNSUBSCRIBE 和 PUBLISH 实现了发布/订阅消息传递范式,其中(引用维基百科)发送者(发布者)没有被编程为将其消息发送给特定的接收者(订阅者)。 相反,已发布的消息被定性为频道,而不知道可能有哪些(如果有的话)订阅者。 订阅者对一个或多个频道表示兴趣,并且只收到感兴趣的消息,而不知道有哪些(如果有)发布者。 发布者和订阅者的这种解耦允许更大的可伸缩性和更动态的网络拓扑。

例如,要订阅频道“channel11”和“ch:00”,客户端会发出 SUBSCRIBE,提供频道名称:

SUBSCRIBE channel11 ch:00

其他客户端发送到这些通道的消息将由 Redis 推送到所有订阅的客户端。 订阅者按照消息的发布顺序接收消息。

订阅一个或多个频道的客户端不应发出命令,尽管它可以对其他频道进行 SUBSCRIBE 和取消订阅。 对订阅和取消订阅操作的回复以消息的形式发送,以便客户端可以只读取连贯的消息流,其中第一个元素指示消息类型。 在订阅的 RESP2 客户端的上下文中允许的命令包括:

  • PING
  • PSUBSCRIBE
  • PUNSUBSCRIBE
  • QUIT
  • RESET
  • SSUBSCRIBE
  • SUBSCRIBE
  • SUNSUBSCRIBE
  • UNSUBSCRIBE

但是,如果使用 RESP3(请参阅 HELLO),则客户端可以在订阅状态下发出任何命令。

请注意,在订阅模式下使用 时,不能使用 UNSUBSCRIBE 和 PUNSUBSCRIBE 等命令,因为不接受任何命令,只能退出 WITH 模式。redis-cliredis-cliCtrl-C

推送消息的格式

消息是具有三个元素的数组回复。

第一个元素是消息的类型:

subscribe:表示我们成功订阅了回复中作为第二个元素给出的频道。 第三个参数表示我们当前订阅的频道数量。

unsubscribe:表示我们已成功取消订阅回复中作为第二个元素给出的频道。 第三个参数表示我们当前订阅的频道数量。 当最后一个参数为零时,我们不再订阅任何通道,客户端可以发出任何类型的 Redis 命令,因为我们处于 Pub/Sub 状态之外。

message:它是由于另一个客户端发出的 PUBLISH 命令而接收的消息。 第二个元素是原始通道的名称,第三个参数是实际的消息负载。

有线协议示例

SUBSCRIBE first second
*3
$9
subscribe
$5
first
:1
*3
$9
subscribe
$6
second
:2

此时,我们从另一个客户端对名为 :second 

> PUBLISH second Hello

这是第一个客户端收到的内容:

*3
$7
message
$6
second
$5
Hello

现在,客户端使用 UNSUBSCRIBE 命令从所有通道中取消订阅,而无需其他参数:

UNSUBSCRIBE
*3
$11
unsubscribe
$6
second
:1
*3
$11
unsubscribe
$5
first
:0

模式匹配订阅

Redis Pub/Sub 实现支持模式匹配。 客户端可以订阅 glob 样式模式,以接收发送到与给定模式匹配的通道名称的所有消息。

例如:

PSUBSCRIBE news.*

将接收发送到频道的所有消息,等等。 所有 glob 样式模式都有效,因此支持多个通配符。news.art.figurativenews.music.jazz

PUNSUBSCRIBE news.*

然后,将取消订阅该模式的客户端。 此调用不会影响其他订阅。

由于模式匹配而收到的消息以不同的格式发送:

  • 消息的类型是:它是从另一个客户端发出的 PUBLISH 命令接收的消息,与模式匹配订阅匹配。 第二个元素是匹配的原始模式,第三个元素是原始通道的名称,最后一个元素是实际的消息负载。pmessage

与 SUBSCRIBE 和 UNSUBSUBSCRIBE 类似, 和 PUNSUBSCRIBE 命令由发送类型为消息的系统确认,并使用与 and 消息格式相同的格式。psubscribepunsubscribesubscribeunsubscribe

与模式和频道订阅匹配的消息 

如果客户端订阅了与已发布消息匹配的多个模式,或者订阅了与该消息匹配的模式和通道,则客户端可能会多次收到一条消息。 以下示例显示了这一点:

SUBSCRIBE foo
PSUBSCRIBE f*

在上面的示例中,如果将消息发送到 通道,客户端将收到两条消息:一条是 type 的消息,另一条是 type 的消息。foomessagepmessage 

模式匹配的订阅计数的含义

在 、 和 消息类型中,最后一个参数是仍处于活动状态的订阅计数。 此数字是客户端仍订阅的通道和模式的总数。 因此,只有当此计数因取消订阅所有通道和模式而降至零时,客户端才会退出 Pub/Sub 状态。subscribeunsubscribepsubscribepunsubscribe

分片发布/订阅

从 Redis 7.0 开始,引入了分片 Pub/Sub,其中分片通道通过用于为插槽分配密钥的相同算法分配给插槽。 必须将分片消息发送到拥有分片通道散列到的插槽的节点。 群集确保将发布的分片消息转发到分片中的所有节点,以便客户端可以通过连接到负责槽位的主节点或其任何副本来订阅分片通道。SSUBSCRIBE、SUNSUBSCRIBE 和 SPUBLISH 用于实现分片的 Pub/Sub。

分片发布/订阅有助于在集群模式下扩展发布/订阅的使用。 它将消息的传播限制在集群的分片内。 因此,与全局发布/订阅相比,通过集群总线的数据量是有限的,在全局发布/订阅中,每条消息都传播到集群中的每个节点。 这允许用户通过添加更多分片来横向扩展 Pub/Sub 使用量。

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

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

相关文章

Python的pytest框架(4)--参数化测试

在 pytest 测试框架中,参数化测试(Parametrized Testing)意味着将一个测试用例设计为能够接受不同输入数据(参数)并分别执行,以验证被测试代码在面对多种情况时的行为是否符合预期。参数化测试的核心理念是…

DAY28| 93. 复原IP地址 ,79.子集 ,90.子集II

文章目录 93.复原IP地址78.子集90.子集II 93.复原IP地址 文字讲解:复原IP地址 视频讲解:复原IP地址 **状态:**此题调试了几次ok,与昨天的分割回文子串相比,就是在判断终止条件处需要处理; 思路:…

设计模式- 单例模式(Singleton)结构|实现方式|优缺点|场景

目录 设计模式(分类) 设计模式(六大原则) 创建型 工厂方法 抽象工厂模式 单例模式 建造者模式 单例模式(Singleton Pattern)是一种创建型设计模式,其…

rust : condvar中一对一和多对一模式初探

condvar是不经常碰到的,但其实在tokio之类库中,还是非常核心的作用。 想进一步体会condvar的使用,还是从场景出发。 一、一个通知发送者,一个接收者 假定一个员工收到一个任务,就是模拟是一个时间片,到时…

【Qt】设置QT标准对话框为中文字体

设置QT标准对话框为中文字体 一、问题二、解决方法1、找到Qt内置的翻译文件 qt_zh_CN.qm2、在代码中加载该文件 一、问题 在Qt中我们使用的标准对话框都是英文,例如下面的 字体选择对话框,但是实际中我们需要构建的是中文对话框。 所以我们需要使用Qt官…

19篇 vue3进阶

一 基础特性 1. **Composition API**:引入了组合式 API,允许以函数的方式组织组件逻辑。 2. **响应式系统**:使用 Proxy 作为其响应式系统的基础,提供更精确的依赖追踪。 3. **模板语法**:保留了 Vue 2 的模板语法…

MySQL InnoDB事务隔离级别与锁机制深入解析

引言 在当今的数据库系统中,事务管理是确保数据一致性和完整性的关键。事务是数据库操作的基本单元,它将一系列的数据库操作组合成一个逻辑工作单元,要么全部成功执行,要么全部失败回滚,这就是所谓的ACID属性&#xf…

js自动缩放页面,html自动缩放页面,大屏自动缩放页面,数字看板自动缩放页面,大数据看板自动缩放页面

js自动缩放页面&#xff0c;html自动缩放页面&#xff0c;大屏自动缩放页面&#xff0c;数字看板自动缩放页面&#xff0c;大数据看板自动缩放页面 由纯JS实现 html代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…

vue 注册自定义指令,对输入框输入内容过滤(区分中英文)

注册vue全局指令 对el-input输入框进行最大长度过滤&#xff08;区分中英文&#xff09; 过滤空格 注册全局指令 main.js /*** 输入框最长输入限制* param {*} e 文本内容* param {number} maxlength 最大字符长度* param {boolean} trim 是否过滤空格* returns {string} 最…

acwing算法提高之图论--有向图的强连通分量

目录 1 介绍2 训练 1 介绍 本博客介绍有向图的强连通分量的题目。 连通分量&#xff1a;是针对有向图的一个概念。对于分量中任意两个结点a、b&#xff0c;必然可以从a走到b&#xff0c;且从b走到a。 强连通分量&#xff1a;是针对有向图的一个概念。极大强连通分量&#xff…

【数据结构】单链表的头节点与尾节点

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

玄子Share-计算机网络参考模型

玄子Share-计算机网络参考模型 分层思想 利用七层参考模型&#xff0c;便于在网络通信过程中&#xff0c;快速的分析问题&#xff0c;定位问题并解决问题 将复杂的流程分解为几个功能相对单一的子过程 整个流程更加清晰&#xff0c;复杂问题简单化 更容易发现问题并针对性的…

【Java开发指南 | 第十七篇】Java 方法

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 简介语法实例构造方法 简介 Java中的方法是用来执行特定任务的一组语句&#xff0c;可以重复使用。它们包含在类或对象中&#xff0c;并通过调用来执行。 举个例子&#xff0c;println() 是一个方法&#xff…

动态内存管理 柔性数组

文章目录 动态内存函数 malloc freecallocrealloc 重新开辟空间realloc 也可以第一个参数为NULL&#xff0c;则是直接开辟内存&#xff0c;类似于malloc用法 常见的动态内存错误对空指针进行解引用操作对开辟的内存越界访问对非动态开辟的内存使用free释放使用free释放动态开辟…

vue2 在循环里,给字体加上随机颜色并加上随机图标且少重复

在循环里&#xff0c;给字体加上随机颜色并加上随机图标且少重复 <template><div class"pbfb5"><el-row :gutter"32"><el-col :xs"6" :sm"6" :lg"6" style"margin-bottom:32px;" v-for&quo…

(四)相关性分析 学习简要笔记 #统计学 #CDA学习打卡

目录 一. 相关性分析简介 二. 相关性分析方法 1&#xff09;连续型变量vs连续型变量&#xff1a;Pearson/Spearman &#xff08;a&#xff09;Pearson &#xff08;b&#xff09;Spearman等级相关系数 2&#xff09;二分类变量&#xff08;自然&#xff09;vs连续型变量&…

macos知名的清理软件 cleanmymac和腾讯柠檬哪个好 cleanmymacx有必要买吗

MacOS是一款优秀的操作系统&#xff0c;但是随着使用时间的增加&#xff0c;它也会产生一些不必要的垃圾文件&#xff0c;占用磁盘空间和内存资源&#xff0c;影响系统的性能和稳定性。为了保持MacOS的清洁和高效&#xff0c;我们需要使用一些专业的清理软件来定期扫描和清除这…

CentOS服务器安装宝塔(图文详解)

宝塔的操作其实就是类似于把linux的指令使用方式&#xff0c;通过宝塔这个第三方工具进行可视化展示&#xff0c;但其实&#xff0c;他还是在操作linux&#xff0c;只是不需要你去记那么多的指令&#xff0c;宝塔把大多数的工具都集成到自己里面&#xff0c;这样你就可以在宝塔…

信号量Semaphore

什么是信号量&#xff1f; C中的信号量&#xff08;Semaphore&#xff09;是一种同步对象&#xff0c;用于控制对共享资源的访问&#xff0c;以防止多个线程或进程同时访问同一资源&#xff0c;从而避免数据不一致的问题。信号量通过维护一个计数值来实现这一功能&#xff0c;…

【Golang】Gin教学-获取请求信息并返回

安装Gin初始化Gin处理所有HTTP请求获取请求的URL和Method获取请求参数根据Content-Type判断请求数据类型处理JSON数据处理表单数据处理文件返回JSON响应启动服务完整代码测试 Gin是一个用Go&#xff08;又称Golang&#xff09;编写的HTTP Web框架&#xff0c;它具有高性能和简洁…