Rust中Redis Pub/Sub问题:消息无法接收
Redis Pub/Sub 消息无法接收的问题分析与修复
核心错误点
- 消息发布早于订阅建立:代码先执行
publish发送消息,之后才将连接转为PubSub模式并订阅频道,此时消息已发送完毕,订阅者完全没机会接收。 - 同步连接误用在异步环境:
get_connection()是同步Redis连接,但你用了#[tokio::main]的异步主函数,应该使用redis crate提供的异步API。 - 单连接模式冲突:同一个Redis连接不能同时执行普通命令(如publish)和PubSub操作,
as_pubsub()会将连接切换到PubSub专属模式,后续无法再用该连接执行普通操作。
修正后的代码
使用异步API,分离发布与订阅的连接(实际场景中通常是不同进程/服务,这里用异步任务模拟):
use redis::{AsyncCommands, Client, RedisError}; #[tokio::main] async fn main() -> Result<(), RedisError> { // 初始化Redis客户端 let client = Client::open("redis://127.0.0.1/")?; println!("Successfully connected to Redis!"); let channel = "mychannel"; let message = "hello"; // 启动订阅异步任务 tokio::spawn(async move { // 创建异步连接用于订阅 let mut pubsub = client.get_async_connection().await?.into_pubsub(); pubsub.subscribe(channel).await?; println!("subscribed to mychannel"); loop { println!("waiting for message"); let msg = pubsub.get_message().await?; let payload: String = msg.get_payload()?; println!("Received data on mychannel: {}", payload); println!("got message"); } }); // 等待订阅任务完成初始化(避免发布过早) tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; // 创建单独的异步连接用于发布消息 let mut con = client.get_async_connection().await?; con.publish(channel, message).await?; println!("message published"); // 保持程序运行,等待接收消息 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; Ok(()) }
关键修正说明
- 改用异步API:引入
AsyncCommandstrait,使用get_async_connection()获取异步连接,适配tokio异步运行环境。 - 分离发布与订阅连接:发布和订阅使用独立的Redis连接,避免模式冲突问题。
- 调整执行顺序:先启动订阅任务,短暂等待确保订阅建立后再发布消息,保证消息能被正常接收。
- 异步任务管理:用
tokio::spawn将订阅逻辑放到后台异步任务,主任务负责发布消息并维持程序运行。
内容的提问来源于stack exchange,提问作者Segmentation fault
相关产品推荐
相关产品推荐

