Aliceは待つのが嫌いです
(brooker.co.za)- サービスの平均リクエスト時間が100msで、MTTRが1分未満であっても、ユーザーは長いリクエストや長い障害により、はるかに長く閉じ込められるため、平均待ち時間をずっと長く感じる
- 運用担当者はリクエストや障害をイベント単位で集計するが、AliceやAlexのようなユーザーは秒・分単位の体感時間で待ち時間を計算する
- この違いは**検査のパラドックス(inspection paradox)**によるものであり、ユーザーが経験する分布は元の遅延分布
f(t)ではなく、tで重み付けされた分布になる - 復旧時間の中央値が30分、p99が600分の対数正規分布では、MTTRが1時間を少し超える程度でも、顧客が体感する平均復旧時間は約6時間まで伸びる
- テールレイテンシと長い復旧時間は顧客体験を支配しうるため、トリム平均(trimmed mean)は右テールの重要な情報を捨ててしまう危険がある
リクエスト単位の平均とユーザー体感平均のギャップ
- AliceはWebサービスを使っており、ほとんどの人と同じように時間を秒と分で感じる
- 運用担当者は平均リクエストが100msで完了すると見ていても、Aliceの平均待ち時間は1秒になりうる
- 障害でも同じ違いが生じる
- 運用担当者はMTTRが1分未満だと言える
- Alexが体感する平均障害時間は1時間かもしれない
- この2つの測定は同時に正しいことがありうる
- 長いリクエストや長い障害は、運用側の集計では1つのイベントである
- ユーザーの時間では、継続した長さのぶんだけより大きな比重を占める
検査のパラドックスが生む t 重み付き分布
- この現象は検査のパラドックスとして捉えられる
- ユーザーは遅延分布
f(t)そのものではなく、tで重み付けされた版を経験する - MTTRまたは平均リクエスト時間が
E[X]のとき、ユーザーが経験する平均は次のようになるE_a[X] = E[X²] / E[X]E_a[X] = E[X] + Var(X) / E[X]
- 分散が大きいほど、ユーザーが体感する平均は運用指標の平均よりもさらに大きく乖離する
中央値30分、p99が600分の例
- 中央値の遅延または復旧時間と99パーセンタイルの値を入れると、対数正規分布を当てはめて、サービス指標と顧客体感の値を比較できる
- 例の値は次のとおり
- 中央値TTR: 30分
- p99 TTR: 600分。つまり、100回のイベントのうち1回は復旧に10時間かかる
- この場合、MTTRは1時間を少し超えるが、顧客が経験する平均復旧時間は約6時間になる
テールレイテンシとトリム平均の落とし穴
- テールレイテンシと長い復旧時間を理解すべき理由はいくつもあり、multiple samplesもその1つである
- サービス時間では、timeout-and-retry によって一部の遅延を隠せる場合がある
- ただし、実行中のリクエストがロックや他の排他的リソースを保持していないことが前提となる
- 復旧時間ではこのような隠蔽は不可能なため、テールの厚さが顧客体験により直接的に現れる
- trimmed mean のようなトリムされた測定値は、顧客体験を支配する右テールの形を覆い隠してしまう問題がある
- トリムされた測定値を好まないもう1つの理由はLittle’s Lawとキャパシティ利用率に関係しており、関連する話は以前に扱った記事にある
対数正規分布を使う際の注意
- 対数正規分布は数値計算のしやすさのために選ばれている
lognormal(μ, σ²)がlognormal(μ + σ², σ²)になる性質があり、0付近でもうまく振る舞う- 遅延や復旧時間の指標に対して、対数正規分布が特に良い選択だとまでは言えない
- この種の問題には、一般にノンパラメトリックな方法で取り組むほうがよいと考えられる
1件のコメント
Lobste.rs のコメント
タイトルは Latency and the inspection paradox のように、より情報量のあるものに変えたほうがよさそう
今のタイトルは実質的に伝えている情報がほぼ 0 に近い 😅
タイトルだけ読んで本文を読まない人からの返信を減らせるから
面白いけど、著者はこれがなぜ成り立つのかを t-weighted という用語と数式以外で説明していないので、いまひとつ理解しにくい
大学の統計の授業をずっと昔に忘れてしまった人でも分かるように、もっと明確に説明してほしかった
E[X]で、各リクエストの重みは1/NになるAlice が体感するレイテンシは時間基準なので、たぶんここで 時間重み付き (t-weighted) が出てくるのだと思う
Alice がレイテンシ
x_1, x_2, ..., x_Mの M 個のリクエストを送ったとすると、「Alice の総待機時間の中から任意の 1 秒を選んだとき、その瞬間に待っているリクエストのレイテンシはどれくらいか?」と考えられるこのときリクエスト i は
x_i / (Σ_j x_j)だけ寄与するので、長いリクエストほどより強く反映されるしたがって時間重み付き平均は次のようになる 簡単な例として、レイテンシが 1 秒のリクエスト 1 つと 10 秒のリクエスト 1 つがあると、通常の平均は 5.5 秒だが、時間重み付き平均は
1 * (1 / 11) + 10 * 10 / 11 = 9.18sになる関連して、The Inspection Paradox is Everywhere も読む価値がある
自分も実際に似たようなことを考えたことがある
この問題を理解する最も分かりやすい例は、バスの乗客に「このバスには何人乗っていますか」と尋ねる調査だと思う
すると「バスは満員だ」という答えはずっと多く得られるが、バスが空いているときは誰にも尋ねられない
すべてのバスが空いていて、たった 1 台だけが混んでいるということもありうる
目的が ユーザー視点 で状況を分析することなら、この統計は正しいと思う
つながりの多いノードは、つながりの少ないノードよりも他のノードの 隣接リスト により頻繁に現れるから
この話題がしっくり来るなら、Gil Tene's "How not to measure latency" を強くおすすめする