Workerman多进程下静态变量不共享是正常现象,因各子进程内存隔离,静态变量互不影响;跨Worker数据同步应选用shmop、Redis或文件轮询等方案,禁用APCu等进程级缓存。

Workerman多进程下静态变量不共享是正常现象,不是bug
因为每个Worker子进程是独立的PHP进程,启动时通过fork()复制主进程内存,但后续各自拥有完全隔离的地址空间。静态变量(如self::$cache、static $instances = [])就落在这个隔离内存里——A进程改了$count,B进程里的$count还是初始值,互不影响。
这和多线程完全不同:线程共享进程内存,静态变量天然可见;而Workerman是多进程模型,不存在“跨进程静态变量”这回事。
别试图用静态变量做跨Worker数据同步
常见错误场景:
- 在
onConnect里把$connection塞进static $clients,却没在onClose中unset,导致内存只增不减 - 用
static $counter = 0想统计全站连接数,结果每个Worker都从0开始计,数值永远不准 - 在
Worker::onWorkerStart里初始化Redis实例并赋给static $redis,误以为所有Worker共用一个连接
这些做法本质是混淆了“单进程内静态生命周期”和“多进程间状态协同”的边界。
真正可用的跨Worker共享方案
根据数据类型和性能要求选:
-
高频读写简单值(如计数器、开关):用
shmop扩展操作共享内存段,比网络IO快一个数量级,但需手动加锁(如flock) -
结构化数据或需持久化:走
Redis(推荐Pub/Sub或INCR/HSET),注意连接要懒加载+显式断连,避免连接对象内部引用泄漏 -
低频广播事件(如配置热更新):用
file_put_contents()写临时文件 +filemtime()轮询,简单可靠,无额外依赖 -
绝对避免:用
apcu_store()——APCu是进程级缓存,不跨Worker;也别碰opcacheAPI,它不提供跨进程写入能力
最容易被忽略的坑:Worker重启后静态变量重置
Workerman默认开启平滑重启(reload),这时旧Worker进程会等当前请求结束才退出,新Worker启动后所有静态变量都是全新初始化的。如果你依赖静态变量存“上次处理到哪条消息”,重启后就会重复消费或跳过数据。
真正需要跨重启保持的状态,必须落地到外部存储:Redis的SET、MySQL的INSERT ... ON DUPLICATE KEY UPDATE,或者本地file_get_contents()读取上一次保存的偏移量。静态变量只适合“本Worker生命周期内”的临时上下文,比如当前连接的用户ID绑定、本次请求的中间计算结果。

















