找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3692

积分

0

好友

507

主题
发表于 9 小时前 | 查看: 1| 回复: 0

我们将以“在线购物网站”作为例子贯穿全文,帮助大家理解Redis Pub/Sub在不同场景下的应用。

1. 什么是 Redis 的 Pub/Sub 机制

专业性描述

Redis Pub/Sub(发布/订阅)是一种消息通信模式,发送者(发布者)将消息发送到指定的频道,订阅了该频道的接收者(订阅者)都会收到此消息。这种模式实现了发布者和订阅者之间的解耦,发布者不需要知道订阅者的存在,订阅者也不需要知道发布者的存在。

大白话类比

这就像电台广播。电台(发布者)在某个频率(频道)上广播节目,所有调到这个频率的收音机(订阅者)都能收到节目。电台不知道有多少收音机在收听,收音机也不知道电台在哪里,它们只通过频率这个中介联系起来。

“在线购物网站”示例

假设我们有一个在线购物网站,当有新订单生成时,需要同时做以下几件事:

  1. 发送短信通知用户
  2. 更新商品库存
  3. 记录订单日志
  4. 更新用户积分

使用Redis Pub/Sub,我们可以让订单服务发布一个消息到 order.created 频道,其他服务订阅这个频道,各自处理自己的业务逻辑。

2. 应用场景:消息发布/订阅,模式订阅

2.1 基本发布/订阅

“在线购物网站”示例

订单服务发布订单创建消息:

# 订单服务发布消息
PUBLISH order.created “订单ID: 1001, 用户ID: 2001, 金额: 299.00”

短信服务订阅该频道:

# 短信服务订阅频道
SUBSCRIBE order.created
# 收到消息后,发送短信给用户

库存服务订阅该频道:

# 库存服务订阅频道
SUBSCRIBE order.created
# 收到消息后,减少库存

2.2 模式订阅

专业性描述

模式订阅允许订阅者通过通配符一次订阅多个频道。Redis支持两种通配符:* 匹配任意多个字符,? 匹配一个字符。

“在线购物网站”示例

假设我们有多个订单相关的事件:

  • order.created 订单创建
  • order.paid 订单支付
  • order.shipped 订单发货
  • order.completed 订单完成

日志服务希望订阅所有订单相关的事件:

# 使用模式订阅
PSUBSCRIBE order.*
# 这样会收到所有以“order.”开头的事件

3. Pub/Sub 的优点、缺点、适用场景

3.1 优点

  1. 解耦:发布者和订阅者不需要知道对方的存在,只需要关注频道。
  2. 实时性:消息发布后立即推送给所有订阅者。
  3. 扩展性:可以方便地增加新的订阅者,不影响现有系统。
  4. 简单易用:Redis命令简单,无需额外组件。

“在线购物网站”示例

当我们需要增加一个新的功能:订单成功后给用户发放优惠券。只需要新增一个优惠券服务,订阅 order.completed 频道即可,不需要修改订单服务。这种基于事件的通信方式非常适合构建松耦合的分布式系统

3.2 缺点

  1. 消息不可持久化:Redis Pub/Sub的消息是即时的,如果没有订阅者,消息就丢失了。订阅者掉线期间的消息也会丢失。
  2. 无消息堆积能力:如果订阅者处理速度慢,消息不会被缓存,会导致消息丢失。
  3. 无消息确认机制:发布者不知道消息是否被成功接收和处理。
  4. 不支持消息重试:如果处理失败,无法重新获取消息。

“在线购物网站”示例

假设短信服务在订单创建时宕机了,那么订单创建的消息就会丢失,用户收不到短信通知。而且即使短信服务恢复,也不会收到之前的消息。这对于关键业务来说是致命缺陷。

3.3 适用场景

  1. 实时通知:如在线聊天、实时弹幕。
  2. 事件广播:如配置更新、服务发现。
  3. 轻量级消息队列:对消息可靠性要求不高,允许少量丢失的场景。
  4. 解耦系统组件:组件间需要解耦,但不要求强可靠性的场景。

“在线购物网站”示例

适合使用Redis Pub/Sub的场景:

  • 用户登录/登出状态广播(用于在线用户列表)
  • 商品价格变化通知(前台展示实时更新)
  • 管理员操作广播(多个后台需要同步状态)

不适合使用Redis Pub/Sub的场景:

  • 订单支付结果通知(不能丢失)
  • 库存扣减消息(必须保证处理)
  • 积分变更记录(需要可靠传递)

4. List、Redis Pub/Sub、Redis Stream、专业级消息中间件的对比

下面我们通过“在线购物网站”的不同场景,对比这四种消息传递方式。

4.1 Redis List(列表)

专业性描述

Redis List是一个简单的列表数据结构,可以用作消息队列。生产者通过LPUSH添加消息,消费者通过RPOP或BRPOP获取消息。

“在线购物网站”示例

商品搜索服务将用户搜索关键词放入队列,异步分析搜索热点:

# 搜索服务生产消息
LPUSH search:keywords “iphone 15”
LPUSH search:keywords “华为mate60”
# 分析服务消费消息
BRPOP search:keywords 0

特点

  • 消息可持久化
  • 支持多个消费者,但每条消息只能被一个消费者获取
  • 简单,但功能有限
  • 无消息确认机制

