ジョブキューを使うと、通知の送信、ファイルの処理、データの同期などのタスクを、リクエストの即時処理から切り離して実行できます。しかし、コンシューマーが処理できる量を超えてジョブが投入されると、バックログが発生します。遅延は、確認応答の遅れ、データの陳腐化、タスクがいつまでも完了しないといった形で表面化し、ユーザーとアプリケーションの運用チームの双方に影響を及ぼします。
対応を決めるには、保留中のメッセージ数を見るだけでは不十分です。重要なのは、メッセージの経過時間、到着と完了の速度、ジョブの種類、依存先の状態です。処理能力が不足している場合はコンシューマーの追加が有効ですが、すでに過負荷のデータベースへのクエリを増やしてしまうこともあります。安全な対応は、まず計測し、発生しているパターンを見極めることから始まります。
バックログから分かることと不足している指標

保留中のジョブ数は、その時点の状況を示すものであって、原因の説明ではありません。ピーク時に増えても介入せずに減ることがあります。一方で、件数が横ばいでも最古のジョブの待機時間が延びている場合があります。そのため、PHPキューのバックログを制御する方法を評価する際は、次の指標を合わせて確認します。
- 流入率:単位時間あたりに受け付けたジョブ数。
- 処理完了率:単位時間あたりに完了したジョブ数。完了数と失敗した試行を区別します。
- 経過時間:最古のジョブが待機している時間。利用できる場合は待機時間のパーセンタイルも確認します。
- 処理時間:ジョブの種類ごとの所要時間と、その変化。
- エラーと再試行:失敗率、試行回数、エラーキューまたは隔離キューに送られたジョブの有無。
- コンシューマーと依存先の状態:稼働中のプロセス、再起動、CPU・メモリ使用率、データベース接続数、外部サービスのレイテンシ。
処理完了率には、実際に完了した有効な処理を反映させる必要があります。各試行を処理済みとして数えると、失敗と再試行のループが見えなくなることがあります。また、キューまたはタスククラスごとに分けて確認することも重要です。全体の平均では、ある種類のジョブがほかのジョブを妨げている状況が隠れることがあります。
処理能力を変更する前にパターンを診断する
運用に適した時間幅で指標を比較し、システムの通常時の挙動と照らし合わせます。パターンは調査の手がかりになりますが、それだけで原因が証明されるわけではありません。
- 流入が継続的に処理完了を上回る:処理能力の不足、処理量の増加、またはジョブの処理時間の延長が考えられます。最近の変更、トラフィックの構成、タスク種別ごとの処理時間を確認します。
- コンシューマーは稼働しているが、処理完了がほぼない:プロセスの停止、無期限の待機、デッドロック、接続プールの枯渇、タイムアウトのない外部呼び出しを調べます。ジョブIDで関連付けたログとトレースを確認します。
- 処理時間と依存先のレイテンシが増加している:コンシューマーがデータベース、API、ストレージの応答を待っている可能性があります。プロセスを増やすと競合が強まり、レイテンシが悪化することがあります。
- 同じジョブで失敗が繰り返される:無効なデータ、回復不能な状態、または不具合が原因かもしれません。再試行ポリシーを確認します。再試行が早すぎると、負荷が急増するおそれがあります。
- ほかのキューが進む一方で、特定のキューが増え続ける:優先度、コンシューマーの割り当て、特定のジョブクラスによるリソースの独占を確認します。
設定変更や最近のデプロイも調べます。テレメトリが、処理中のコンシューマーと、稼働しているものの進捗のないコンシューマーを区別できているか確認してください。プロセスが稼働しているというチェックだけでは、ジョブの完了を保証できません。
実測値からバックログの処理能力を見積もる
処理完了率が継続的に流入率を上回れば、その差が維持される限りキューは減少します。運用上の概算では、バックログの処理時間は、保留中の件数を正味の処理能力(同じ期間における処理完了率から流入率を引いた値)で割って見積もれます。この差がゼロ以下なら、待ち時間が延びても滞留は解消されません。
この見積もりは目安であり、復旧時刻を保証するものではありません。処理速度が維持され、ジョブの構成とコストがほぼ同じであることを前提としています。少数の長時間ジョブ、再試行、依存先の制限によって結果は変わります。実負荷で観測したレートを使い、介入のたびに見積もり直してください。コストの異なるタスクについては、ジョブ数だけでなく、クラスごとに計算するか、処理時間を測定します。
段階的に、上限を設けて介入する
元に戻せる、範囲を限定した対策を優先します。コンシューマー数を変更する前に、各依存先が許容できる影響と、変更を元に戻す方法を確認してください。
- 可能であれば新たな流入を抑える:重要度の低いプロデューサーを一時停止する、上限を設ける、優先度の低いタスクを先送りするといった方法があります。業務ルール、記録、復旧手段なしにジョブを破棄することは避けてください。
- 問題のあるジョブを隔離する:試行回数に上限を設け、適切な場合は待ち時間を段階的に延ばし、失敗が続くジョブを確認可能なエラーキューに振り分けます。そうしたジョブを放置しないでください。修正して再処理する必要がある場合があります。
- 優先度を保護する:緊急タスクをメンテナンスや大量処理から分離し、優先度の低いキューがいつまでも待たされないことを確認します。
- 並行処理数を段階的に調整する:小刻みにコンシューマー数を変更し、スループットと飽和状態を観察します。データベース接続数、CPU、メモリ、外部サービスのクォータに見合った上限を維持します。
- 原因を解消する:遅いクエリ、ブロッキング、タイムアウトのない呼び出しがある場合は、並列プロセスを増やし続ける前にボトルネックを解消します。
ジョブが複数回実行される可能性がある場合、冪等性は特に重要です。外部への副作用や書き込みが再試行に耐えられるように設計するか、適切な重複排除の仕組みを導入します。また、副作用を実行した後、メッセージを確定する前にコンシューマーが停止した場合に何が起きるかも確認してください。
しきい値と復旧手順を定める
一律の数値ではなく、サービス要件に基づいてしきい値を設定します。アラートでは、最大経過時間または待機時間のパーセンタイル、バックログの傾向、流入と処理完了の差、エラー率を組み合わせられます。経過時間は単独の件数よりもユーザーへの影響と結び付きやすく、件数は規模の把握に役立ちます。
誰が対応するのか、どのキューを一時停止できるのか、どの依存先に確認が必要なのか、どの変更に承認が必要なのかを文書化します。インシデント中は、時刻、仮説、実施した対応、観測された効果を記録してください。調整のたびに、データベースのレイテンシ、外部エラー、リソース使用量、アプリケーションの障害が許容できないほど増えることなく、処理完了率が上がっているか確認します。
経過時間と件数が継続的に減り、ジョブが正常に完了し、依存先の状態が安定した水準に戻ったことを確認してから、復旧したと判断します。カウンターが減っただけで問題を解決済みとしないでください。メッセージが破棄されていたり、別のキューに滞留していたりする可能性があります。
再発防止のチェックリスト

- キューごとに流入、有効な処理完了、経過時間、処理時間、再試行を測定していますか?
- ジョブにタイムアウトが設定され、再試行ポリシーに適切な有限の上限がありますか?
- 件数だけでなく、進捗がない状態にもアラートを設定していますか?
- 最大並行処理数は、共有する依存先の上限を守っていますか?
- すべての処理を止めずに、問題のあるジョブクラスを隔離できますか?
- 安全に一時停止、再開、再処理するための手順が文書化されていますか?
- コード、負荷、設定の変更後に、指標と副作用を確認していますか?
健全なキューが必ずしも空である必要はありません。通常の変動が生じる場合もあります。実務上の基準は、想定したサービスレベル内でジョブが完了し、失敗が可視化され、システムにピークを吸収できる余力があることです。その挙動を測定すれば、滞留がユーザーへのサービス中断に発展する前に対応できます。



