当前位置: 首页 > news >正文

Redis 发布订阅模式完全指南

引言

在前面的 Redis 文章中,我们学习了五种基本数据类型、持久化、主从复制和哨兵模式。今天要讲的是 Redis 的发布订阅功能——一种轻量级的消息通信模式。

发布订阅的核心思想很简单:有人发布消息到频道,订阅了该频道的人就能收到消息。这和微信公众号非常像——你关注了一个公众号(订阅频道),号主发文章(发布消息),你就能收到推送。

虽然专业消息队列(如 RabbitMQ、Kafka)功能更强大,但 Redis 的发布订阅足够轻量、零配置,适合中小型项目中的实时通知、聊天消息等场景。

第一部分:基础命令

一、订阅频道

# 语法:SUBSCRIBE 频道名 [频道名 ...] # 订阅一个或多个频道 # 终端1:订阅 news 和 sports 频道 127.0.0.1:6379> SUBSCRIBE news sports Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "news" 3) (integer) 1 1) "subscribe" 2) "sports" 3) (integer) 2

执行 SUBSCRIBE 后,客户端进入订阅模式,会一直阻塞等待消息,直到手动Ctrl+C退出。

二、发布消息

# 语法:PUBLISH 频道名 消息内容 # 终端2:向 news 频道发布消息 127.0.0.1:6379> PUBLISH news "今天科技圈发生了大事" (integer) 2 # 返回值 2 表示有 2 个订阅者收到了消息 # 向 sports 频道发布消息 127.0.0.1:6379> PUBLISH sports "CBA总决赛今晚打响" (integer) 2

终端1 收到的消息

为甚会出现这种\xe4此类信息呢,那他是错误的还是怎么回事???

原因:

其实收到\xe4\xbb...这样的数据,是因为Redis 客户端和服务器之间的编码/解码不一致

简单说:Redis 存进去的是"好的"中文,但你用来显示的程序把它当成了"原始字节码"直接打印了。(所以他们其实是一个东西,只是展示的样子不同罢了,就像不同语言一样汉语与英语)

那么如何解决呢?

在进入 Redis 之前,先设置一下编码,或者在连接时指定:

# 方法1:设置终端编码 export LANG=zh_CN.UTF-8 redis-cli # 方法2:连接时加上 --raw 参数(推荐) redis-cli --raw

加上--raw后,再XREADGET,应该就能直接显示中文了。

三、退订频道

# 语法:UNSUBSCRIBE [频道名 ...] # 不带参数则退订所有频道 127.0.0.1:6379> UNSUBSCRIBE news # 只退订 news 127.0.0.1:6379> UNSUBSCRIBE # 退订所有

第二部分:模式订阅

除了订阅具体频道,Redis 还支持模式匹配——订阅所有名称匹配某种模式的频道。

# 语法:PSUBSCRIBE 模式 [模式 ...] # 订阅所有以 "news." 开头的频道 127.0.0.1:6379> PSUBSCRIBE news.*

通配符规则

模式匹配不匹配
news.*news.sportsnews.technewssports.news
news.*.chinanews.tech.chinanews.sports.chinanews.china
*所有频道
# 测试 # 终端1:模式订阅 127.0.0.1:6379> PSUBSCRIBE news.* # 终端2:发布消息 127.0.0.1:6379> PUBLISH news.tech "AI 新突破" (integer) 1 # 终端1 收到: 1) "pmessage" # 模式消息类型 2) "news.*" # 匹配的模式 3) "news.tech" # 实际频道名 4) "AI 新突破" # 消息内容

普通订阅 vs 模式订阅

订阅方式命令收到消息格式用途
普通订阅SUBSCRIBEmessage订阅具体频道
模式订阅PSUBSCRIBEpmessage按模式匹配批量订阅

退订模式

# 语法:PUNSUBSCRIBE [模式 ...] 127.0.0.1:6379> PUNSUBSCRIBE news.*

第三部分:查看频道状态

# 查看当前活跃的频道(至少有一个订阅者) 127.0.0.1:6379> PUBSUB CHANNELS 1) "news" 2) "sports" # 查看匹配模式的活跃频道 127.0.0.1:6379> PUBSUB CHANNELS news.* 1) "news.tech" 2) "news.sports" # 查看某个频道的订阅者数量 127.0.0.1:6379> PUBSUB NUMSUB news sports 1) "news" 2) (integer) 3 # news 有 3 个订阅者 3) "sports" 4) (integer) 2 # sports 有 2 个订阅者 # 查看模式订阅的数量 127.0.0.1:6379> PUBSUB NUMPAT (integer) 2 # 当前有 2 个模式订阅

第四部分:实际应用场景

一、实时聊天系统

# 用户A 发送消息 PUBLISH room_101 "大家好,我是新来的" # 用户B、C、D(都订阅了 room_101)立即收到

二、系统通知推送

# 场景:电商系统,订单状态变更通知 # 用户下单后,订阅自己的订单频道 SUBSCRIBE order:10086 # 后台处理订单,状态变更时发布消息 PUBLISH order:10086 "您的订单已发货,快递单号:SF1234567890" # 用户收到实时通知

三、配置热更新

第五部分:C 语言实现发布订阅

