大家好,我是jobleap.cn的小九。
你想了解 Python 操作 Redis 的 Pub/Sub(发布/订阅)功能的使用方法、应用场景和解决的核心问题,这份教程会从核心概念、环境准备、API 详解到实战案例,全方位讲解 Redis Pub/Sub 在 Python 中的落地使用。
一、Redis Pub/Sub 核心概念与价值
1. 什么是 Redis Pub/Sub
Redis Pub/Sub 是 Redis 提供的发布/订阅消息通信模式:
- 发布者(Publisher):向指定的「频道(Channel)」发送消息,无需关心谁在接收。
- 订阅者(Subscriber):订阅一个或多个频道,持续监听频道内的消息,无需关心谁在发送。
- 核心特点:松耦合、实时性、一对多(一个发布者可向多个订阅者推送消息)。
2. 解决的核心问题
- 系统解耦:避免模块间直接调用,比如订单模块无需直接调用通知模块,只需向「订单完成」频道发消息,通知模块订阅该频道即可。
- 实时通信:实现服务间/客户端间的实时消息推送(如实时通知、聊天、监控告警)。
- 广播通知:一次发布,多个订阅者同时接收(如系统公告、配置更新推送)。
- 流量削峰:非核心流程通过 Pub/Sub 异步处理,避免主流程阻塞。
3. 典型应用场景
- 实时消息通知(如电商订单支付成功通知、用户注册欢迎语);
- 系统监控告警(如服务器CPU过高时推送告警消息);
- 微服务间异步通信;
- 聊天室、实时弹幕等互动场景;
- 配置中心的配置更新广播。
二、环境准备
1. 安装依赖
Python 操作 Redis 需安装 redis 库(推荐 4.x+ 版本),执行以下命令:
pip install redis
2. 确保 Redis 服务运行
- 本地 Redis:启动 Redis 服务(默认端口 6379,无密码);
- 远程 Redis:记录地址、端口、密码,后续连接时配置。
三、Python Redis Pub/Sub 常用 API 详解
1. 基础连接配置
首先初始化 Redis 连接,这是 Pub/Sub 的基础:
import redis
# 初始化 Redis 客户端(根据实际情况修改参数)
redis_client = redis.Redis(
host="localhost", # Redis 地址
port=6379, # Redis 端口
password="", # Redis 密码(无则留空)
db=0, # 使用的数据库编号
decode_responses=True # 自动将返回的字节串转为字符串(避免手动解码)
)
2. 发布者(Publisher)核心 API
发布者的核心操作是 publish(),向指定频道发送消息:
def publish_message(channel: str, message: str):
"""
向指定频道发布消息
:param channel: 频道名称
:param message: 要发送的消息
:return: 接收消息的订阅者数量
"""
# 核心 API:publish(频道名, 消息内容)
subscriber_count = redis_client.publish(channel, message)
print(f"向频道 {channel} 发布消息:{message}")
print(f"本次有 {subscriber_count} 个订阅者接收消息")
return subscriber_count
# 调用示例
if __name__ == "__main__":
publish_message("order_notify", "订单【123456】支付成功!")
关键说明:
publish(channel, message)返回值是「当前订阅该频道的在线订阅者数量」;- 消息内容可以是字符串、JSON 字符串(复杂数据推荐),示例中用简单字符串演示。
3. 订阅者(Subscriber)核心 API
订阅者需要创建「订阅对象」,并持续监听消息,核心 API 包括 pubsub()、subscribe()、listen():
def subscribe_channel(channel: str):
"""
订阅指定频道,持续监听消息
:param channel: 频道名称
"""
# 1. 创建 Pub/Sub 对象
pubsub = redis_client.pubsub()
# 2. 订阅指定频道(可订阅多个,如 subscribe(chan1, chan2))
pubsub.subscribe(channel)
print(f"已订阅频道 {channel},等待消息...\n")
# 3. 持续监听消息(阻塞式)
for message in pubsub.listen():
"""
message 是字典格式,核心字段:
- type: 消息类型(subscribe/psubscribe 表示订阅成功;message/pmessage 表示收到消息)
- channel: 消息所属频道
- data: 消息内容(type=message 时有效)
"""
if message["type"] == "message":
# 仅处理实际的消息(过滤订阅成功的通知)
print(f"收到频道 {message['channel']} 的消息:{message['data']}")
# 调用示例
if __name__ == "__main__":
subscribe_channel("order_notify")
关键说明:
pubsub():创建 Pub/Sub 操作对象,所有订阅/取消订阅都基于该对象;subscribe(channel1, channel2...):订阅一个或多个固定频道;listen():阻塞式监听消息,会一直运行直到手动停止(如 Ctrl+C);- 消息字典的
type字段需过滤:只有message类型是实际的业务消息,subscribe只是订阅成功的通知。
4. 进阶 API:模式订阅(Pattern Subscribe)
如果需要订阅「一类频道」(如所有以 notify_ 开头的频道),可使用 psubscribe():
def pattern_subscribe(pattern: str):
"""
模式订阅(匹配一类频道)
:param pattern: 匹配模式(如 notify_* 表示所有以 notify_ 开头的频道)
"""
pubsub = redis_client.pubsub()
# 模式订阅:匹配所有以 notify_ 开头的频道
pubsub.psubscribe(pattern)
print(f"已模式订阅 {pattern},等待消息...\n")
for message in pubsub.listen():
if message["type"] == "pmessage":
# 模式订阅的消息 type 是 pmessage
print(f"收到匹配频道 {message['channel']} 的消息:{message['data']}")
# 调用示例:订阅所有 notify_ 开头的频道
pattern_subscribe("notify_*")
5. 取消订阅
可通过 unsubscribe()/punsubscribe() 取消指定频道的订阅:
def unsubscribe_demo():
pubsub = redis_client.pubsub()
pubsub.subscribe("order_notify", "user_notify")
# 取消订阅单个频道
pubsub.unsubscribe("order_notify")
# 取消订阅所有频道
# pubsub.unsubscribe()
# 模式订阅的取消
# pubsub.punsubscribe("notify_*")
四、实战案例:实时订单通知系统
1. 需求场景
电商系统中,订单支付成功后,发布者向 order_notify 频道推送订单消息,两个订阅者分别处理:
- 订阅者1:发送短信通知用户;
- 订阅者2:记录订单日志到本地。
2. 完整代码实现
(1)发布者:订单支付成功后发布消息
# publisher.py
import redis
import json
# 初始化 Redis 客户端
redis_client = redis.Redis(
host="localhost",
port=6379,
password="",
decode_responses=True
)
def publish_order_success(order_id: str, user_phone: str, amount: float):
"""发布订单支付成功消息(用 JSON 封装复杂数据)"""
# 构造复杂消息体(推荐用 JSON 字符串)
message = json.dumps({
"order_id": order_id,
"user_phone": user_phone,
"amount": amount,
"timestamp": "2026-01-27 10:00:00"
})
# 发布到 order_notify 频道
redis_client.publish("order_notify", message)
print(f"订单 {order_id} 支付成功,已发布通知消息")
# 模拟订单支付成功
if __name__ == "__main__":
publish_order_success("OD20260127001", "13800138000", 99.0)
(2)订阅者1:短信通知
# subscriber_sms.py
import redis
import json
redis_client = redis.Redis(
host="localhost",
port=6379,
password="",
decode_responses=True
)
def send_sms_notify():
"""订阅订单频道,发送短信通知"""
pubsub = redis_client.pubsub()
pubsub.subscribe("order_notify")
print("短信通知服务已启动,等待订单消息...")
for message in pubsub.listen():
if message["type"] == "message":
# 解析 JSON 消息
order_data = json.loads(message["data"])
# 模拟发送短信(实际场景调用短信API)
print(f"【短信通知】用户 {order_data['user_phone']},您的订单 {order_data['order_id']} 支付成功,金额 {order_data['amount']} 元")
if __name__ == "__main__":
send_sms_notify()
(3)订阅者2:订单日志
# subscriber_log.py
import redis
import json
from datetime import datetime
redis_client = redis.Redis(
host="localhost",
port=6379,
password="",
decode_responses=True
)
def record_order_log():
"""订阅订单频道,记录订单日志"""
pubsub = redis_client.pubsub()
pubsub.subscribe("order_notify")
print("订单日志服务已启动,等待订单消息...")
for message in pubsub.listen():
if message["type"] == "message":
order_data = json.loads(message["data"])
# 模拟记录日志(实际场景可写入文件/数据库)
log_content = f"{datetime.now()} - 订单 {order_data['order_id']} 支付成功,金额 {order_data['amount']} 元,用户手机号 {order_data['user_phone']}"
with open("order_log.txt", "a", encoding="utf-8") as f:
f.write(log_content + "\n")
print(f"【日志记录】{log_content}")
if __name__ == "__main__":
record_order_log()
3. 运行与测试
- 启动 Redis 服务;
- 分别打开 3 个终端,依次运行:
- 终端1:
python subscriber_sms.py(启动短信订阅者); - 终端2:
python subscriber_log.py(启动日志订阅者); - 终端3:
python publisher.py(发布订单消息);
- 终端1:
- 观察终端1和终端2的输出,会实时收到订单消息并处理。
五、注意事项与避坑指南
- 消息不持久化:Redis Pub/Sub 是「即发即失」的,订阅者离线期间的消息会丢失,若需持久化消息,需使用 Redis Stream 或 Kafka;
- 阻塞监听:
listen()是阻塞式的,若需在主线程不阻塞,可结合多线程/多进程使用; - 连接稳定性:若 Redis 连接断开,订阅者需重新连接并订阅;
- 消息大小:Redis 单条消息不宜过大(建议 < 1MB),避免占用过多内存;
- 性能限制:Redis Pub/Sub 适合轻量级实时通信,高并发场景建议用专业消息队列(如 Kafka、RabbitMQ)。
总结
- 核心价值:Redis Pub/Sub 解决了系统解耦、实时通信、广播通知的问题,是轻量级的消息通信方案;
- 核心 API:发布用
publish(channel, message),订阅用pubsub().subscribe(channel)+listen(),模式订阅用psubscribe(); - 关键注意:消息不持久化、监听是阻塞式的,高可靠/高并发场景需结合其他组件(如 Stream、Kafka)。
这份教程覆盖了 Python Redis Pub/Sub 的核心用法和实战场景,你可以基于此扩展到自己的业务场景中,比如替换为实际的短信API、日志存储方案等。