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

embedded/2024/10/20 11:44:09/

订阅发布

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.ppmy.cn/embedded/8879.html

相关文章

【Hadoop大数据技术】——Azkaban工作流管理器(学习笔记)

📖 前言:在前面HDFS分布式文件系统中,我们使用Linux自带的Crontab(定时任务工具)来定时调度任务,但是当业务规模变大并且需要可视化监控任务执行的时候,Crontab就已经不能满足这些需求了。为此&…

北大字节联合发布视觉自动回归建模(VAR):通过下一代预测生成可扩展的图像

北大和字节发布一个新的图像生成框架VAR。首次使GPT风格的AR模型在图像生成上超越了Diffusion transformer。 同时展现出了与大语言模型观察到的类似Scaling laws的规律。在ImageNet 256x256基准上,VAR将FID从18.65大幅提升到1.80,IS从80.4提升到356.4,推理速度提高了20倍。 相…

牛客Linux高并发服务器开发学习第二天

Gcc编译 利用gcc 生成应用时如果不加-o 和应用名,默认生成a.out 可以用./ a.out打开 Gcc工作流程 可执行程序Windows系统中为.exe Linux系统中为.out g也可以编辑c程序 gcc也可以编译cpp代码,只是在编译阶段gcc不能自动共和C程序使用的库进行联接&…

python--pyQt5 进度条:QProgressBar

https://www.cnblogs.com/itwangqiang/articles/14959401.html https://blog.csdn.net/weixin_43990846/article/details/123880081 进度条用于向用户指示操作的进度,并向他们保证应用程序仍在运行 例 1 import sys from PyQt5.QtWidgets import QApplication, QWi…

2024蓝桥杯每日一题(最大公约数)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一:公约数 试题二:最大公约数 试题三:等差数列 试题四:最大比例 试题五:Hankson的趣味题 试题一:公约数 【题目描述】 …

“卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法

原文链接:“卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601940&idx6&sn515e01666037570939aaf0eee56f46d1&chksmfa820ef3cdf587e5276eac181c890026b6ca4bc36ce0e4f80d89d…

机器学习-11-基于多模态特征融合的图像文本检索

总结 本系列是机器学习课程的系列课程,主要介绍机器学习中图像文本检索技术。此技术把自然语言处理和图像处理进行了融合。 参考 2024年(第12届)“泰迪杯”数据挖掘挑战赛 图像特征提取(VGG和Resnet特征提取卷积过程详解&…

第十五届蓝桥杯c++b组赛后复盘和真题展示

题目变成八道了,分数一百分可能,感觉拿奖难度还是很高 第一题是一个简单的握手问题 答案算出来1204,纯手写 第二题是 物理题 纯蒙,随便猜了个轨迹,答案具体忘了,最后是 .45 第三题暴力 第四题 我是傻逼…