ThinkPHP 5.1 中使用 Swoole Atomic 实现跨请求计数,需将应用切换为 Swoole HTTP Server 模式,在 onWorkerStart 初始化 Atomic 实例并挂载至 $server,于 onRequest 中安全读写;FPM 环境下不可用,可选 Redis、APCu 或 MySQL 替代。

ThinkPHP 5.1 默认运行在 PHP-FPM 模式下,每个请求都是独立进程,无法直接共享变量。若需跨请求、跨进程的计数功能(比如限流、统计在线人数、全局自增 ID),必须借助外部共享存储或进程间通信机制。Swoole 的 Atomic 提供了无锁、线程/进程安全的整型计数器,但要注意:它仅在 Swoole Server(如 HttpServer、WebsocketServer)中有效,不能直接用于 FPM 环境。因此,“在 ThinkPHP 5.1 中使用 Swoole Atomic”实际是指:将 TP5.1 应用以 Swoole HTTP 服务器方式运行,并在其回调中使用 Atomic。
前提:启用 Swoole 并切换为 Swoole Server 模式
TP5.1 官方不原生支持 Swoole,需手动集成。常见做法是绕过框架入口,用 Swoole 启动 HTTP 服务,再将请求委托给 TP 内核处理(类似 Swoole + ThinkPHP 的 bridge 方案)。这意味着:
- PHP 环境必须已安装 Swoole 扩展(建议 ≥ 4.4.0)
- 启动脚本(如 server.php)替代传统的 php-fpm/nginx 入口
- 所有请求由 Swoole Worker 进程处理,而非 CGI/FPM 进程,这才具备使用 Atomic 的条件
创建和使用 Atomic 计数器
Atomic 实例在 Swoole Server 生命周期内全局有效,可在 onStart/onWorkerStart/onRequest 等回调中初始化一次,然后在 onRequest 中读写。例如:
- 在 onWorkerStart 中创建 Atomic 实例(避免重复创建),并绑定到 Server 对象属性上
- 在 onRequest 中调用
$server->atomic->add(1)或$server->atomic->get() - Atomic 是进程级共享,同一 Worker 内多个协程可安全访问;不同 Worker 需共用同一个 Atomic 实例(Swoole 自动保证跨 Worker 原子性)
与 ThinkPHP 协同的关键点
由于 TP5.1 的 Request/Response 是基于 PHP 超全局变量和输出缓冲设计的,而 Swoole 的 onRequest 回调接收的是 $request 和 $response 对象,需做适配:
立即学习“PHP免费学习笔记(深入)”;
- 将 Swoole $request 的 get/post/server 等数据注入 TP 的 Request 对象(可通过反射或手动赋值)
- 捕获 TP 的输出内容(ob_start + ob_get_clean),再用
$response->end()发送 - Atomic 实例建议挂载在 Swoole Server 实例上(如
$server->counter = new \Swoole\Atomic();),便于在回调中统一访问
替代方案对比(当无法用 Swoole 时)
如果项目仍运行在 FPM 下,无法使用 Atomic,则需其他共享机制:
- Redis INCR:最常用,性能好、天然分布式,适合高并发计数
- APCu:单机共享,速度快,但不支持多机器,且 FPM 进程重启后丢失
- MySQL 自增/UPDATE … SET count = count + 1:强一致性,但性能瓶颈明显,仅适合低频场景
- Swoole Table:比 Atomic 更灵活(支持字符串、多字段),但内存占用略高,也仅限 Swoole 环境



















