System Design入門 設計判断を数字とコードで確かめる
時間切れと再試行
この回でやること
諦める時間と再試行の間隔・上限を決め、待ち時間を確かめます。
- 読む 約 7 分
- 最後にクイズ 1 問
待ち続けない
有料席の予約では、外の決済サービスへ承認を問い合わせます。返事が来ないときに待ち続けると、接続や処理の枠が塞がり、次の予約も待たされます。
そこで、1回の問い合わせを何ミリ秒で打ち切るか決めます。これが時間切れで、相手の不調がこちら全体に広がるのを抑えます。
返ってくる可能性はありますが、待つ間も資源を使います。時間切れを長くするほど通るとは限らず、混雑している相手を待つ要求がこちらにも溜まります。
時間切れは、こちらが返事を得られなかったという意味です。相手が決済を終えている場合もあるので、失敗したと決めつけて新しい支払いを作ると二重決済につながります。
間隔と上限を決めて試し直す
一時的な不調なら再試行できますが、直後に何度も送ると相手の混雑を増やします。試す間隔を倍にする指数バックオフで、相手の回復を待ちます。
待ち時間は、最初の間隔を失敗のたびに倍にして求めます。ただし間隔には上限を置き、試す回数にも上限を置きます。
回数を決めずに続けると、利用者が待てない長さになります。同じ予約の再試行では同じ要求だと分かる鍵を使い、二度届いても結果が増えない形にする必要もあります。
間隔の上限だけでは、再試行は終わりません。1回の時間切れ、試す回数、間隔を合わせて、利用者が待つ時間を確認します。
予約サービスで解いてみる
DAUが3万人、1人6回のアクセスなら、平均は約2 QPSです。ピーク係数50で毎秒100件、1台40件なら3台ですが、これは処理の枠が長く塞がらない仮定です。
月5万円の予算で台を足す前に、決済の待ち方を見直します。ここでは1回250ミリ秒で時間切れ、初回を含めて最大5回試し、間隔は100ミリ秒から倍にして500ミリ秒で止めます。
5回の試行の間に待つのは4回です。最初の試行前と、最後に諦めたあとは待ちません。
| 失敗した試行 | 次の試行までの間隔 |
|---|---|
| 1回目 | 100ミリ秒 |
| 2回目 | 200ミリ秒 |
| 3回目 | 400ミリ秒 |
| 4回目 | 500ミリ秒 |
間隔の合計は100+200+400+500で1200ミリ秒です。すべて時間切れなら問い合わせ自体も250×5で1250ミリ秒かかり、合わせて2450ミリ秒待ちます。
この例は表の間隔どおりに待ち、通信以外の時間を省いた見積もりです。同時に失敗した要求が同時に再試行しないよう、実際には間隔を少しずらす工夫もあります。
上限まで試して返事がなければ、決済結果の確認へ進みます。単に「失敗」と表示して新しい予約を促す前に、元の要求が成立していないか確かめます。