Workerman 4 多进程下全局变量和静态数组无法共享状态,必须使用 Redis 等外部存储;Redis 通过连接池、原子命令和规范 key 设计实现高效、安全、可扩展的共享状态管理。

Workerman 4 多进程下不能靠全局变量或静态数组共享状态,因为每个 Worker 进程内存完全隔离。想让所有进程读写同一份数据,必须用外部统一存储,Redis 是最常用、最可靠的选择。
为什么全局变量在多进程里失效
Worker 进程启动后各自拥有独立的 PHP 内存空间。你在 onConnect 或控制器里写 $counter++ 或 static::$users = [...],这个变量只存在于当前进程。其他进程既看不到,也改不了,更不会同步。
- A 进程里
$count = 100,B 进程里$count还是初始值(甚至未定义) - 用
static存大数组,不仅不共享,还会导致内存持续增长、GC 清不掉 - 仅当
Worker::$processCount = 1(单进程调试)时,全局变量才“看起来有效”
用 Redis 实现真正共享状态
所有 Worker 进程通过 TCP 连接同一个 Redis 实例,读写的是同一份数据,天然支持并发、原子操作和跨机器扩展。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 计数器类场景:用
INCR user:login:total,多个进程同时调用也不会重复或丢失 - 状态标记类:如
SET user:1001:online 1 EX 300,配合过期时间自动清理 - 列表/集合类:用
LPUSH chat:room1 $msg+LTRIM做消息队列或最近记录 - 避免直接
GET+SET手动更新,优先用INCRBY、HINCRBY、SETNX等原子命令
连接管理必须走连接池
每次请求都 new Redis() 或 redis_connect(),等于每秒新建大量 TCP 连接,很快触发 Too many open files 或 Redis 拒绝连接。
- 推荐使用
webman/redis扩展(Workerman 官方维护),它内置连接池 - 在
config/redis.php中配置:'min_connections' => 2、'max_connections' => 20 - 业务中统一调用
Redis::get($key)、Redis::incr($key),底层自动复用连接 - 绝对不要在
onWorkerStart里 new 一个 Redis 实例然后赋给Worker::$redis—— 多进程共享连接句柄会出错
Key 设计要带业务域、参数签名和版本号
硬编码 user_list 或 cache 这类泛型 key,上线后极易引发缓存污染、环境串号、逻辑变更后数据不刷新等问题。
- 正确格式示例:
user:list:page_2:filter_status_1:v2 - 包含三要素:业务域(
user:list)、参数签名(page_2:filter_status_1)、版本号(v2) - 版本号用于快速清旧缓存,比如接口加了新字段,只需改
v2 → v3,旧 key 自然失效 - 不同环境(dev/staging/prod)建议用不同 Redis DB 或加前缀隔离,避免共用一套实例时 key 冲突

















