crontab 任务在上一轮还没跑完时又被触发,就会造成重复处理:重复扣款、重复发短信、重复跑结算。PHP 没有内置的进程互斥,但用 flock 文件锁可以简单可靠地解决。
实现思路
脚本启动后尝试对锁文件加 LOCK_EX 排它锁并配合 LOCK_NB 非阻塞:加锁成功说明没有其它实例在跑,正常执行;加锁失败说明已有实例占用,直接退出。锁文件按脚本路径 MD5 命名,避免互相干扰。
完整代码
<?php
/**
* flock 防止脚本重复执行
* 用法:把需要互斥的任务逻辑放在加锁成功之后即可
*/
$lockFile = sys_get_temp_dir() . "/job_" . md5(__FILE__) . ".lock";
$fp = fopen($lockFile, "w");
if (!$fp) {
exit("无法创建锁文件");
}
// LOCK_EX 排它 + LOCK_NB 非阻塞
if (!flock($fp, LOCK_EX | LOCK_NB)) {
fclose($fp);
exit("已有实例运行中,本次跳过");
}
echo "任务开始:" . date("Y-m-d H:i:s") . PHP_EOL;
sleep(5); // 模拟耗时任务
flock($fp, LOCK_UN);
fclose($fp);
echo "任务完成" . PHP_EOL;
?>使用注意
- 锁是劝告性锁,必须所有执行同一任务的脚本都走同一把锁才有效;
- 进程异常退出时操作系统会自动释放文件锁,不会出现死锁残留;
- 多个定时任务请各用各的锁文件名,避免互相误伤。
小结
文件锁实现简单、跨平台可用,适合单机任务调度;分布式多机部署时再迁移到 Redis SETNX 或任务调度中间件。
评论(0)
暂无评论,快来抢沙发吧~