4.2 Redis Pub/Sub(发布/订阅)

“在线购物网站”示例

用户下单后,需要同时通知多个服务:

# 订单服务发布
PUBLISH order.paid “订单ID: 1001, 金额: 299.00”
# 多个服务订阅
# 短信服务、库存服务、积分服务等

特点

  • 一对多广播
  • 实时推送
  • 消息不持久化
  • 无消息堆积能力

4.3 Redis Stream(流)

专业性描述

Redis 5.0引入的数据类型,专门为消息队列设计。支持消息持久化、消费者组、消息确认等特性。

“在线购物网站”示例

订单支付成功后的可靠消息传递:

# 支付服务生产消息
XADD order:payments * orderId 1001 userId 2001 amount 299.00
# 创建消费者组
XGROUP CREATE order:payments sms-group $ MKSTREAM
XGROUP CREATE order:payments stock-group $ MKSTREAM
# 不同消费者组独立消费
# 短信服务消费者组
XREADGROUP GROUP sms-group consumer1 COUNT 1 STREAMS order:payments >
# 库存服务消费者组
XREADGROUP GROUP stock-group consumer1 COUNT 1 STREAMS order:payments >

特点

  • 消息可持久化
  • 支持消费者组,同一消息可被不同组消费
  • 支持消息确认和重试
  • 功能丰富,接近专业消息队列

4.4 专业级消息中间件(如RabbitMQ、Kafka)

“在线购物网站”示例

大规模订单处理,需要高可靠性和高吞吐量:

  • Kafka:用于用户行为日志收集,海量日志数据
  • RabbitMQ:用于订单状态同步,需要复杂路由

特点

  • 功能最完整
  • 支持各种消息模式
  • 高可靠性、高可用性
  • 管理和运维复杂
  • 资源消耗较大

4.5 对比表格

特性 Redis List Redis Pub/Sub Redis Stream 专业消息中间件
消息持久化 支持 不支持 支持 支持
消息广播 不支持 支持 支持消费者组 支持
消息确认 不支持 不支持 支持 支持
消息重试 不支持 不支持 支持 支持
消息顺序 先进先出 无保证 有序 有序
吞吐量 中高
可靠性
复杂度 简单 简单 中等 复杂
适用场景 简单任务队列 实时通知广播 可靠消息队列 企业级应用

“在线购物网站”选择建议

  1. 实时在线人数统计:使用 Pub/Sub(实时性要求高,允许丢失)
  2. 订单支付结果通知:使用 Stream(需要可靠性,但不想引入复杂中间件)
  3. 用户行为日志收集:使用 Kafka(海量数据,高吞吐)
  4. 异步发送邮件:使用 List(简单,允许少量丢失)

5. 记忆技巧与实战要点

核心口诀
Pub/Sub是广播,实时推送不可少。
消息丢了不负责,适合通知和报警。
List能做简单队,一消费者消费掉。
Stream才是真队列,持久确认功能强。
专业中间件虽好,复杂场景再上场。

6. Redis Pub/Sub 应用架构图

Redis Pub/Sub在微服务中的架构示意图

图例解读

  1. 订单服务发布订单创建消息到 order.created 频道
  2. 短信、库存、积分、日志服务都订阅了这个频道,都会收到消息
  3. 用户服务发布用户注册消息到 user.registered 频道
  4. 日志和推送服务订阅了这个频道
  5. 商品服务发布价格更新消息到 price.updated 频道
  6. 日志和推送服务订阅了这个频道

通过这样的架构,各个服务之间完全解耦,新增服务只需要订阅感兴趣的频道,无需修改发布者代码。

7. 实战要点

选择依据

需要广播且允许丢失:用Pub/Sub
简单队列,单消费者:用List
需要可靠性,多消费者:用Stream
企业级复杂需求:用专业消息中间件

注意事项

  • Pub/Sub订阅后,客户端会阻塞等待消息,需要单独连接
  • Stream的消息不自动删除,需要定期清理
  • List作为队列时,注意处理消费者崩溃的情况
  • 专业消息中间件部署和维护成本较高

监控指标

  • Pub/Sub客户端数量
  • Stream消息堆积数
  • List队列长度
  • 消息处理延迟

容灾设计

  • Pub/Sub:订阅者断线重连后无法收到之前消息,需有补偿机制
  • Stream:配置合理的持久化策略
  • 重要业务:需要有死信队列和重试机制

性能优化

  • 批量处理消息
  • 合理设置消费者数量
  • 监控内存使用,避免消息堆积

总结

Redis Pub/Sub是一种简单高效的发布/订阅机制,非常适合实时通知、事件广播等场景。但在需要消息可靠性、持久化的场景下,应该选择Redis Stream或专业消息中间件。在实际应用中,需要根据业务需求、可靠性要求、系统复杂度等因素综合考虑,选择合适的消息传递方式。对于希望深入探讨更多后端架构与中间件选型的朋友,欢迎访问云栈社区进行交流。




上一篇:XiebroC2渗透测试框架实战:Go/.NET跨平台C2工具的功能解析与使用教程
下一篇:TiDB 数据库 SCHEMA 设计:关于表属性与函数的常见误区与正确答案
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-4 20:00 , Processed in 0.386082 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表