我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Redis | 第8章 发布订阅与事务《Redis设计与实现》

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Redis | 第8章 发布订阅与事务《Redis设计与实现》

Redis | 第8章 发布订阅与事务《Redis设计与实现》

目录
  • 前言
    • 《Redis常用命令及示例总结(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html
  • 1. 发布订阅
    • 1.1 频道的订阅与退订
    • 1.2 模式的订阅与退订
    • 1.3 发送消息
    • 1.4 查看订阅消息
  • 2. 事务
    • 2.1 事务的实现
    • 2.2 WATCH 命令的实现
    • 2.3 事务的 ACID 性质
  • 最后

前言

参考资料:《Redis设计与实现 第二版》;

第三部分为独立功能的实现,主要由以下模块组成:发布订阅事务Lua 脚本排序二进制位数组慢查询日志监视器

本篇将介绍 Redis 的发布订阅事务。Redis 提供了频道与模式的订阅与退订,支持对频道发送消息。Redis 的事务机制支持一次性、按顺序执行多个命令,以及事务的 ACID 性质;

与本章相关的 Redis 命令总结在下篇文章,欢迎点击收藏,本篇将不再重复:

《Redis常用命令及示例总结(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html

1. 发布订阅

1.1 频道的订阅与退订

  • 客户端使用 SUBSCRIBE 命令订阅某个或某些频道;

  • 客户端使用 UNSUBSCRIBE 命令退订频道;

  • Redis 将所有频道的订阅关系保存在服务器状态的 pubsub_challens 字典里:

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

一个 pubsub_channels 字典示例

  • 频道订阅的情况
    • 频道已有其他订阅者,则将客户端添加到订阅者链表末端;
    • 反之,字典里没有该频道,则创建一个键值对项;
  • 频道退订的情况
    • 找到频道对应链表,删除客户端信息;
    • 若删除后链表长度为0,则删除键;

频道的订阅

1.2 模式的订阅与退订

  • 客户端使用 PSUBSCRIBE 命令订阅某个或某些模式;

  • 客户端使用 PUNSUBSCRIBE 命令退订模式;

  • Redis 将所有模式的订阅关系保存在服务器状态的 pubsub_patterns 链表里:

    struct redisServer{
        //...
        //保存所有模式订阅关系,记录被订阅的模式
        list *pubsub_patterns;
    }; 
    
  • pubsub_patterns 链表保存的结构体如下:

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

pubsub_patterns 链表示例

  • 客户端在订阅模式时,会创建一个 pubsubPattern 结构体,并添加到链表尾部;
  • 客户端在退订模式时,遍历链表删除对应模式;

模式与频道的订阅

1.3 发送消息

  • 客户端执行 PUBLISH channel message 命令将 message 消息发送给 channel 频道,然后服务器将消息发送给频道与模式订阅者;
  • 将消息发送给频道订阅者:
    • pubsub_channels 字典里找到频道 channel 的所有订阅者名单(链表),然后将消息发送给名单上的所有客户端;
  • 将消息发送给模式订阅者:
    • 遍历 pubsub_patterns 链表,查找与 channel 频道相匹配的模式,然后将消息发送给订阅了这些模式的客户端;

频道发送消息
模式频道发送消息

1.4 查看订阅消息

  • 客户端使用 PUBSUB 命令查看频道或模式的相关信息;
  • PUBSUB CHANNELS [pattern] 命令用于返回服务器当前被订阅的频道;
  • PUBSUB NUMSUB [channel ...] 命令接受任意多个频道作为输入参数,返回这些频道的订阅者数量。通过查询 pubsub_channels 字典中对应频道键的链表值的长度;
  • PUBSUB NUMPAT 命令用于返回服务器当前被订阅模式的数量。通过查询 pubsub_patterns 链表的长度;

2. 事务

  • 事务提供一种将多个命令打包,然后一次性、按顺序执行多个命令的机制;
  • 并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求;

2.1 事务的实现

  • 事务开始
    • 使用 MULTI 命令;
    • 通过修改客户端状态中 flags 属性为 REDIS_MULTI 实现;
  • 命令入队
    • 当客户端切换到事务模式时,会根据命令不同采取不同的操作;
    • 与事务相关的命令有:EXECDISCARDWATCHMULTI
      服务器判断命令类型
  • 事务队列
    • Redis 客户端里有事务状态属性 mstate

      typedef struct redisClient{
          //...
          //事务状态
          multiState mstate;
      } redisClient;
      
    • multiState 事务状态结构,包含事务队列与计数器:

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

事务队列逻辑图

  • 执行事务
    • 处于事务状态的客户端向服务器发送 EXEC 命令时,会执行事务;
    • 服务器遍历客户端的事务队列,执行队列中保存的所有命令,将执行结果返回给客户端;

2.2 WATCH 命令的实现

  • WATCH 命令是一个乐观锁;

  • 在执行 EXEC 命令:监视任意数量的数据库建;

  • 在执行 EXEC 命令:检查被监视的键是否至少有一个已经被修改,是则拒绝执行事务,返回错误;

  • Redis 数据库保存一个 watched_keys 字典:

    typedef struct redisDb{
        //...
        // 字典,键表示被 WATCH 命令监视的数据库键;值为链表,记录监视该键的客户  端
        dict *watched_keys;
    } redisDb;
    
  • 所有对数据库进行修改的命令,在执行后都会调用 multi.c/touchWatchKey 函数对 watched_keys 字典进行检查:

    • 如果有客户端监视被修改的键,则将客户端的 REDIS_DIRTY_CAS 标识打开,表示客户端的事务安全性被破坏;
  • 服务器接收到 EXEC 命令时,会根据客户端是否打开 REDIS_DIRTY_CAS 标识决定是否执行事务:

    • 如果打开,说明本次提交不安全,服务器会拒绝执行客户端提交的事务;
    • 否则说明事务安全,可以提交;

判断事务是否安全

2.3 事务的 ACID 性质

  • Redis 数据库的事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、耐久性(Durability);
  • 原子性
    • 事务队列要么全部执行,要么一个都不执行;
    • Redis 不支持事务回滚机制(rollback),事务队列中某个命令在执行期间出现错误,后续事务也会继续执行;
  • 一致性
    • 一致指:数据符合数据库本身的定义和要求,没有包含非法或无效的错误数据;
    • 数据库在执行事务之前是一致的,在执行事务之后,无论事务是否成功,数据库也应该是一致的;
    • Redis 的一致性有:入队错误、执行错误、服务器停机;
  • 隔离性
    • 数据库中多个事务并发执行,各个事务之间不会互相影响,并且与串行执行的结果相同;
    • 原因:Redis 使用单线程方式执行事务以及事务队列中的命令,且服务器保证在事务执行期间不会对事务中断;
  • 耐久性
    • 当一个事务执行完毕,执行事务所得的结果会被保存到永久性存储介质;

    • Redis 的事务耐久性由持久化模式支持:

      服务器的持久化模式 事务的耐久性 说明
      无持久化模式 不具有
      RDB 持久化模式 不具有 服务器只会在特定条件下执行 BGSAVE
      AOF 持久化模式,且appendfsync 的值为 always 具有 程序总在执行命令后调用同步函数
      AOF 持久化模式,且appendfsync 的值为 everysec 不具有 程序每秒同步一次命令数据到硬盘
      AOF 持久化模式,且appendfsync 的值为 no 不具有 同步操作由操作系统决定
      服务器打开了 no-appendfsync-on-rewrite 选项 不具有 该选项打开时,服务器在执行 BGSAVEBGREWRITEAOF 命令时,会暂时停止对 AOF 文件进行同步(尽可能减少 I/O 阻塞)
    • 不管 Redis 在上面模式下运行,在事务最后加上 SAVE 命令总可以保证事务的耐久性。但因为效率低,不具有实用性;


最后

新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Redis | 第8章 发布订阅与事务《Redis设计与实现》

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Redis | 第8章 发布订阅与事务《Redis设计与实现》

目录前言《Redis常用命令及示例总结(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html1. 发布订阅1.1 频道的订阅与退订1.2 模式的订阅与退订1.3 发送消息1.4 查看订阅消息2. 事务2.1 事
Redis | 第8章 发布订阅与事务《Redis设计与实现》
2016-06-20

Redis | 第6章 事件与客户端《Redis设计与实现》

目录前言1. 事件1.1 文件事件1.1.1 I/O 多路复用程序的实现1.1.2 事件类型与 API1.1.3 文件事件的处理器1.2 时间事件1.2.1 API1.2.2 serverCron 函数1.3 事件的调度与执行2. 客户端2.1 客户端属性2.
Redis | 第6章 事件与客户端《Redis设计与实现》
2014-08-19

Redis | 第7章 Redis 服务器《Redis设计与实现》

目录前言1. 命令请求的执行过程1.1 发送命令请求1.2 读取命令请求1.3 命令执行器(1):查找命令实现1.4 命令执行器(2):执行预备操作1.5 命令执行器(3):调用命令的实现函数1.6 命令执行器(4):执行后续工作1.7 将命令回复发送给客户端
Redis | 第7章 Redis 服务器《Redis设计与实现》
2022-04-27

Redis | 第3章 对象《Redis设计与实现》

目录前言1. Redis对象概述1.1 对象的定义2. 字符串对象3. 列表对象3.1 quicklist 快速链表4. 哈希对象5. 集合对象6. 有序集合对象7. Redis对象的特点7.1 类型检查与命令多态7.2 内存回收7.3 对象共享7.4 对象的
Redis | 第3章 对象《Redis设计与实现》
2016-10-04

Spring boot+redis实现消息发布与订阅

一.创建spring boot项目 org.springframework.boot spring-boot-starter-data-redis org.spr
Spring boot+redis实现消息发布与订阅
2017-09-29

Redis | 第9章 Lua 脚本与排序《Redis设计与实现》

目录前言1. Lua 脚本1.1 Redis 创建并修改 Lua 环境的步骤1.2 Lua 环境协作组件1.3 EVAL 命令的实现1.4 EVALSHA 命令的实现1.5 脚本管理命令的实现1.6 脚本复制1.6.1 EVAL、SCRIPT FLUSH、SC
Redis | 第9章 Lua 脚本与排序《Redis设计与实现》
2017-01-01

Redis | 第4章 Redis中的数据库《Redis设计与实现》

目录前言1. Redis中的数据库2. 数据库的键空间3. 键的生成时间与过期时间4. Redis中的过期键删除策略5. AOF、RDB和复制功能对过期键的处理5.1 生成 RDB 文件5.2 载入 RDB 文件5.3 AOF 文件写入5.4 AOF 重写5.
Redis | 第4章 Redis中的数据库《Redis设计与实现》
2020-04-14

怎么利用Jedis实现Redis的订阅与发布

怎么利用Jedis实现Redis的订阅与发布?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是Redis发布订阅Redis发布订阅是一种消息通信模式,发送者通
2023-05-31

Redis | 第11章 服务器的复制《Redis设计与实现》

目录前言1. 旧版复制功能的实现1.1 同步与命令传播1.2 旧版复制功能的缺陷2. 新版复制功能的实现2.1 部分重同步的实现原理3. PSYNC 命令的实现4. 复制的详细步骤4.1 设置主服务器的地址和端口4.2 建立套接字连接4.3 发送 PING 命
Redis | 第11章 服务器的复制《Redis设计与实现》
2020-11-24

Redis | 第12章 Sentinel 哨兵模式《Redis设计与实现》

目录前言1. 启动并初始化 Sentinel2. Sentinel 与服务器间的默认通信2.1 获取主服务器信息2.2 获取从服务器信息2.3 向主服务器和从服务器发送信息3. 接受来自主服务器和从服务器的频道信息3.1 更新 Sentinel 字典3.2 创
Redis | 第12章 Sentinel 哨兵模式《Redis设计与实现》
2017-09-21

如何利用Redis实现分布式消息发布与订阅

如何利用Redis实现分布式消息发布与订阅引言:在分布式系统中,消息发布与订阅是一种常见的通信模式,可以实现不同模块之间的解耦。Redis作为一种高性能的键值对存储系统,可以用来实现分布式消息发布与订阅功能。本文将介绍如何使用Redis来实
如何利用Redis实现分布式消息发布与订阅
2023-11-07

Redis | 第5章 Redis 中的持久化技术《Redis设计与实现》

目录前言1. RDB 持久化1.1 RDB 文件的创建与载入1.2 自动间隔性保存1.2.1 设置保存条件1.2.2 dirty 计数器和 lastsave 属性1.2.3 检查保存条件是否满足1.3 RDB 文件1.3.1 RDB 的文件结构1.3.2 da
Redis | 第5章 Redis 中的持久化技术《Redis设计与实现》
2018-11-05

python中sub-pub机制怎么实现Redis的订阅与发布

本篇内容介绍了“python中sub-pub机制怎么实现Redis的订阅与发布”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!先介绍一下red
2023-07-05

SpringBoot整合Redis实现消息发布与订阅的示例代码

能实现发送与接收信息的中间介有很多,比如:RocketMQ、RabbitMQ、ActiveMQ、Kafka等,本文主要介绍了Redis的推送与订阅功能并集成SpringBoot的实现,感兴趣的可以了解一下
2022-11-13

Redis | 第10章 二进制数组、慢查询日志和监视器《Redis设计与实现》

目录前言1. 二进制位数组1.1 位数组的表示1.2 GETBIT 命令的实现1.3 SETBIT 命令的实现1.4 BITECOUNT 命令的实现1.5 BITOP 命令的实现2. 慢查询日志2.1 慢查询记录的保存2.2 慢查询日志的阅览与删除2.3 添加
Redis | 第10章 二进制数组、慢查询日志和监视器《Redis设计与实现》
2019-06-28

编程热搜

目录