
2026/03/30 23:09
リクエストをキューに入れると、容量の課題も同様に増大します。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
コアレッスンは、トラフィックピークを滑らかにするためにキューを追加すると遅延が単に延期されるだけであり、ユーザーが「苦しむ」総時間が減少するわけではないということです。10ノード構成のシステムがフルキャパシティで稼働している場合、応答時間はほぼ1秒前後を保ちますが、毎時の急増が発生するときまでです。午後8〜9時に2000req/s のスパイクが発生した際には、キューが約360万件に膨張し、ユーザーに対して約1時間の待機時間を強いることになります。10%程度の軽微なオーバーロードでも、数十万件ものリクエストがキューに入れられ、数分単位の遅延が生じます。FIFO順序付けはこれらの待ち時間をさらに長くする可能性がありますし、ランダムまたは加重選択ではパーセンタイルレイテンシが変化します(例:90%パーセンタイルが純粋なランダムで約14秒に跳ね上がる)。したがって、キューは単に遅延を別の場所へ移動させるだけであり、ゼロサムゲームです。
実際的なキューでは、真のランダム性を得るために
SPOP を使用するか、タイムスタンプ付きで加重プルするために ZRANGE を使用することが考えられます。ただし、四分位数をリアルタイムで計算するのはコストが高いです。ドライブスルーラインなどの実世界のアナロジーは、ソフトウェアシステムにおける見えない遅延として表れる隠れたバックログを示す良い例です。
容量を拡張することで問題が解決します:11ノード(約10%増量)を追加すると、2倍のスパイクを約9時間で排出できます。15ノード(約50%増量)を追加すると、ほぼ1時間でクリアします。15ノードとFIFO順序付けの場合、午後9時の知覚遅延は約20分から10時にはほぼゼロに低下します。推奨事項は明確です——キューがトラフィックスパイクを吸収することに頼るよりも、積極的なスケーリングへの投資を行うべきです。
本文
以下は、数か月前にTwitterでやり取りした内容です。
(訳注:文脈を保ちつつ、日本語として自然にするため、専門用語も適切に翻訳しています。)
Twitter ― 世界最大のタウンホール
ここでは、この方を特定して非難する意図はありません。私の知る限り、彼は非常に成功したビジネスを運営しており、多くの場合私よりも賢いでしょう。しかし、私たちは「待ち行列」に対する理解が異なります―これは私が以前から書いてきた、心の中で大切にしているテーマです。
1. 画像
- あなたの p90 ランタイム(遅延)グラフは、1 秒前後で完璧に健全に見えます。
- ただし、過去1時間以内に送信されたすべての顧客リクエストは、3.6 百万件もの他のリクエストの後ろに並んでいるため、1時間の遅延を経験しています。
どうしてこんなことが起きるのでしょうか?
あなたが API を提供し、実際の制約から「待ち行列インタフェース」を既存のリアルタイムリクエスト/レスポンスモデルに代わる良い選択肢だと考えたとしましょう。
2. 詳細
| 項目 | 内容 |
|---|---|
| リクエストレート | 24時間/日、週7日の間で 1,000 req/s |
| 処理時間 | 各リクエストは 1秒 |
| ノード数 | 10ノード。各ノードが最大 100 req/s を扱える → クラスター全体の容量は 1,000 req/s です。 |
| 完全にキャパシティに達しています ― 入力レートと処理容量が一致します。 |
リクエストが急増した場合:
- 午後8時〜9時:リクエストレートが 2,000 req/s に倍増
- オプション:
- 容量を超えるリクエストは拒否(過酷)
- ノードを追加(コスト高)
- 待ち行列に入れて遅延させる(魅力的だがコスト大)
- オプション:
3. 遅延への影響
2倍の急増時:
| 時間帯 | ランタイム |
|---|---|
| 午後8時〜9時 | 1 秒 → 1時間 |
これは 「認知遅延」(クライアント側で感じる遅延)です。サーバー側の処理時間ではなく、待ち行列に待つ時間を含みます。
なぜこんなに高いのでしょうか?
- 待ち行列が増えるためです。
- 1秒あたり 1,000 件を処理しながら、同時に 1,000 件を追加すると、9 時点で 3.6 百万 件が溜まります(余剰 1,000 × 3,600 秒)。
- レートが元のキャパシティに戻っても、待ち行列を排出する余裕はありません。新しいリクエストは処理されるまで 1 時間 待つことになります。
より穏やかな急増(10% オーバー:1,100 req/s)の場合:
| 待ち行列サイズ | 認知遅延 |
|---|---|
| 360k 件 | 約6分 |
多くの本番環境で起きるピークは、2 倍よりも小さく、1 時間未満ですが、以下と絡むことがよくあります:
- リトライ ― 待ち行列と組み合わせると一般的に悪影響
- オートスケーリング ― 通常は容量不足が拡張後のシステムで解消されれば有効
4. 待ち行列選択戦略
FIFO(先入れ先出し):
- 9 時点以降、すべての遅延集計値(p50, p90 等)は約 6 分 を要します。
ランダム選択(シミュレーション):
| 指標 | FIFO | ランダム |
|---|---|---|
| 中央値 | 6 s | 5 s |
| p25 | 6 s | ≈2 s |
| p90 | 6 s | ≈14 s |
- FIFO は公平ですが、極端に遅いケースが発生しやすく、ランダムはテールレイテンシを悪化させる可能性があります。
重み付き四分位選択(シミュレーション):
| 四分位 | 確率 |
|---|---|
| 最古 25% | 40 % |
| 次の 25% | 30 % |
| 次の 25% | 20 % |
| 最若い 25% | 10 % |
- 中央値はわずかに上昇し、p90・p99 は減少します。
5. 遅延の信頼区間
午後9時にリクエストを送った場合、遅延が 1 分 になる確率と 10 分 になる確率は?
ランダム vs 重み付き四分位で描かれた認知遅延の信頼区間グラフで示されます。
結論:固定された待ち行列と容量がある場合、運よく早いリクエストを得ると同時に、遅いリクエストも生まれます。分布は変えられるものの、総合的な「苦しみ」は一定です。
6. 実務上のポイント
-
待ち行列を追加することが唯一の短期オプションである場合、選択戦略を試してください。
- 真ランダム:Redis
SPOP - 重み付き四分位:Redis
(リクエスト時に計算コストが高い)ZRANGE - もしくは複数のキューを作成し、時間とともにアイテムを移動させる方法があります—ただし同時実行性の問題が発生します。
- 真ランダム:Redis
-
プロアクティブスケジューリング(ジョブスケジューラ)は、計画と実行間で環境が変化するため難しいです。
7. 待ち行列ではなく容量を追加
待ち行列は 9 時点で 3.6 百万件 に達し、決して回復しません。遅延は永遠に高いままです。キューを縮小するには:
| クラスターサイズ | キューが排出されるまでの時間 |
|---|---|
| 11 ノード(10 % 増) | 9 時間 |
| 15 ノード(50 % 増) | 1 時間 |
- 15ノード と FIFO を使用すると:
- 9 時点での遅延:20 分
- 9:30 に:10 分
- 10 時に:約 1 秒へ戻ります。
知恵を絞る余地はほとんどありません。容量を追加するか、顧客が遅延を受け入れるかの選択です。待ち行列はただ「遅れ」を生じさせるだけで、根本的な問題を解決しません。
8. 最後に
実際の待ち行列はソフトウェア待ち行列よりも可視性があります―ドライブスルーで並ぶ人々を見ることができ、その列に入るかどうか判断できます。
もしサービスが「1 秒」や「6〜60 分」のように不定期に変動する場合は、待ち行列を増やすのではなく 容量を追加 すべきです。
システムが時折高速で、時折遅いという原因が不明瞭な場合――それは解決可能です。私はスタートアップ向けにレイテンシ最適化されたシステム設計を手伝っており、理解しやすく 3 時間前のインシデントを減らすサポートを行っています。ぜひご相談ください:supremeinformatics.com