Workerman4 多服务器节点 websocket 集群,消息同步 redis 实现方案

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 36 浏览 0 回复
Workerman4 WebSocket集群消息同步核心是Redis协调而非Session复制:用Redis维护用户路由表(online:user:id)、Pub/Sub广播消息、Stream存离线消息、Hash存会话元数据,并通过节点心跳实现故障感知。

workerman4 多服务器节点 websocket 集群,消息同步 redis 实现方案

Workerman4 多服务器节点 WebSocket 集群中,消息同步不能靠“复制 Session”或“共享内存”,因为 WebSocket 连接是绑定在具体进程和 TCP socket 上的本地资源。Redis 不是用来存连接本身,而是作为全局状态协调中心——它解决的是“谁在哪、消息该发给谁、掉线了怎么补”这三个核心问题。

用 Redis 维护在线用户路由表

每个节点在用户成功建立 WebSocket 连接后,立刻往 Redis 写一条带过期时间的记录:

  • Key:`online:user:10086`
  • Value:`{"node":"node-a","sid":"abc123","ts":1727960520}`(含节点标识、会话唯一 ID、时间戳)
  • 使用 `SET online:user:10086 "..." EX 60`,确保连接断开后自动清理

这样,当业务系统(比如聊天服务)要给用户 10086 推送消息时,先查 Redis 知道他在 node-a 节点,再通过内部通信机制(如 Redis Pub/Sub 或 HTTP RPC)把消息定向投递给 node-a,由它完成本地 Session 推送。

用 Redis Pub/Sub 做跨节点消息广播通道

不依赖节点间直连,所有节点都订阅同一个频道(例如 `ws:msg:global`),业务方发消息时只往这个频道 publish 一次:

  • 消息体示例:{"to_user":10086,"content":"hello","from_user":10001}
  • 每个节点收到后,检查本地是否持有该用户的连接(查自己维护的 `userSidMap` 或直接查 Redis 的在线路由)
  • 若本地有连接,直接调用 $connection->send();否则忽略

这种方式天然支持横向扩容,新增节点只需启动时订阅频道即可接入整个消息分发网络。

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载

用 Redis Stream 存离线消息与会话快照

用户掉线期间产生的消息不能丢,需暂存在 Redis Stream 中:

  • Stream key:`offline:msg:10086`
  • 每条消息包含完整上下文(发送方、内容、时间、消息 ID)
  • 用户重连后,节点从 Stream 拉取未读消息(用 XREAD COUNT 50 STREAMS offline:msg:10086 $ 或按 ID 回溯)
  • 配合 `XACK` 标记已消费,避免重复推送

同时可将关键会话元数据(如最后活跃时间、设备类型)用 Hash 存到 `session:meta:abc123`,供其他模块快速查询,无需反序列化整个连接对象。

节点注册与心跳保活必须统一管理

集群需要一个全局可见的节点视图,否则无法做路由决策:

  • 每个 Workerman4 节点启动时,向 Redis 写入临时节点信息:SET node:node-a '{"ip":"10.0.1.10","port":2346,"ts":1727960520}' EX 30
  • 定时任务每 15 秒刷新一次 TTL,超时未刷新则认为节点下线
  • 路由逻辑查 `online:user:10086` 得到 node-a 后,再查 `node:node-a` 确认其是否存活,避免向已宕机节点转发

这套机制让集群具备故障感知能力,不需要额外引入 ZooKeeper 或 etcd。

评论0
回复 · 0
还没有回复
微信客服 微信客服 QQ官方交流群 QQ官方交流群