Appearance
定时任务
MineShop 使用 Hyperf 的 Crontab 组件实现定时任务,支持秒级调度和分布式锁。
🎯 任务列表
| 任务 | 执行周期 | 说明 |
|---|---|---|
| SeckillActivityStatusCrontab | 每10分钟 | 秒杀活动状态推进 |
| GroupBuyExpireCrontab | 每5分钟 | 团购过期处理 |
| OrderAutoCloseCrontab | 每分钟 | 订单自动关闭 |
| StatisticsAggregateCrontab | 每小时 | 统计数据聚合 |
| GeoRegionSyncCrontab | 每天凌晨 | 地区数据同步 |
📦 任务实现
秒杀状态推进
php
// SeckillActivityStatusCrontab.php
#[Crontab(
name: 'seckill-activity-status',
rule: '* */10 * * * *', // 每10分钟
callback: 'execute',
memo: '秒杀活动状态自动推进'
)]
class SeckillActivityStatusCrontab
{
public function execute(): void
{
// 1. 处理待开始的场次(30分钟内)
$this->processPendingSessions();
// 2. 处理已过期的场次
$this->processExpiredSessions();
// 3. 联动激活活动
$this->processActivityStart();
// 4. 联动结束活动
$this->processActivityEnd();
}
}待开始场次处理
php
private function processPendingSessions(): void
{
// 查找30分钟内即将开始的场次
$sessions = $this->sessionRepository->findPendingSessionsWithinMinutes(30);
foreach ($sessions as $session) {
try {
$startTime = Carbon::parse($session->start_time);
if ($startTime->lte(Carbon::now())) {
// 已到开始时间,立即激活并预热缓存
$this->sessionService->start($session->id);
$this->cacheService->warmSession($session->id);
} else {
// 未到开始时间,推送延迟任务
$delaySeconds = (int) $startTime->diffInSeconds(Carbon::now());
$this->driverFactory->get('default')->push(
new SeckillSessionStartJob($session->id),
$delaySeconds
);
}
} catch (\Throwable $e) {
$this->logger->error('处理待开始场次失败', [
'id' => $session->id,
'error' => $e->getMessage()
]);
}
}
}过期场次处理
php
private function processExpiredSessions(): void
{
foreach ($this->sessionRepository->findActiveExpiredSessions() as $session) {
try {
// 跳过已取消或已售罄的场次
if (in_array($session->status, ['cancelled', 'sold_out'])) {
continue;
}
$this->sessionService->end($session->id);
$this->logger->info('场次已结束', ['id' => $session->id]);
} catch (\Throwable $e) {
$this->logger->error('处理过期场次失败', [
'id' => $session->id,
'error' => $e->getMessage()
]);
}
}
}🔧 Crontab 规则
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └── 星期 (0-7, 0和7都是周日)
│ │ │ │ └─────── 月份 (1-12)
│ │ │ └──────────── 日期 (1-31)
│ │ └───────────────── 小时 (0-23)
│ └────────────────────── 分钟 (0-59)
└─────────────────────────── 秒 (0-59, Hyperf 扩展)常用示例:
* * * * * *- 每秒执行0 * * * * *- 每分钟执行0 */10 * * * *- 每10分钟执行0 0 * * * *- 每小时执行0 0 0 * * *- 每天凌晨执行
🔒 分布式锁
多实例部署时,使用 Redis 锁防止重复执行:
php
#[Crontab(
name: 'my-task',
rule: '0 * * * * *',
callback: 'execute',
singleton: true, // 启用单例模式
onOneServer: true // 只在一台服务器执行
)]⚠️ 注意事项
- 执行时间: 任务执行时间不要超过调度间隔
- 异常处理: 捕获异常避免影响其他任务
- 日志记录: 记录关键操作便于排查问题
- 监控告警: 配置任务执行失败告警