ThinkPHP6原生不支持秒级定时任务,需采用Linux cron+sleep脚本或Swoole定时器实现;推荐独立PHP脚本配合flock锁、时间校准及守护机制,避免框架开销与并发问题。

ThinkPHP6 本身不内置秒级定时任务支持,官方的 think-scheduler 扩展仅支持分钟级(最小粒度为 1 分钟)。若需真正秒级执行(如每 5 秒、每 30 秒触发),需绕过框架调度器,采用系统级或进程级方案实现。
使用 Linux cron + PHP 脚本(推荐,稳定可靠)
cron 最小单位是分钟,但可通过循环脚本+sleep 实现秒级精度。关键在于:不依赖 TP 的命令行入口,而是用独立 PHP 脚本执行逻辑,避免框架初始化开销和并发阻塞。
- 写一个纯 PHP 脚本(如
/path/to/second_task.php),直接 require 自动加载器,手动实例化必要类,调用业务方法 - 脚本内用
while(true)+sleep(5)控制间隔,加时间校准(如记录上一次执行时间,动态调整 sleep 值防累积误差) - 通过 systemd 或 nohup 后台常驻运行:
nohup php /path/to/second_task.php > /dev/null 2>&1 & - 配合 cron 每分钟拉起一次守护检查(防崩溃退出),例如:
* * * * * pgrep -f "second_task.php" || php /path/to/second_task.php > /dev/null 2>&1 &
利用 Swoole 定时器(适合已用 Swoole 的项目)
若项目基于 Swoole(如 Hyperf 或自建 Swoole Server),可直接用 Swoole\Timer::tick() 实现毫秒级精度,完全脱离 CLI 生命周期限制。
- 在 Swoole 启动后(如
onWorkerStart回调中)注册定时器:Swoole\Timer::tick(5000, function() { /* 执行你的 TP 逻辑,注意不能用 $this->app 等 CLI 上下文 */ }); - 业务逻辑需轻量,避免阻塞事件循环;数据库/Redis 操作建议用协程客户端(如
swoole_mysql或co\Redis) - 注意:不能直接调用 ThinkPHP 的命令行命令(如
php think task:run),因其依赖同步 CLI 环境
避免踩坑的关键细节
秒级任务对稳定性、资源占用和并发安全更敏感,以下几点必须处理:
-
进程唯一性:防止重复启动多个实例,可用文件锁(
flock)、Redis SETNX 或数据库唯一键控制 - 异常隔离:单次执行异常不能中断整个循环,必须 try-catch 并记录错误日志,继续下一轮
-
时间漂移控制:单纯
sleep(5)在高负载下会延迟,建议每次执行前计算与预期时间的偏差,动态修正 sleep 值 -
TP 实例复用:不要在循环内反复 new App 或调用
App::getInstance();可初始化一次,复用容器和服务(注意多协程下非线程安全对象需隔离)
不建议的方式
以下方法看似简单,实际问题明显,应避免:
- 在 Web 请求中用
sleep()模拟秒级轮询 —— 阻塞用户、耗尽 PHP-FPM 进程、无法保证准时 - 用 AJAX 轮询触发
php think xxx命令 —— CLI 初始化开销大、并发高时 fork 失败、无进程管理 - 强行修改
think-scheduler源码支持秒级 —— 调度器设计基于 Cron 表达式,硬改会导致时间错乱和任务堆积
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











