Cronの多重起動を防止する
PHPでDM配信システムを実装した。
仕組みは以下。
- メールの件名、本文、配信先をDBに登録
- Cronで5分間隔でmail_send.phpを実行。
- mail_send.php 内でDBから配信済みフラグが
0
のレコードを70件取得し、メール配信 - 配信が完了した宛先には配信済みフラグを
1
に変更 - 以後繰り返し。
詳しい実装方法はまた別の記事で紹介するかも。
んで、Cronはこんな感じ
*/5 * * * * php /path/to/dir/mail_send.php
これはこれでうまく動くんだけど、なんらかの問題があって全てを配信できなかった場合、前回配信が終わらず配信フラグが0
の配信先を再度取得してしまう。
結果、同じ配信先に2通のメールが配信されてしまうことになる。
これはまずい。
lockfileを作成して多重起動を防止
やり方は結構簡単で、Cronを実行した際に、lockfileを作成し、処理が全て終わったらlockfileを削除する。 Cronが回ってきた時、lockfileが存在する(処理が完了していない)場合は処理を実行しない。
コードはこんな感じ。
// 同階層にlockfileを作成する場合、__DIR__ . '/lockFile.txt';でもおk。 $lockFile = '/path/to/dir/lockFile.txt'; if (file_exists($lockFile)) { exit(0); // ファイルが存在する場合、プログラムを停止させる } // 実行する前にファイルを作成する touch($lockFile); **************************************************** メール配信処理 **************************************************** ///処理が終わったらlockfifleを削除する unlink($lockFile);
やってみると多重起動は防止できていることがわかると思うる。
念の為、自動でlockfileを削除する処理を追加する
万が一lockfileの削除ができなかった場合、処理が終わってないと判断され、手動でlockfileを削除しない限りメール配信がされないことになってしまう。
そこで、作成から一定時間経過したlockfileは削除するという処理を追加する。
// 同階層にlockfileを作成する場合、__DIR__ . '/lockFile.txt';でもおk。
$lockFile = '/path/to/dir/lockFile.txt';
// 作成時間から5分経過していたらlockfileを削除する
$limit = 5;
if (strtotime(date('Y-m-d H:i:s')) - filemtime($lockFile) / 60 > $limit) {
unlink($lockFile);
}
if (file_exists($lockFile)) {
exit(0); // ファイルが存在する場合、プログラムを停止させる
}
// 実行する前にファイルを作成する
touch($lockFile);
****************************************************
メール配信処理
****************************************************
///処理が終わったらlockfifleを削除する
unlink($lockFile);
これでCronの多重起動が防止できました。
よかったら参考にしてみてください。