IT-Q

前回の実行が終わる前に次の実行時刻が来たら、どうなりますか。

何もしなければ重複して起動します。同じデータを2つのプロセスが同時に触り、二重送信や二重集計が起きます。withoutOverlapping() を付けてロックを取れば防げます。

面接官が見ているのは重複実行という定番の事故を知っているか。

これは「Laravel で定期実行を組む方法として妥当なのはどれですか。」への追撃質問です。

よくある答えと、面談でどう見られるか

  • 重複して起動する。withoutOverlapping() でロックを取り、有効期限も指定する
    その通りです。プロセスが異常終了するとロックが残ることがあるので、期限指定まで言えると強いです。
  • 自動的にスキップされる
    何もしなければ重複起動します。それが二重処理の原因になります。
  • 前の実行が強制終了される
    強制終了はされません。並行して走ります。
  • キューに積まれて順番待ちになる
    スケジューラはキューとは別の仕組みです。

面接官は何を見ているか

  • デフォルトでは重複して起動すると理解している
  • 二重処理による不整合の危険を指摘できた
  • withoutOverlapping() による対処を挙げた

模範解答

何もしなければ重複して起動します。処理が想定より長引いたときに、同じデータを2つのプロセスが同時に触ることになり、二重送信や二重集計といった不整合が起きます。対処は withoutOverlapping() を付けること。ロックを取って、前の実行中はスキップされます。

詰めて聞かれるのはロックの寿命です。既定の有効期限は24時間なので、サーバーが落ちるなどしてロックが残ると、翌日まで実行されないままになります。withoutOverlapping(10) のように分単位で短く指定しておくのが安全です。ロックはキャッシュに置かれるので、詰まったときは schedule:clear-cache で消せます。

なお、これはあくまで同一サーバー内の重複を防ぐ仕組みです。スケジューラを複数台で動かしていると各サーバーでそれぞれ実行されるので、そちらは onOneServer で1台に絞ります。