聊聊 Redis 的高级特性之一: 发布订阅

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。图中,消费者1和消费者2 订阅了 Redis 服务的频道 channel ,当生产者通过 PUBLISH 命令发送给频道 channel 时, 这个消息就会被发送给订阅它的两个客户端。

这篇文章,我们聊聊 Redis 的高级特性之一: 发布订阅

1 发布订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

图中,消费者1和消费者2 订阅了 Redis 服务的频道 channel ,当生产者通过 PUBLISH 命令发送给频道 channel 时, 这个消息就会被发送给订阅它的两个客户端。

下表列出了 Redis 发布订阅常用命令:

命令 用法 描述
PSUBSCRIBE PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道
PUBSUB PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态
PUBLISH PUBLISH channel message 将信息发送到指定的频道
PUNSUBSCRIBE PUNSUBSCRIBE [pattern [pattern ...]] 退订所有给定模式的频道
SUBSCRIBE SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息
UNSUBSCRIBE UNSUBSCRIBE [channel [channel ...]] 指退订给定的频道

2 客户端演示

我们开启两个 redis-cli 客户端,演示了发布订阅是如何工作的。

客户端 A 执行订阅命令:

subscribe mychannel
AI 代码解读

订阅命令执行成功后:

客户端 B 执行发布命令:

publish mychannel helloworld
AI 代码解读

发布命令执行成功后,客户端 A 就会接收到新的消息:

3 实现原理

每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构, 结构的 pubsub_channels 属性是一个字典, 这个字典就用于保存订阅频道的信息:

struct redisServer {
    // ...
    dict *pubsub_channels;
    // ...
};
AI 代码解读

其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。

下图中, client2 、 client5 和 client1 就订阅了 channel1 , 而其他频道也分别被别的客户端所订阅:

当客户端调用 SUBSCRIBE 命令时, 程序就将客户端和要订阅的频道在 pubsub_channels 字典中关联起来。

举个例子,如果客户端 client10086 执行命令 SUBSCRIBE channel1 channel2 channel3 ,那么前面展示的 pubsub_channels 将变成下面这个样子:

当调用 PUBLISH channel message 命令, 程序首先根据 channel 定位到字典的键, 然后将信息发送给字典值链表中的所有客户端。

如果某个客户端执行命令 PUBLISH channel1 "hello moto" ,那么 client2 、 client5 和 client1 三个客户端都将接收到 "hello moto" 信息:

4 适用场景

在使用发布订阅功能时,需要理解两点。

1、保证先让消费者先订阅队列,然后再让生产者发布消息。

如果消费者异常挂掉并重新上线,它只能接收新的消息。在其下线期间,生产者发布的消息将无法被消费者接收,因为找不到该消费者,这些消息会被丢弃。

如果所有消费者都下线,那么生产者发布的消息将因为没有任何消费者而全部被丢弃。

2、发布订阅不具备数据持久化的能力

发布订阅相关的操作不会被写入到 Redis 数据库(RDB)或追加写入文件(AOF)中。如果 Redis 宕机并重新启动,Pub/Sub 的数据将会全部丢失。

基于上面的分析,发布订阅功能特别适合对少量消息丢失不敏感通知类型的场景。

5 实战演示

笔者开源了一个短信服务,为了提升系统性能,应用信息存储在本地内存中,定时任务会每隔30秒重新刷新一次缓存。

但在分布式部署的场景下,不同应用间的本地内存数据可能因为执行时间差异导致数据不同步。

基于这样的场景,我们可以使用 Redis 的发布订阅功能,实现本地内存的及时刷新。

1、配置 Redis 频道监听器容器

2、触发发布消息

当应用发送变化时,比如新增、修改、删除,则调用发送消息到频道方法。

下图,当我们启动两个短信平台应用,在控制台修改应用信息时,我们发现两个应用的本地内存都发生变化了。

6 总结

  1. Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

​ 消费者1和消费者2 订阅了 Redis 服务的频道 channel ,当生产者通过 PUBLISH 命令发送给频道 channel 时, 这个消息就会被发送给订阅它的两个客户端。

  1. 在使用发布订阅功能时,需要理解两点。

    • 保证先让消费者先订阅队列,然后再让生产者发布消息。

    • 发布订阅不具备数据持久化的能力。

  2. 发布订阅功能特别适合对少量消息丢失不敏感通知类型的场景。

  3. 笔者开源的短信平台项目,使用了 Redis 的发布订阅功能实现本地内存的实时同步。

短信平台地址https://github.com/makemyownlife/platform-sms


参考资料:

https://redisbook.readthedocs.io/en/latest/feature/pubsub.html

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
打赏
0
0
0
0
252
分享
相关文章
Redis设计与实现——Redis命令参考与高级特性
Redis 是一个高性能的键值存储系统,支持丰富的数据类型(字符串、列表、哈希、集合等)和多种高级功能。本文档涵盖 Redis 的核心命令分类,包括数据类型操作、事务与脚本、持久化、集群管理、系统监控等。特别介绍了事务的原子性特性、Lua 脚本的执行方式及优势、排序机制、发布订阅模型以及慢查询日志和监视器工具的使用方法。适用于开发者快速掌握 Redis 常用命令及其应用场景,优化系统性能与可靠性。
Redis的基本特性以及其基础命令用法
这只是冰山一角,Redis的强大功能和简洁的操作方法值得我们深入了解和掌握,是复杂数据问题解决的有力工具。所以,来一场有趣的Redis冒险吧!
123 6
|
9月前
|
Redis 发布订阅
10月更文挑战第18天
79 1
Redis 发布订阅
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
150 10
【redis】redis的特性和主要应用场景
【redis】redis的特性和主要应用场景
590 2
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
本文全面阐述了Redis事务的特性、原理、具体命令操作,指出Redis事务具有原子性但不保证一致性、持久性和隔离性,并解释了Redis事务的适用场景和WATCH命令的乐观锁机制。
1085 0
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
18)Redis 的发布订阅模型
18)Redis 的发布订阅模型
117 0
Redis快速度特性及为什么支持多线程及应用场景
Redis快速度特性及为什么支持多线程及应用场景
211 11
Lettuce的特性和内部实现问题之Redis的管道模式提升性能的问题如何解决
Lettuce的特性和内部实现问题之Redis的管道模式提升性能的问题如何解决
112 0
Lettuce的特性和内部实现问题之Lettuce天然地使用管道模式与Redis交互的问题如何解决
Lettuce的特性和内部实现问题之Lettuce天然地使用管道模式与Redis交互的问题如何解决
130 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问