thinkphp 6 定时任务需自行实现状态持久化,核心是建 job_schedules 表记录生命周期;通过行锁或唯一索引防重复;执行中实时更新 status、progress、error_message;结合队列派发提升可靠性;并提供可视化监控与告警。

ThinkPHP 6 的定时任务本身不自带“状态持久化”能力——它只是按时间触发执行逻辑,任务是否成功、执行到哪一步、是否重试过,全靠开发者自己记录。所谓“进阶”,核心就是把任务的生命周期(调度、执行、失败、重试、完成)全部落库可查,而非依赖内存或临时变量。
用数据库表固化任务元信息
不能只靠 php think timer:run 或系统 cron 触发就完事。必须建一张任务状态表,例如 job_schedules:
- 字段建议:id、job_name(如 'send_daily_report')、status(0待执行/1运行中/2成功/3失败)、last_run_at、next_run_at、retry_count、max_retries、error_message、created_at、updated_at
- 关键动作:每次定时任务启动前,先查该 job_name 最近一条记录;若 status 是 1(运行中)且 last_run_at 超过阈值(比如5分钟),说明上次卡死,可标记为超时并允许抢占
-
避免重复执行:用数据库行锁(
SELECT ... FOR UPDATE)或唯一联合索引(job_name + date(current_date))控制单日仅跑一次
执行过程中的状态实时更新
别等整个任务跑完再写 success,中间关键节点也要落库:
- 刚进入任务体,立刻
Db::table('job_schedules')->where('job_name', $name)->update(['status' => 1, 'last_run_at' => date('Y-m-d H:i:s')]) - 每完成一个子步骤(如“已拉取用户列表”“已发送100封邮件”),更新
progress字段(int 类型,0–100)和log字段(JSON 或 TEXT 存摘要) - 捕获异常后,立即写入
error_message并递增retry_count,再判断是否达到max_retries
与队列联动实现可靠重试
纯定时命令容易因进程崩溃丢失上下文。更稳的做法是:定时脚本只负责“派发”,真正干活交给队列:
- 定时命令(如
app\command\DailyReportSchedule.php)不做业务,只调用Queue::push(new SendDailyReportJob()) -
SendDailyReportJob实现fire()方法,在里面做状态更新、分批处理、异常捕获 - 队列驱动用 Redis 或数据库,确保任务不丢;失败时自动进 delay 队列重试,同时更新数据库中对应 job 的 retry_count 和 error_message
提供可视化状态看板
光有数据不够,得能查、能筛、能告警:
- 后台加个「任务监控」页面,列出所有注册的 job_name,按 status 着色,显示 last_run_at、duration、progress
- 对连续失败 ≥3 次的任务,自动触发企业微信/钉钉通知
- 支持手动点击「重试」:不是重新 push 一个新 job,而是把原记录 status 改回 0,并清空 error_message,让下次调度自然接管
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











