Redis中的订阅发布和事务(一)

订阅发布

PUBSUB NUMSUB

PUBSUB NUMSUB [channel-1 channel-2… channel-n]子命令接受任意多个频道作为输入参数,并返回这些频道的订阅者数量。
这个子命令是通过pubsub_channels字典中找到频道对应的订阅者链表,然后返回订阅者链表的长度来实现的(订阅者链表的长度
就是频道订阅者的数量),这个过程可以用以下伪代码来描述:

def pubsub_numsub(*all_input_channels):
# 遍历输入的所有频道
for channel in all_input_channels:
# 如果pubsub_channels字典中没有channel这个键
# 那么说明channel频道没有任何订阅者
if channel not in server.pubsub_channels:
# 返回频道名
reply_channel_name(channel)
# 订阅者数量为0
reply_subscribe_count(0)# 如果pubsub_channels字典中存在channel键
# 那么说明channel频道至少有一个订阅者
else:
# 返回频道名
reply_channel_name(channel)
# 订阅者链表的长度就是订阅者数量
reply_subscribe_count(len(server.pubsub_channels(channel)))

例子

在这里插入图片描述

  • 举个例子。对于图中所示的pubsub_channels字典来说,对字典中的四个频道执行PUBSUB NUMSUB命令将获得以下回复
redis>PUBSUB NUMSUB news.it news.sport news.business news.movie
1)."news.it"
2)."3"
3)."news.sport"
4)."2"
5)."news.business"
6)."2"
7)."news.movie"
8)."1"

PUBSUB NUMPAT

PUBSUB NUMPAT子命令用于返回服务器当前被订阅模式的数量。这个子命令是通过返回pubsub_patterns链表的长度来实现的,因为这个链表的长度就是服务器被订阅模式的数量,这个过程可以用以下伪代码来描述:

def pubsub_numpat():
# pubsub_patterns链表的长度即是被订阅模式的数量
reply_pattern_count(len(server.pubsub_patterns))

例子

  • 举个例子。对于图中所示的pubsub_patterns链表来说,执行PUBSUB NUMPAT命令将返回3:
redis>PUBSUB NUMPAT
(integer) 3

在这里插入图片描述

事务

概述

Redis通过MULTI、EXEC、WATCH等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后采取执行其他客户端的命令请求。

例子
  • 举个例子。事务首先以一个MULTI命令为开始,接着将多个命令放入事务当中,最后由EXEC命令将这个事务提交(commit)给服务器执行:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET "name" "Practical Common Lisp"
QUEUED
127.0.0.1:6379> GET "name"
QUEUED
127.0.0.1:6379> SET "author" "Peter Seibel"
QUEUED
127.0.0.1:6379> GET "author"
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "Practical Common Lisp"
3) OK
4) "Peter Seibel"

事务的实现

一个事务从开始到结束通常会经历以下三个阶段:

  • 1.事务开始
  • 2.命令入队
  • 3.事务执行

事务开始

MULTI命令的执行标志着事务的开始:

redis> MULTI
OK

MULTI命令可以将执行该命令的客户端从非事务状态切换至事务状态,这一切换是通过在客户端状态的flags属性中打开REDIS_MULTI标识来完成的,MULTI命令的实现可以用以下伪代码来表示:

def MULTI():
# 打开事务表示
client.flags |= REDIS_MULTI# 返回OK回复
replyOK()

命令入队

当一个客户端处于非事务状态时,这个客户端发送的命令会立即被服务器执行:

127.0.0.1:6379> SET "name" "Practical Common Lisp"
OK
127.0.0.1:6379> GET "name"
"Practical Common Lisp"
127.0.0.1:6379> SET "author" "Peter Seibel"
OK
127.0.0.1:6379> GET "author"
"Peter Seibel

与此不同的是,当一个客户端切换到事务状态之后,服务器会根据这个客户端法拉的不同命令执行不同的操作:

  • 1.如果客户端发送的命令为EXEC、DISCARD、WATCH、MULTI四个命令的其中一个,那么服务器立即执行这个命令
  • 2.与此相反,如果客户端发送的命令是EXEC、DISCARD、WATCH、MULTI四个命令以外的其他命令,那么服务器并不立即执行这个命令,而是将这个命令放入一个事务队列里面,然后向客户端返回QUEUED回复。

