要点: キューが吸収できるのは短い負荷の波だけです。無制限に受け入れれば、過負荷が長い待ち時間へ変わるだけです。
この記事の用語: DLQ:繰り返し失敗したジョブを隔離するキュー。冪等キー:重複処理を防ぐ識別子。
現場の課題
キューの長さだけを見てワーカーを増やすと、DBや外部サービスを過負荷にします。大量処理を行う一つのテナントが、共有能力を使い切る可能性もあります。
10通のメールと10件の動画エンコードでは負荷が違います。件数より種別別の最古待ち時間を見て、DBや外部サービスの実能力を超えない同時実行上限を置きます。
設計と実装
- ジョブを遅延目標、処理コスト、テナントで分類してからキューへ入れます。
- 各ジョブへ冪等キー、再試行上限、最終失敗時の方針を持たせます。
- 最古ジョブの待ち時間でスケールし、DBと外部サービスの安全上限を超えないようにします。
実装例
job = broker.receive(visibilityTimeout = 60s)
if inbox.exists(job.id): ACK
with dependencyLimiter.acquire(job.kind):
result = handle(job.payload)
transaction(inbox.insert(job.id), save(result))
ACK本番導入の進め方
最古待ち時間と再試行理由を先に測ります。高リスクなジョブを別プールへ分離し、観測のみの上限から少数テナントへ適用し、DLQからの再実行も訓練します。
まとめ
本番キューは無限バッファではなく、有限な処理能力を配分する仕組みです。
