workerman4 websocket集群消息同步核心是redis协调而非session复制:用redis维护用户路由表(online:user:id)、pub/sub广播消息、stream存离线消息、hash存会话元数据,并通过节点心跳实现故障感知。

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 缓存和数据结构管理技能。通过自然语言操作 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。