服务器判断命令是该入队还是该立即执行的过程可以用流程图来描述
在这里插入图片描述

事务队列

每个Redis客户端都由自己的事务状态,这个事务状态保存在客户端状态的mstate属性里面:

typedef struct redisClient {
// ...// 事务状态
multiState mstate; // MULTI/EXEC state// ...
}redisClient;

事务状态包含一个事务队列,以及一个已入队命令的计数器(也可以说是事务队列的长度):

typedef struct multiState {
// 事务队列, FIFO顺序
multiCmd *commands;// 已入队命令计数
int count;
} multiState;

事务队列是一个multiCmd类型的数组,数组中的每个multiCmd结构都保存了一个已入队命令的相关信息,包括指向命令实现函数的指针、命令的参数,以及参数的数量:

typedef struct multiCmd {
// 参数
robj **argv;// 参数数量
int argc;// 命令指针
struct redisCommand *cmd;
}multiCmd;

事务队列以先进先出(FIFO)的方式保存入队的命令,较先入队的命令会被放到数组的前面,而较后入队的命令则会被放到数组的后面

例子
  • 举个例子。如果客户端执行以下命令:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET "name" "Practical Common Lisp"
QUEUED
127.0.0.1:6379> GET "name"
QUEUED
127.0.0.1:6379> SET "author" "Peter Seibel"
QUEUED
127.0.0.1:6379> GET "author"
QUEUED

那么服务器将为客户端创建如图所示的事务状态:
1.最先入队的SET命令被放在了事务队列的索引0位置上
2.第二入队的GET命令被放在了事务队列的索引1位置上
3.第三入队的另一个SET命令被放在了事务队列的索引2位置上
4.最后入队的另一个GET命令被放在了事务队列的索引3位置上
在这里插入图片描述

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

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

相关文章

Nuclei 减少漏报的使用小技巧

在最近工作的渗透测试项目中发现Nuclei存在一个问题,就是相同的网站连续扫描多次会出现漏报的情况,此前没有注意过这个情况,所以写篇文章记录一下。 在此之前我的常用命令都是一把梭,有就有没有就继续其他测试 $ nuclei -u htt…

代码随想录算法训练营第四十五天| 70. 爬楼梯 (进阶),322. 零钱兑换 ,279.完全平方数

题目与题解 70. 爬楼梯 (进阶) 题目链接:70. 爬楼梯 (进阶) 代码随想录题解:70. 爬楼梯 (进阶) 解题思路: 这道题要求每次可以爬1-m层的楼梯,最终爬到n&…

微服务架构中的业务数据可视化设计

目录 1.概要设计 1.1明确可视化目标 1.2数据整合与标准化 1.3选择合适的数据可视化工具 1.4设计可视化界面 1.5 实时更新与优化 2.技术实现 2.1数据采集与整合 2.2数据处理与转换 2.3数据存储 2.4 数据可视化 2.5 实时数据更新 2.6 安全性与权限控制 2.7 监控与日…

