分布式环境下存在的问题
Web 应用中经常使用 WebSocket 进行实时通信。在分布式服务架构下,WebSocket 连接到某一个具体的服务实例上,会话状态只存在于该实例的内存中,无法跨实例通信。使用 Redis 作为消息总线或者连接管理层,可以实现跨实例连接管理、会话状态共享、消息广播。
Redis 的作用
- 连接注册表
使用 Map(userId, Session) 管理连接。
- 发布/订阅
使用 pub/sub 广播进行跨实例通信。某个实例接收到要发给特定用户的消息,广播此消息到所有实例,订阅此消息的实例接收到消息之后检查本地是否存在该用户连接,如果存在则发送消息到该用户。
可能存在的问题
消息投递不可靠
Redis 中的消息投递不可靠、无重试、无持久化,可能存在消息丢失的风险。
广播风暴
如果实例较多,即便只需要发送一条消息,也需要广播大量消息,而大量的消息因为无需处理而被丢弃,造成带宽、CPU 等资源的极大浪费。
优化方案
Redis Streams + Consumer Groups
使用 Redis Streams + 消费者组,支持消息持久化、ACK 确认、重试及回溯。
本地优先 + 定向广播
建立 连接-实例 注册表,优先检查本地连接,如果本地无该连接再向特定实例广播该消息,减少无效消息。
场景局限
适用于小规模系统(10 实例以内,QPS < 1k),可继续使用 Pub/Sub + 定向频道,简单高效。
中大型系统或需可靠性:强烈推荐 Redis Streams + 按实例分片,确保消息可靠性、避免广播风暴。