引言在前面的 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 后客户端进入订阅模式会一直阻塞等待消息直到手动CtrlC退出。二、发布消息# 语法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 LANGzh_CN.UTF-8 redis-cli # 方法2连接时加上 --raw 参数推荐 redis-cli --raw加上--raw后再XREAD或GET应该就能直接显示中文了。三、退订频道# 语法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.sports、news.technews、sports.newsnews.*.chinanews.tech.china、news.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 或专业消息队列无确认机制发布者不知道消息是否被处理改用 RabbitMQACK 机制无消息堆积消息不会被存储即发即忘改用 Kafka持久化消息订阅者阻塞SUBSCRIBE 后客户端只能接收消息需要专门的连接处理什么时候用 Redis 发布订阅场景是否适合实时聊天✅ 适合系统通知✅ 适合配置热更新✅ 适合订单处理不能丢消息❌ 不适合金融交易需要确认❌ 不适合总结一、核心命令速查命令作用SUBSCRIBE channel订阅频道UNSUBSCRIBE [channel]退订频道PUBLISH channel msg发布消息PSUBSCRIBE pattern模式订阅PUNSUBSCRIBE [pattern]退订模式PUBSUB CHANNELS查看活跃频道PUBSUB NUMSUB查看订阅者数量二、消息格式订阅方式消息格式普通订阅[message, 频道名, 消息内容]模式订阅[pmessage, 模式, 频道名, 消息内容]三、一句话记忆Redis 发布订阅是一种轻量级消息通信模式发布者通过 PUBLISH 向频道发消息订阅者通过 SUBSCRIBE 实时接收。支持通配符模式匹配PSUBSCRIBE但不持久化、不确认适合实时通知等场景不适合关键业务消息。
Redis 发布订阅模式完全指南
发布时间:2026/5/29 0:57:11
引言在前面的 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 后客户端进入订阅模式会一直阻塞等待消息直到手动CtrlC退出。二、发布消息# 语法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 LANGzh_CN.UTF-8 redis-cli # 方法2连接时加上 --raw 参数推荐 redis-cli --raw加上--raw后再XREAD或GET应该就能直接显示中文了。三、退订频道# 语法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.sports、news.technews、sports.newsnews.*.chinanews.tech.china、news.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 或专业消息队列无确认机制发布者不知道消息是否被处理改用 RabbitMQACK 机制无消息堆积消息不会被存储即发即忘改用 Kafka持久化消息订阅者阻塞SUBSCRIBE 后客户端只能接收消息需要专门的连接处理什么时候用 Redis 发布订阅场景是否适合实时聊天✅ 适合系统通知✅ 适合配置热更新✅ 适合订单处理不能丢消息❌ 不适合金融交易需要确认❌ 不适合总结一、核心命令速查命令作用SUBSCRIBE channel订阅频道UNSUBSCRIBE [channel]退订频道PUBLISH channel msg发布消息PSUBSCRIBE pattern模式订阅PUNSUBSCRIBE [pattern]退订模式PUBSUB CHANNELS查看活跃频道PUBSUB NUMSUB查看订阅者数量二、消息格式订阅方式消息格式普通订阅[message, 频道名, 消息内容]模式订阅[pmessage, 模式, 频道名, 消息内容]三、一句话记忆Redis 发布订阅是一种轻量级消息通信模式发布者通过 PUBLISH 向频道发消息订阅者通过 SUBSCRIBE 实时接收。支持通配符模式匹配PSUBSCRIBE但不持久化、不确认适合实时通知等场景不适合关键业务消息。