Hedged Requestとは?遅いAI APIを複製するときの条件と危険
ほとんどのAI API呼び出しが5秒で終わっても、1%だけ40秒かかれば、対話画面では「ときどき固まる」サービスになる。平均時間を縮めても、この遅い裾が残ることがある。
Hedged Requestは、最初の要求が一定時間を超えても終わらないとき、同等の二本目を開始し、先に成功した結果を採用する方法である。失敗してから送り直すRetryと異なり、最初の要求が処理中のまま二本目を競わせる。
遅延の長い裾を短くできる可能性がある一方、下流負荷、token、費用を増やす。生成AIでは二つの回答内容が異なる場合もあり、「速い方が正しい」とは限らない。常用する高速化ではなく、厳しいtail latency目標があり、追加負荷を制御できる経路だけで検討する仕組みである。
平均では見えないtail latency
分散システムでは、networkの揺れ、特定instanceの混雑、garbage collection、connection確立、共有資源の競合などで、一部の要求だけが大きく遅れる。Google ResearchのThe Tail at Scaleは、規模と処理経路が増えるほど、一部componentの一時的な高遅延が全体の応答を支配し得ることを示している。
AIアプリではさらに、入力token、出力token、Tool Calling、RAG、ストリーミング、モデル側の混雑で処理時間が変わる。p50が改善してもp99が悪いままなら、多数の利用者のうち少数が毎回長く待つ。
一つの画面が10個の独立結果をすべて待つ場合、各呼び出しの遅い側へ当たる機会も増える。平均だけでなくp50、p95、p99、deadline超過率を経路別に測る必要がある。
Retryとの違い
Retryは、errorまたはtimeoutで一回目を終了扱いにしてから次を始める。Hedged Requestは、一回目がまだ成功する可能性を残したまま二回目を始める。
例えば通常は5秒で終わる処理について、8秒経過しても完了しない場合だけ二本目を送る。二本目が3秒で成功すれば、開始から11秒で返せる。一回目を30秒のtimeoutまで待ってからRetryするより早い。
ただし、一回目も裏で動いているため、その間は同じ仕事が二本存在する。先に返った結果を採用した後、負けた要求を安全にcancelできなければ、下流は最後まで二本分を処理する。利用者が見る遅延だけ下がり、provider側の負荷と費用は残ることがある。
最初から二本送らない
すべての要求を同時に二本送れば、p50も少し改善するかもしれないが、request数と費用はほぼ倍になる。混雑時には自分の複製がさらに混雑を作り、tail latencyを悪化させる。
Hedgingは通常、実測した遅延分布を基に待機thresholdを置く。p95を超えた要求だけ複製するなら、正常時の多くは一本で完了する。AWSのDynamoDB資料も、初回が十分早く返らない場合だけ同等の二本目を送り、先着した結果を使う方法として説明している。
thresholdを短くするほど遅延改善の機会は増えるが、複製率も上がる。固定秒数を推測で置かず、操作、region、payload size、model、時間帯ごとの分布で決める。構成変更後は再測定する。
遅い理由が共通なら効果がない
二本の要求が同じ混雑原因を共有していれば、両方とも遅くなる。
- 同じmodelの全体的な過負荷
- 同じregionまたはAvailability Zoneの障害
- 同じdatabase partitionやhot key
- 同じ巨大promptと長い出力
- 同じconnection poolの枯渇
- 呼び出し元自身のCPUやnetwork飽和
Hedgingが効くのは、一時的なinstanceの遅れやnetwork pathの揺れなど、二本目が別の遅延要因を引ける場合である。別instance、別replica、必要なら別regionへ送ると独立性は増すが、data freshness、居住地域、費用、モデル版の差も生まれる。
原因を調べずHedgingを足すと、長すぎるprompt、不要なTool Calling、接続設定の不備といった本来直すべき問題を隠す。まずtraceで遅い区間を特定し、通常の最適化で直せない残りのtailへ適用する。
読み取りと書き込みを分ける
同じ文書の取得、検索、埋め込みの参照など、副作用のない読み取りは比較的Hedgingしやすい。二本実行されても外部状態を二重変更しないためである。
メール送信、決済、予約、公開、ticket更新のような書き込みは危険である。先に返った一方だけを採用しても、もう一方が後から成功すれば操作は二重になる。AWSのDynamoDB資料も、Hedgingは読み取りで扱いやすく、書き込みには順序や冪等性の対策が必要だとしている。
書き込みへ適用するなら、二本とも同じidempotency keyと元の操作時刻を使い、保存先が重複を拒否できることを確認する。cancelは二重実行防止の保証ではない。cancelが届く前に処理が確定している可能性がある。
AIエージェントのTool Calling全体を複製するのではなく、読み取り専用の検索やmodel推論など、安全な一段だけを対象にする。
生成結果では「先着」を品質と混同しない
同じmodel、prompt、設定でも、生成文が完全に一致するとは限らない。二本を競わせて速い方を返すと、結果選択の規則が「先に終わった方」になる。
分類や構造化抽出なら、schema validation、必須項目、根拠との整合を満たした最初の結果を採用できる。自由文、推論、コード生成では、短いが不完全な回答が先に終わる可能性がある。速度だけで選ばず、最低限の品質検査を通過した最初の結果とする。
異なるmodelやproviderを競わせる場合は、Hedgingというよりmodel routingとfallbackの性質が強くなる。出力品質、安全基準、Tool Calling形式、data handlingが同等かを事前評価する。速いproviderへ自動的に偏ることで、品質分布が変わる点も監視する。
tokenと費用の増加を予算へ入れる
LLM APIは、同じ長い入力を二本へ送るだけでもtoken消費が増える。負けた要求を途中でcancelしても、cancelまでに処理した分が請求やrate limitへ数えられる場合がある。providerの契約とusage計測を確認し、無料になると仮定しない。
Hedging用に次の上限を持つ。
- 複製を許す操作の種類
- 全要求に対する最大Hedge率
- 一操作あたりの追加要求数
- tenantごとの追加tokenと費用
- 全体のin-flight上限
- 下流の429、503時に停止する条件
OpenAI APIはrequests per minuteとtokens per minuteなど複数のrate limitを持つ。Hedged Requestも別のrequestとして流量へ加わるため、通常要求用の容量を食い尽くさないようにする。
Concurrency Limitの内側で実行する
初回要求をConcurrency Limitへ通し、Hedged Requestだけ別枠にすると、混雑時ほど上限を越えて下流へ流せる。二本目も同じin-flight制御へ通す。
Hedging専用の小さな予備枠を設ける方法もある。通常枠が完全に埋まったときに複製を増やさず、本当にtail latency改善へ使える余裕だけを確保する。下流が過負荷、Circuit BreakerがOpen、rate limitが近い場合はHedgingを止める。
Request Coalescingとも役割が逆になる。Request Coalescingは同じ仕事を一つへまとめるが、Hedgingは一つの仕事を意図的に複製する。同じkeyへ多数の利用者が待っているとき、共有leaderを何本もHedgeすると増幅が大きくなる。coalesced job全体で一本だけ予備要求を許す。
deadlineとcancelを設計する
Hedged Requestは全体deadlineを延ばす仕組みではない。初回と二本目は同じ操作deadlineを共有する。残り時間が短く、二本目が成功する見込みがないなら開始しない。
勝者が決まったら、負けた要求へcancelを伝える。ただし、応答を返す処理とcleanupを分け、cancel失敗や遅い完了を記録する。ストリーミングで一部を利用者へ表示した後に別の応答へ切り替えると文章がつながらないため、通常は最初のtokenを返す前、または内部の非streaming区間に限定する。
二本がほぼ同時に成功した場合も、結果保存やcache更新を一度だけ確定する。遅れて届いた結果が新しい値を古い値で上書きしないよう、操作IDとversionを使う。
観測する指標
Hedgingなしの基準値と比較し、遅延改善と追加負荷を同時に見る。
- 操作別のp50、p95、p99遅延
- Hedge開始率と二本目の勝率
- thresholdから二本目開始までの遅れ
- 追加request、token、費用
- 負けた要求のcancel成功率と残存時間
- 初回と二本目が通ったinstance、region、provider
- 429、503、timeoutの増減
- 品質検査の合格率と採用結果の品質
- 書き込みの重複拒否と遅延到着
二本目の勝率が低いなら、thresholdが遅すぎるか、二本が同じ遅延原因を共有している。p99が下がっても429と費用が大きく増えるなら、全体として持続できない。
負荷試験で確かめる
- 通常遅延と人工的な長いtailを混ぜ、p99だけが改善するか確認する
- thresholdをp50からp99まで変え、複製率、費用、遅延を比較する
- 同じ障害領域と別障害領域へ二本目を送り、効果の差を測る
- 勝者決定後も負けた要求が実行される状況で、in-flightと費用を測る
- 429と503を返し、混雑時にHedgingが停止するか確認する
- 同じidempotency keyの書き込みを競わせ、外部操作が一度だけか確認する
- 異なる生成結果を返し、速度だけで不正な結果を採用しないか確認する
AWSの公開事例では、非Hedge時の遅延分布に対して待機点を変え、p99改善と重複request率の両方を測っている。別のworkloadへ同じpercentileをそのまま移さず、自分の処理と費用で再測定する。
まとめ
Hedged Requestは、初回が一定時間を超えた場合だけ同等の二本目を送り、先に有効な結果を採用してtail latencyを抑える。Retryより早く回復できる可能性があるが、二本が同時に動くため、下流負荷と費用を必ず増やす。
読み取りまたは冪等な処理へ限定し、実測分布からthresholdを決める。二本目をConcurrency Limitとrate limitの内側へ通し、過負荷時は停止する。生成結果には品質検査を置き、勝者決定後は負けた要求をcancelする。p99の改善だけでなく、追加token、重複率、品質、cancel後の残存処理まで測って初めて採用を判断できる。