Redis发布订阅和事务实现原理

news2024/11/17 1:29:45

Redis发布订阅和事务实现原理

  • 发布订阅
    • 实现
      • 频道订阅与退订
      • 频道模式订阅与退订
      • 发送消息
  • 事务
    • 事务队列
    • 执行事务
    • WATCH命令实现
    • ACID
      • 原子性
      • 一致性
      • 隔离性
      • 持久性


发布订阅

Redis的发布订阅由PUBLISH,SUBSCRIBE,PSUBSCRIBE等命令组成,例子如下:

在这里插入图片描述
在这里插入图片描述
redis中我们还可以通过PSUBSCRIBE "user.*"命令完成频道的模式订阅,也就是模糊匹配,而SUBSCRIBE命令是明确订阅某个频道,也就是精确匹配。

当我们通过publish向某个频道发送命令时,该消息不仅会发送给订阅该频道的所有用户,同时也会发送给与该频道相匹配的模式的订阅者。
在这里插入图片描述


实现

频道订阅与退订

redis服务器全局状态由redisServer结构体对象保存,该对象内部保存了所有频道的订阅关系:

struct redisServer{
   //...
   
   //保存所有频道的订阅关系
   dict *pubsub_channels;
  
  //... 
}

pubsub_channels属性的数据类型是字典类型,该字典中的key保存了频道名,value链表将订阅该频道的所有客户端串联起来:

在这里插入图片描述

  • 当我们通过subscribe命令订阅某个频道的时候,所做的工作如下:
    在这里插入图片描述

  • 当我们通过unsubscribe命令退订某个频道时,所做的工作如下:

在这里插入图片描述


频道模式订阅与退订

struct redisServer{
   //...
   
   //保存所有频道的订阅关系
   dict *pubsub_channels;
   //保存所有模式订阅关系
   list *pubsub_patterns;
  
  //... 
}

typedef struct pubsubPattern{
   //订阅模式的客户端
   redisClient *client;
   //被订阅的模式
   robj *pattern
}pubsubPattern

pubsub_patterns链表中保存的元素类型是pubsubPattern,该结构体记录了每个客户端所订阅的频道模式。

在这里插入图片描述

  • 订阅模式
    在这里插入图片描述
  • 退订模式

在这里插入图片描述


发送消息

当一个redis客户端执行PUBLISH channel message命令时,服务器需要执行以下两步:

  1. 将消息发送给channel频道的所有订阅者

在这里插入图片描述

  1. 如果有一个或多个模式pattern与channel匹配,那么将消息发送给pattern模式的订阅者

在这里插入图片描述


事务

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

在这里插入图片描述
事务执行分为三个阶段:

  • 事务开始: 通过multi命令表示开启事务,标记当前客户端进入事务状态
    在这里插入图片描述

  • 命令入队
    在这里插入图片描述

  • 事务执行


事务队列

每个Redis客户度都通过multiState属性来记录当前事务状态:

struct redisClient {
      //事务状态
      multistate mstate;
      ... 
}

事务状态包含一个事务队列和已经入队的命令计数器:

struct multistate {
   //事务队列--FIFO顺序
   multicmd *cmds;
   //已经入队的命令计数器
   int count; 
}

事务队列中每个multicmd都保存了当前已入队命令的信息:

struct multicmd {
  //参数
  robj **argv;
  //参数个数
  int argc;
  //命令指针
  struct redisCommand *cmd;
}

事务队列以先入先出顺序保存命令,例如:
在这里插入图片描述
事务队列中保存命令顺序:
在这里插入图片描述


执行事务

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

在这里插入图片描述


WATCH命令实现

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

每个Redis数据库都保存着一个watched_keys字典,该字典的key是某个被watch命令监视的数据库键,而值是一个链表,链表中记录了所有监视当前key的客户端。

struct redisDb{
   //正在被watch命令监视的key
   dict *watched_keys;
}

在这里插入图片描述


所有对数据库进行修改的命令,如: SET,LPUSH,SADD,ZREM,DEL等,在执行后都会调用touchWatchKey函数对watched_keys字典进行检查,如果字典中存在该key,那么会将监视该key对应的客户端的REDIS_DIRTY_CAS标记打开,表示当前客户端的安全性已经被破坏了。

在这里插入图片描述


当exec事务执行命令被调用时,服务器会检查当前客户端对应的REDIS_DIRTY_CAS标识是否已经被打开了,如果被打开了,就拒绝执行事务:
在这里插入图片描述


ACID

原子性

redis事务队列中的命令要么全部执行,要么全部不执行。

如果命令在入队过程中,出现了命令语法格式错误导致命令入队失败,那么当前事务中所有命令都不会被执行。

在这里插入图片描述
如果事务队列中命令执行时,发生错误,那么redis不提供回滚机制,并且命令将会继续执行下去,直到执行完毕:
在这里插入图片描述


