Redis 的发布订阅(Pub/Sub)是一种基于消息的通信模式,用于实现不同组件、服务或客户端之间的异步通信。它遵循 "发布者 - 订阅者" 模型,核心思想是解耦消息的发送者(发布者)和接收者(订阅者),使它们无需直接交互即可传递信息。
核心概念
-
频道(Channel)消息的传输媒介,类似广播电台的频率。发布者向指定频道发送消息,订阅者通过订阅频道接收消息。频道是动态创建的,无需提前定义,首次被引用时自动创建。
-
发布者(Publisher)发送消息的一方,无需关心谁在接收消息,只需将消息发送到指定频道。
-
订阅者(Subscriber)接收消息的一方,需提前订阅感兴趣的频道。订阅后,会收到该频道所有新发布的消息(历史消息不会被回溯)。
基本工作流程
- 订阅者通过
SUBSCRIBE命令订阅一个或多个频道。 - 发布者通过
PUBLISH命令向指定频道发送消息。 - Redis 服务器将消息实时推送给所有订阅了该频道的订阅者。
- 订阅者可通过
UNSUBSCRIBE命令取消订阅。
关键特性
- 实时性:消息一经发布,立即推送给订阅者(无持久化,错过即丢失)。
- 多对多通信:一个频道可被多个订阅者订阅,一个发布者可向多个频道发送消息。
- 模式匹配:支持通过
PSUBSCRIBE命令订阅符合特定模式的频道(如news_*匹配所有以news_开头的频道)。 - 轻量级:协议简单,性能高效,适合高频次、低延迟的消息传递。
适用场景
- 实时通知:如系统通知、状态更新、聊天消息等。
- 事件广播:分布式系统中,一个服务的事件需要被多个服务感知(如订单状态变更通知库存、支付等服务)。
- 日志收集:多个应用实例将日志发送到指定频道,由一个集中服务订阅并处理。
- 简单的消息队列:虽然功能有限,但可快速实现简单的生产者 - 消费者模型。
局限性
- 无消息持久化:若订阅者离线,期间的消息会丢失(需持久化可考虑 Redis Stream 或专业消息队列)。
- 无消息确认机制:Redis 不保证消息一定被订阅者接收。
- 阻塞式接收:订阅者接收消息是阻塞的,需单独线程 / 进程处理。
py程序示例
import redis
import threading
import time
# 连接 Redis 服务器
# 注意:请根据实际情况修改 Redis 连接参数
r = redis.Redis(
host='localhost',
port=6379,
db=0,
decode_responses=True # 自动解码为字符串,避免bytes类型
)
def publisher(channel):
"""发布者函数:向指定频道发送消息"""
try:
count = 1
while True:
message = f"这是第 {count} 条消息"
# 发布消息到指定频道
r.publish(channel, message)
print(f"已发布: {message} 到频道 {channel}")
count += 1
time.sleep(2) # 每2秒发送一条消息
except KeyboardInterrupt:
print("\n发布者已停止")
def subscriber(channel):
"""订阅者函数:从指定频道接收消息"""
try:
# 创建订阅对象
pubsub = r.pubsub()
# 订阅指定频道
pubsub.subscribe(channel)
print(f"已订阅频道 {channel},等待消息...")
# 循环监听消息
for message in pubsub.listen():
# 过滤掉订阅确认消息
if message['type'] == 'message':
print(f"\n收到消息: {message['data']} 来自频道 {message['channel']}")
except KeyboardInterrupt:
print("\n订阅者已停止")
if __name__ == "__main__":
# 定义要使用的频道名称
channel_name = "demo_channel"
# 创建并启动订阅者线程
sub_thread = threading.Thread(target=subscriber, args=(channel_name,), daemon=True)
sub_thread.start()
# 等待订阅者准备就绪
time.sleep(1)
# 启动发布者
try:
publisher(channel_name)
except KeyboardInterrupt:
print("\n程序已退出")
总结
Redis Pub/Sub 是一种轻量级、实时的消息通信模式,适合对消息可靠性要求不高、追求简单高效的场景。若需要消息持久化、重试机制等高级功能,可考虑 Redis Stream 或 Kafka、RabbitMQ 等专业消息队列。

910

被折叠的 条评论
为什么被折叠?