一、发布者

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <hiredis/hiredis.h> int main() { // 连接 Redis redisContext *c = redisConnect("127.0.0.1", 6379); if (c == NULL || c->err) { printf("连接失败: %s\n", c->errstr); return -1; } // 发布消息 redisReply *reply = redisCommand(c, "PUBLISH news %s", "Hello, Redis 发布订阅!"); if (reply == NULL) { printf("发布失败\n"); return -1; } printf("订阅者数量: %lld\n", reply->integer); freeReplyObject(reply); redisFree(c); return 0; }

编译

gcc publisher.c -o publisher -lhiredis

二、订阅者

#include <stdio.h> #include <stdlib.h> #include <hiredis/hiredis.h> int main() { redisContext *c = redisConnect("127.0.0.1", 6379); if (c == NULL || c->err) { printf("连接失败: %s\n", c->errstr); return -1; } // 订阅频道 redisReply *reply = redisCommand(c, "SUBSCRIBE news"); if (reply == NULL) { printf("订阅失败\n"); return -1; } freeReplyObject(reply); // 循环接收消息 printf("等待消息...\n"); while (redisGetReply(c, (void**)&reply) == REDIS_OK) { if (reply->type == REDIS_REPLY_ARRAY && reply->elements == 4) { // 收到消息:[message, 频道名, 消息内容, 空] printf("频道: %s\n", reply->element[1]->str); printf("内容: %s\n", reply->element[2]->str); } freeReplyObject(reply); } redisFree(c); return 0; }

第六部分:发布订阅的局限性

缺点说明解决方案
消息不持久化订阅者不在线时发的消息会丢失改用 Redis Stream 或专业消息队列
无确认机制发布者不知道消息是否被处理改用 RabbitMQ(ACK 机制)
无消息堆积消息不会被存储,即发即忘改用 Kafka(持久化消息)
订阅者阻塞SUBSCRIBE 后客户端只能接收消息需要专门的连接处理

什么时候用 Redis 发布订阅?

场景是否适合
实时聊天✅ 适合
系统通知✅ 适合
配置热更新✅ 适合
订单处理(不能丢消息)❌ 不适合
金融交易(需要确认)❌ 不适合

总结

一、核心命令速查

命令作用
SUBSCRIBE channel订阅频道
UNSUBSCRIBE [channel]退订频道
PUBLISH channel msg发布消息
PSUBSCRIBE pattern模式订阅
PUNSUBSCRIBE [pattern]退订模式
PUBSUB CHANNELS查看活跃频道
PUBSUB NUMSUB查看订阅者数量

二、消息格式

订阅方式消息格式
普通订阅[message, 频道名, 消息内容]
模式订阅[pmessage, 模式, 频道名, 消息内容]

三、一句话记忆

Redis 发布订阅是一种轻量级消息通信模式,发布者通过 PUBLISH 向频道发消息,订阅者通过 SUBSCRIBE 实时接收。支持通配符模式匹配(PSUBSCRIBE),但不持久化、不确认,适合实时通知等场景,不适合关键业务消息。

http://www.jsqmd.com/news/906530/

相关文章:

  • 联想拯救者Y7000系列BIOS隐藏选项一键解锁终极指南
  • Arduino伺服电机控制:从PWM原理到安全项目实践
  • 别再只盯着时域波形了!通过伯德图‘看懂’直流电机双闭环的稳定性与快速性
  • 深度评测:LaserGRBL开源激光雕刻控制软件的技术架构与性能分析
  • Waves插件下载完整指南:2026最新版本安装教程与使用技巧
  • 小白也能轻松上手:用AI建站工具从注册到发布的极速实操指南
  • 易语言实战:手把手教你写一个CS1.6武器切换器(附完整源码与避坑点)
  • 5分钟掌握《重返未来:1999》智能小助手M9A:彻底解放你的游戏时间
  • 上位机知识篇---/script和/bin文件
  • OpenBoard:为什么这款开源Android输入法是你的隐私保护终极选择?
  • 2026年5月专业的铑水回收公司怎么选择厂家推荐榜,高浓度铑水、低浓度铑水、含杂铑水、废铑催化剂溶液厂家选择指南 - 海棠依旧大
  • 告别WebGL!用Unity Embedded Browser插件打造高性能PC端混合应用界面
  • 千问 LeetCode 2791. 树中可以形成回文的路径数 C语言实现
  • GD32 vs STM32:不只是主频和价格,深入聊聊Flash、功耗与ADC那些影响选型的细节
  • 千问 LeetCode 2801. 统计范围内的步进数字数目 Java实现
  • 2026年5月市面上开封大型彩灯制作厂家怎么选厂家推荐榜,大型灯组/巡游花车/民俗灯展/文旅夜游花灯厂家选择指南 - 海棠依旧大
  • 【Elasticsearch从入门到精通】第57篇:Elasticsearch查询性能优化——慢查询分析与优化策略
  • 租户冷热数据分离策略全解析,深度解读DeepSeek如何实现毫秒级租户切换与存储成本降47%
  • 如何快速实现代码高亮:hilite.me的终极指南
  • 深度解析:基于ODT的Microsoft Office自动化部署与配置管理指南
  • 从 Copilot 到 Autopilot 升级路线图 需要补齐的五个能力
  • OpenCV项目实战:给你的C++图像处理程序加上自定义字体和中文水印
  • Windows鼠标指针美化终极指南:免费获取macOS风格指针包
  • 2026年5月新消息:海南小户型设计团队如何选择与高效联系 - 2026年企业资讯
  • 关系运算符,逻辑运算符,三元运算符
  • 模块二,Agent的推理模式是什么
  • 开发者发布深度指南:将Claude Code从对话工具变为可运营智能体工作环境
  • 告别手动复位!用CPAL脚本的Signal Check和Reset函数,5分钟搞定自动化测试信号校验
  • Arduino RFID音乐乐器:从电感色码到交互设计的嵌入式实践
  • 5分钟快速上手:使用Unlock-Music在浏览器中解锁加密音乐文件完整指南