一致性

  • 出现入队错误会导致当前事务被拒绝执行
  • 事务执行时出现错误,不会中断事务执行
  • redis服务器执行事务过程中停机不会导致数据不一致,服务器重启时可以通过rdb或者aof文件恢复数据

空白数据库总是可以看做是一致的


隔离性

数据库的隔离性指的是多个并发执行事务互不干扰,并且并行事务执行结果要与串行执行一致。

Redis使用单线程执行事务,并且执行事务期间不会对事务进行中断,因此,redis的事务总是以串行化方式运行。


持久性

因为Redis的事务不过是简单地用队列包裹起了一组Redis命令,Redis并没有为事务提供任何额外的持久化功能,所以Redis事务的耐久性由Redis所使用的持久化模式决定:

□ 当服务器在无持久化的内存模式下运作时,事务不具有耐久性:一旦服务器停机,包括事务数据在内的所有服务器数据都将丢失。

□ 当服务器在RDB持久化模式下运作时,服务器只会在特定的保存条件被满足时,才会执行BGSAVE 命令,对数据库进行保存操作,并且异步执行的BGSAVE 不能保证事务数据被第一时间保存到硬盘里面,因此RDB持久化模式下的事务也不具有耐久性。

□ 当服务器运行在AOF持久化模式下,并且appendfsync选项的值为always 时,程序总会在执行命令之后调用同步(sync)函数,将命令数据真正地保存到硬盘里面,因此这种配置下的事务是具有耐久性的。

□ 当服务器运行在AOF持久化模式下,并且appendfsync选项的值为everysec 时,程序会每秒同步一次命令数据到硬盘。因为停机可能会恰好发生在等待同步的那一秒钟之内,这可能会造成事务数据丢失,所以这种配置下的事务不具有耐久性。

□ 当服务器运行在AOF持久化模式下,并且appendfsync 选项的值为no时,程序会交由操作系统来决定何时将命令数据同步到硬盘。因为事务数据可能在等待同步的过程中丢失,所以这种配置下的事务不具有耐久性。


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

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

相关文章

三菱FX5U系列PLC通过简单CPU通信功能实现以太网通信的具体方法示例

三菱FX5U系列PLC通过简单CPU通信功能实现以太网通信的具体方法示例 对于三菱FX5U系列PLC,只需对CPU模块进行简单的参数设置,即可实现在指定时间内与指定软元件进行数据收发的功能。以1:1的方式设置通信对象(传送源)和通信对象(传送目标),在指定的通信对象之间进行数据的…

windows下TensorFlow-GPU 的安装教程

文章目录安装环境一. 查看自己的GPU版本是否支持cuda二 .安装CUDA三. 安装cuDNN安装环境 Anaconda: 4.10.1python: 3.8.8tensorflow-gpu: 2.5.0cuda: 11.4.0cudnn: 8.2.2.26 一. 查看自己的GPU版本是否支持cuda 打开显卡的控制面板,查看显卡是否支持cuda 查看te…

物联网-初步探索lua

初步探索lua 在物联网行业中,存在各种协议;比如在电控和云端进行通信的时候需要对功能进行解码和编码;当云端下发到设备的时候需要将Json格式的命令转换成电控码;当电控进行上报或者返回的时候,需要将16进制的电控码转…

(黑马C++)L06 重载与继承

一、关系运算符重载 以重载等于号运算符为例&#xff1a; #include<string> #include <iostream> using namespace std;class Person { public:Person(string Name, int age) {this->m_Name Name;this->m_Age age;}public:string m_Name;int m_Age; };bo…

SD存储卡接口规范介绍

SD存储卡简介 SD卡高度集成闪存&#xff0c;具备串行和随机存取能力。可以通过专用优化速度的串行接口访问&#xff0c;数据传输可靠。接口允许几个卡垛叠&#xff0c;通过他们的外部连接。接口完全符合最新的消费者标准&#xff0c;叫做SD卡系统标准&#xff0c;由SD卡系统规范…

用javascript分类刷leetcode14.排序算法(图文视频讲解)

常见排序算法复杂度 n^2除nlogn在不同数据规模下的结果 常见排序算法 算法可视化来源&#xff1a;http://visualgo.net/ 冒泡排序&#xff1a;时间复杂度O(n^2) 比较相邻元素&#xff0c;如果第一个比第二个大&#xff0c;则交换他们一轮下来&#xff0c;可以保证最后一个数…

Android入门第56天-在Android里使用OKHttp多线程下载文件并展示其进度

简介 OkHttp是一个神器。OkHttp分为异步、同步两种调用。今天我们就会基于OkHttp的异步调用实现一个多线程并行下载文件并以进度条展示总进度的实用例子。当然这不是我们的Android里使用OkHttp的最终目标&#xff0c;我们最终在下一篇中会在今天这一课的基础上加入“断点续传”…

