メール送信や画像変換などはキューに入れてワーカーが後で処理する。リトライと冪等性が前提。
メール送信・画像の変換・外部 API への通知・CSV の書き出しなど、時間がかかる処理や失敗しやすい処理は、リクエストの中で行わずキューにジョブとして入れ、別のプロセス(ワーカー)が後で処理します。ユーザーへの応答が速くなり、外部が落ちていてもリクエストは失敗しません。
ジョブの失敗とリトライ・デッドレター
- リトライ:失敗したら指数バックオフで数回やり直す。直らない失敗(データが壊れている)はすぐ諦める。
- デッドレターキュー(DLQ):上限まで失敗したジョブを別のキューに移し、捨てずに残す。件数を監視し、原因を直してから再投入する。
- 冪等にする:多くのキューは「少なくとも1回」届ける(同じジョブが2回動くことがある)ので、2回動いても結果が同じになるように作る(送信済みの記録を見る、一意制約)。
- DB と一緒に:「注文を保存してからジョブを入れる」の間で落ちるとずれる。コミットした後に入れる、または同じ DB の表にイベントを書いて別の処理で送る(Outbox パターン)。
- ジョブには ID など最小限だけを入れ、処理のときに DB から最新を読む。タイムアウトと同時実行数の上限も決める。
| 道具 | 仕組み | よく使う場面 |
|---|---|---|
| Amazon SQS | AWS のキューのサービス。可視性タイムアウト・DLQ がある | AWS 上のサービス、Lambda と組み合わせる |
| Sidekiq | Redis を使う Ruby のジョブの仕組み | Rails |
| BullMQ | Redis を使う Node.js のジョブの仕組み | Node.js・TypeScript |
| その他 | Celery(Python)、Cloud Tasks・Pub/Sub(Google Cloud)、DB を使う仕組み(Solid Queue・good_job など) | 言語や基盤に合わせて |
面接ではこう答える
メール送信や画像の変換のように時間がかかる処理や失敗しやすい処理は、リクエストの中で行わず、キューにジョブとして入れてワーカーが後で処理します。ユーザーへの応答が速くなり、外部が落ちていてもリクエストは失敗しません。失敗したら指数バックオフでリトライし、上限を超えたらデッドレターキューに移して監視します。多くのキューは同じジョブが2回届くことがあるので、ジョブは冪等に作ります。
Webとの関わり重い処理や外部連携のある機能を作るときの基本の設計です。
DBラボを読み込んでいます…