Hyperf 中实现每日定点多进程定时任务,需配置 crontab 定时触发后,在 execute 方法中用 Co::parallel 多协程并发处理分片数据;CPU 密集型任务可配合 Process 组件启子进程;多实例部署时须用 Redis 分布式锁防重入。

Hyperf 中实现每日定点执行的多进程定时任务,核心在于结合 hyperf/crontab 组件与进程管理机制(如 hyperf/process 或协程并发),避免单点阻塞、提升执行稳定性。关键不是“开多个进程跑 cron”,而是让定时触发后,以多进程/多协程方式并行处理业务逻辑。
配置 crontab 实现每日定点触发
在 config/autoload/crontab.php 中注册定时任务,使用标准 cron 表达式指定时间(如每天 2:00 执行):
return [
[
'name' => 'daily-report-task',
'type' => 'command',
'rule' => '0 0 2 * * ?', // 每天凌晨 2:00
'singleton' => true,
'callback' => [App\Task\DailyReportTask::class, 'execute'],
'memo' => '生成昨日业务报表',
],
];
注意:Hyperf 的 crontab 默认是单进程主 tick 调度,不自动多进程;它只负责“准时唤起”,具体执行逻辑需自行做并发控制。
在任务类中启动多协程并发处理
推荐优先使用协程(轻量、高效),而非 fork 多进程(资源重、管理复杂)。在 execute() 方法中用 Co::parallel() 或 Parallel 组件分片执行:
- 将待处理数据按业务维度分组(如按商户 ID、地区、日期分区)
- 每组分配一个协程,设置合理超时和错误捕获
- 避免在协程内使用阻塞 IO(如未协程化 MySQL 同步查询)
示例片段:
$results = Co::parallel(
array_map(fn($shard) => fn() => $this->processShard($shard, $date), $shards),
10 // 最大并发数
);
foreach ($results as $error => $result) {
if ($error) {
Log::warning('Shard failed', ['shard' => $error]);
}
}
需要真正多进程时使用 Process 组件
若任务涉及 CPU 密集型操作(如图像压缩、加密计算),协程无法释放 CPU,此时可用 hyperf/process 启动子进程:
- 定义一个继承
AbstractProcess的进程类,复写handle() - 在定时任务中通过
ProcessManager::getInstance()->start(ProcessName::class)启动多个实例 - 建议配合信号监听或 IPC(如 Redis 队列)协调父子进程状态
注意:不要在 handle() 中直接写死循环,应设计为“启动→执行一次→退出”,由定时器统一调度更可控。
确保单机多实例部署时不重复执行
当服务部署多实例(如 Docker 多副本),需加分布式锁防止重复触发:
- 使用 Redis 锁(
set key val nx ex 3600)包裹整个定时逻辑 - 锁 key 建议含日期+任务名,如
crontab:daily-report:2024-06-15 - 执行完成后主动 del,或依赖过期自动释放
锁失败则直接 return,不报错也不重试,符合定时任务幂等设计原则。