【我在异世界学Linux】认识冯诺依曼体系结构

文章目录一、冯诺依曼体系结构是什么二、冯诺依曼为什么要这么设计&#xff1f;三、内存是怎么提高效率的呢&#xff1f;解释&#xff1a;程序要运行&#xff0c;必须加载到内存四、和QQ好友聊天的时候&#xff0c;数据是怎么流向的&#xff1f;一、冯诺依曼体系结构是什么 冯诺…

教你使用Java开发一款简单的扫雷小游戏 附实例代码

相信很多小伙伴都知道也玩过扫雷游戏,本篇文章将和大家分享一篇关于如何使用Java来实现一款简单的扫雷小游戏,这有助于大家对于Java相关知识的学习有一定的参考价值,下面是详情内容。 简介 学了几周的Java,闲来无事,写个乞丐版的扫雷,加强一下Java基础知识。 编写过程…

树莓派4b串口配置

从树莓派的相关资料我们可以看到&#xff0c;树莓派有两个串口可以使用&#xff0c;一个是硬件串口&#xff08;/dev/ttyAMA0&#xff09;,另一个是mini串口&#xff08;/dev/ttyS0&#xff09;。硬件串口有单独的波特率时钟源&#xff0c;性能好&#xff0c;稳定性强&#xff…

【Java寒假打卡】Java基础-接口

【Java寒假打卡】Java基础-接口接口的介绍接口的定义和特点接口中的成员特点JDK8 接口中的成员特点JDK9 接口中的成员特点类和接口的关系接口的介绍 &emsp&#xff1b;当一个类中的所有方法都是抽象方法的时候&#xff0c;我们就可以将其定义为接口&#xff0c;接口也是一…

Redis 缓存数据库

目录Redis 高可用方案高可用概念Redis 高可用的实现方案1、主从模式2、哨兵模式3、集群模式Redis 高可用方案 高可用概念 高可用&#xff08;High Availability&#xff0c;既HA&#xff09;&#xff0c;指的是通过尽量缩短日常维护操作和减少突发系统奔溃锁导致的停机时间来提…

Vagrant 安装 Centos7

首先准备VirtualBox, 当前实验版本为&#xff1a;7.0.4-154605-Win&#xff1b; 再次下载Vagrant windows版本&#xff1a;当前实验版本&#xff1a;vagrant_2.3.4_windows_i686 如果安装VirtualBox过程中提示缺少&#xff1a;Microsoft Visual C 2019 Redistributable &…

MySQL索引概述

索引的英文名叫 index 在数据库是一种帮助MySQL高效获取数据的数据结构 而且是一种有序的数据结构 在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用(指向)数据&#xff0c; 这样就可以在这些数据结构上实现高级找…

公钥基础设施 时间戳规范测评

声明 本文是学习信息安全技术 公钥基础设施 标准符合性测评. 下载地址而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 公钥基础设施 时间戳规范测评 时间戳的产生和颁发 申请和颁发方式 测评依据见GB/T 20520—2006中6.1的内容。 开发者应提供文档…

2.0、Linux-基础了解

2.0、开机关机和基本目录介绍 开机登录&#xff1a; 开会机会启动许多程序&#xff1b;他们在Windows叫做 "服务" &#xff0c;在 Linux 中叫做 "守护进程"&#xff08;daemon&#xff09;&#xff1b; 开机成功后&#xff0c;他会显示一个文本登录…

Tailoring Self-Supervision for Supervised Learning-读后总结

Tailoring Self-Supervision for Supervised Learning摘要文章思路一些值得读的参考文献和技术&#xff1a;值得一读的高引文献可视化技术摘要 近期&#xff0c;在监督学习中部署一个合适的自监督学习来提高监督学习的性能是一个具有前景的方式。然而&#xff0c;因为之前的前…

MP中定义全局常量用于xml的判断,List<String> list = new ArrayList<>(Arrays.asList(“test“));

,1.普通方式 mybatis-plus.configuration.variables.secretFilterSwitch0 yml的方式 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.demo configuration: variables: userId: 456132465 userName: 李四 配置完成后在代…

人文社科类文献去哪些数据库检索下载

查找下载人文社科类文献的数据库大盘点&#xff1a; 1、文献党下载器&#xff08;wxdown.org&#xff09; 大型文献馆&#xff0c;几乎整合汇集了所有中外文献数据库资源&#xff0c;可附带权限进入文献数据库查找下载文献&#xff0c;覆盖全科包括查找下载人文社科类文献的众…

【C和数据结构-5+1】习题第一天

文章目录一.选择题1.整型在内存中的存储2.大小端字节序3.指针的大小4.形参一级指针或二级指针的区别5.二维数组传参降维成数组指针二.编程题1.自守数2.质数判断一.选择题 1.整型在内存中的存储 猜一猜打印的结果? int main() {char a 101;int sum 200;a 27; sum a;printf…