【ZZULIOJ】1072: 青蛙爬井(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy 提示 code 题目描述 有一口深度为high米的水井,井底有一只青蛙,它每天白天能够沿井壁向上爬up米,夜里则顺井壁向下滑down米,若青蛙从某个早晨开始向外爬&#xff0c…

患者关系管理系统功能详解

脉购健康管理系统(软件)包含:客户开卡、健康档案、问卷调查、问诊表、自动设置标签、自动随访、健康干预、健康调养、历年指标趋势分析、疾病风险评估、饮食/运动/心理健康建议、同步检查报告数据、随访记录、随访电话录音、健康阶段总结、打…

Java - 阿里巴巴命名规范

文章目录 前言一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 日期时间(六) 集合处理(七) 并发处理(八) 控制语句(九) 注释规约(十) 前后端规约(十一) 其他 二、异常日志(一) 错误码(二) 异常处理(三) 日志规约 三、单元测试四、安全规约五、MySQL 数据…

2024面试软件测试,常见的面试题(上)

一、综合素质 1、自我介绍 面试官您好,我叫XXX,一直从事车载软件测试,负责最多的是中控方面。 以下是我的一些优势: 车载的测试流程我是熟练掌握的,且能够独立编写测试用例。 平时BUG提交会使用到Jira,类似…

postgis源码编译安装-实操成功

依赖环境安装 sqlite3安装 https://www.sqlite.org/2024/sqlite-autoconf-3450200.tar.gz tar xvf sqlite-autoconf-3450200.tar cd sqlite-autoconf-3450200 mkdir -p /home/postgres/app/postgis/sqlite3 ./configure --prefix=/home/postgres/app/postgis/sqlite3 ma…

电缆检测仪的正确使用方法有哪些步骤?

电缆检测仪的正确使用方法是:首先,确保检测仪电源充足,设备完好无损;其次,根据电缆类型和故障类型选择合适的测试模式和参数;接着,将检测仪与电缆正确连接,确保接触良好;…

深入挖掘C语言 ----动态内存分配

开篇备忘录: "自给自足的光, 永远都不会暗" 目录 1. malloc和free1.1 malloc1.2 free 2. calloc和realloc2.1 calloc2.2 realloc 3. 总结C/C中程序内存区域划分 正文开始 1. malloc和free 1.1 malloc C语言提供了一个动态开辟内存的函数; void* malloc (size_t s…

python处理IP对应城市省份

python处理IP对应城市省份 IP地理地址库geoip2用法 数据包下载 数据包下载地址(需要注册) https://www.maxmind.com/en/accounts/258630/geoip/downloads 考虑到注册麻烦,可以到下面这个github的链接去直接下载 https://github.com/Hackl0…

AItoolchain相关技术学习

AItoolchain主要模块包括: 模型转换:将深度学习模型转换为特定硬件平台可以识别和执行的格式。嵌入式运行环境:提供异构模型的运行库支持,确保模型在目标设备上的运行效率。性能验证:包括静态和动态性能评估&#xff…

2024-9.python文件操作

文件操作 引言 到目前为止,我们做的一切操作,都是在内存里进行的,这样会有什么问题吗?如果一旦断电或发生意外关机了,那么你辛勤的工作成果将瞬间消失。是不是感觉事还挺大的呢?现在你是否感觉你的编程技…

【Java EE】依赖注入DI详解

文章目录 🌴什么是依赖注入🍀依赖注入的三种方法🌸属性注入(Field Injection)🌸构造方法注入🌸Setter注入🌸三种注入优缺点分析 🌳Autowired存在的问题🌲解决Autowired对应多个对象问…

动态库静态库linux

动态库静态库 静态库 静态库必须包含在可执行文件里,整个都要包含 缺点:消耗系统大,每个使用静态库的程序都要复制静态库(浪费内存) 影响使用场景: 在静态库内存小的时候,可以用来提升速度 制…

redis在Windows下设置静默启动

redis在Windows下设置静默启动 下载windows版redis,解压cmd命令行有窗口启动(这种启动方式,这个界面就不能关闭才会生效 注册成为服务,设置成开机启动或者手动启动(静默启动)清除缓存本地清除,直接打开redis-cli.exe本地远程连接清除缓存 下载…

投影矩阵(Projection Matrix)

在机器学习和数据分析中,投影矩阵是一个非常重要的工具,它主要用于将高维数据降维或者变换到新的坐标系中。这个过程通常被称为线性变换或投影。 过程: 假设我们有一个原始的高维数据集X,其中每一列代表一个特征,每一行…

Scala 03 —— Scala Puzzle 拓展

Scala 03 —— Scala Puzzle 拓展 文章目录 Scala 03 —— Scala Puzzle 拓展一、占位符二、模式匹配的变量和常量模式三、继承 成员声明的位置结果初始化顺序分析BMember 类BConstructor 类 四、缺省初始值与重载五、Scala的集合操作和集合类型保持一致性第一部分代码解释第二…

【C++】<入门>C++入门基础知识

C入门 1. 入门0. 本节知识点熟悉目的1. C关键字(C98) 2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.1 函数重载概念5.2 C支持函数重载的原理--名字修饰(name Ma…

Vue3从入门到实践:深度了解新组件

1.Teleport 概念:Teleport(传送门)是一个新的特性,用于在DOM中的任意位置渲染组件。它允许你将组件的内容渲染到DOM中的另一个位置,而不受组件层次结构的限制。 下面举出例子解释: 1.新建App.vue文件作…