统计各个函数的耗时_Prometheus 常用函数 histogram_quantile 的若干“反直觉”问题...
作者:disksing
histogram_quantile 是 Prometheus 特別常用的一個函數,比如經常把某個服務的 P99 響應時間來衡量服務質量。不過它到底是什么意思很難解釋得清,特別是面向非技術的同學。另一方面,即使是資深的研發同學,在排查問題的時候也經常會發現 histogram_quantile 的數值出現一些反直覺的“異常現象”然后摸不著頭腦。本文將結合原理和一些案例來分析這個問題。
統計學含義
Quantile 在統計學里面中文叫 分位數,其中 X 分位數就是指用 X-1 個分割點把概率分布劃分成 X 個具有相同概率的連續區間。常用的比如有二分位數,就是把數據分成兩個等量的區間,這其實就是 中位數 了。還有當 X=100 時也叫 百分位數(percentile),比如我們常說 P95 響應延遲是 100ms,實際上是指對于收集到的所有響應延遲,有 5% 的請求大于 100ms,95% 的請求小于 100ms。
Prometheus 里面的 histogram_quantile 函數接收的是 0-1 之間的小數,將這個小數乘以 100 就能很容易得到對應的百分位數,比如 0.95 就對應著 P95,而且還可以高于百分位數的精度,比如 0.9999。
quantile 的“反直覺案例”
問題 1:P99 可能比平均值小嗎?
正如中位數可能比平均數大也可能比平均數小,P99 比平均值小也是完全有可能的。通常情況下 P99 幾乎總是比平均值要大的,但是如果數據分布比較極端,最大的 1% 可能大得離譜從而拉高了平均值。一種可能的例子:
1, 1, ... 1, 901 // 共 100 條數據,平均值=10,P99=1問題 2:服務 X 由順序的 A,B 兩個步驟完成,其中 X 的 P99 耗時 100ms,A 過程 P99 耗時 50ms,那么推測 B 過程的 P99 耗時情況是?
直覺上來看,因為有 X=A+B,所以答案可能是 50ms,或者至少應該要小于 50ms。實際上 B 是可以大于 50ms 的,只要 A 和 B 最大的 1% 不恰好遇到,B 完全可以有很大的 P99:
A = 1, 1, ... 1, 1, 1, 50, 50 // 共 100 條數據,P99=50 B = 1, 1, ... 1, 1, 1, 99, 99 // 共 100 條數據,P99=99 X = 2, 2, ... 1, 51, 51, 100, 100 // 共 100 條數據,P99=100如果讓 A 過程最大的 1% 接近 100ms,我們也能構造出 P99 很小的 B:
A = 50, 50, ... 50, 50, 99 // 共 100 條數據,P99=50 B = 1, 1, ... 1, 1, 50 // 共 100 條數據,P99=1 X = 51, 51, ... 51, 100, 100 // 共 100 條數據,P99=100所以我們從題目唯一能確定的只有 B 的 P99 應該不能超過 100ms,A 的 P99 耗時 50ms 這個條件其實沒啥用。
問題 3:服務 X 由順序的 A,B 兩個步驟完成,其中 A 過程 P99 耗時 100ms,B 過程 P99 耗時 50ms,那么推測服務 X 的 P99 耗時情況是?
有人覺得答案是“不超過 150ms”,理由是 A 過程的 P99 是 100ms,說明 A 過程只有 1% 的請求耗時大于 100ms,同理 B 過程也只有 1% 的請求耗時大于 50ms,當這兩個 1% 恰好撞上才會產生 150ms 的總耗時,絕大多數情況下總耗時都是小于 150ms 的。
此處問題同樣在于認為數據是“常規分布”的,假如 A 過程和 B 過程最大的 1% 大的離譜,例如都是 500ms+,那么服務 X 就會有 1%-2% 的請求耗時 500ms+,也就是說服務 X 的 P99 耗時會在 500ms 以上:
A = 1, 1, ... 1, 1, 100, 500 // 共 100 條數據,P99=100 B = 1, 1, ... 1, 1, 50, 500 // 共 100 條數據,P99=50 X = 2, 2, ... 51, 101, 501, 501 // 共 100 條數據,P99=501問題 4:服務 X 有兩種可能的執行路徑 A,B,其中 A 路徑統計 P99 耗時為 100ms,B 路徑統計 P99 耗時 50ms,那么推測服務 X 的 P99 耗時情況是?
這個問題看上去十分簡單,如果所有請求都走 A 路徑,P99 就是 100ms,如果都走 B 路徑的話,P99 就是 50ms,然后如果一部分走 A 一部分走 B,那 P99 就應該是在 50ms ~ 100ms 之間。
那么實際上真的是這樣嗎?我經過仔細的研究,最后發現確實就是這樣的……乍看上去這個問題跟涉及到平均數的辛普森悖論有些像,似乎可以通過調整 A 路徑和 B 路徑的比例搞出一些幺蛾子,但其實不論 A 跟 B 是怎樣的比例,從數量上看,大于 100ms 的請求最多只有 1%A + 1%B = 1%X 個,因此 X 的 P99 不會大于 100ms,同理小于 50ms 的請求不會多于 99%X 個,可知 X 的 P99 也不會小于 50ms。
問題 5:某服務 X 保存數據的過程是把數據發給數據庫中間件 M,中間件 M 有 batch 機制,會把若干條并發的請求合并成一個請求發往數據庫進行存盤。如果測得 X 保存數據耗時的 P99 為 100ms,那么推測 M 請求數據庫的 P99 耗時情況是?
關鍵點在于一個請求的多個步驟不是一一對應的,這種情況在分布式系統中并不罕見,我們需要具體情況具體分析,很難簡單地推斷 M 的 P99 耗時。
最容易注意到的,M 的高延遲能在多大程度上影響 X 的延遲,跟 batch size 息息相關。例如 M 存在一些耗時特別高請求,但是對應的 batch size 恰好很小,這樣對 X 的影響就比較有限了,我們就可能觀察到 M 的 P99 遠大于 X 的 P99 的現象。與之相反,如果對應的 batch size 恰好特別大,極少量的 M 高延遲也會體現在 X 的統計中,我們就能觀察到 X 的 P99 遠大于 M 的 P99 的現象。
再比如 M 在連接數據庫時可能使用了連接池,如果少量的數據庫請求過慢,可能導致連接池發生阻塞影響后續的大量存盤請求,這時 M 統計到的高延遲請求很少,而 X 統計到的高延遲會很多,最終也能形成 X 的 P99 遠大于 M 的 P99 的狀況。
histogram 場景下的 quantile
前面的內容都是從 quantile 的定義出發的,并不限于 Prometheus 平臺。具體針對 Prometheus 里的 histogram_quantile,還有一些要注意的點。
一個是因為 histogram 并不記錄所有數據,只記錄每個 bucket 下的 count 和 sum。如果 bucket 設置的不合理,會產生不符合預期的 quantile 結果。比如最大 bucket 設置的過小,實際上有大量的數據超出最大 bucket 的范圍,最后統計 quantile 也只會得到最大 bucket 的值。因此如果觀察到 histogram_quantile 曲線是筆直的水平線,很可能就是 bucket 設置不合理了。
另一種情況是 bucket 范圍過大,絕大多數記錄都落在同一個 bucket 里的一段小區間,也會導致較大的偏差。例如 bucket 是 100ms ~ 1000ms,而大部分記錄都在 100ms ~ 200ms 之間,計算 P99 會得到接近于 1000ms 的值,這是因為 Prometheus 沒記錄具體數值,便假定數據在整個 bucket 內均勻分布進行計算。Prometheus 的官方文檔 里也描述了這個問題。
本文轉載自 disksing 的個人博客。
更多分布式數據庫技術文章閱讀:
Blog-cns | PingCAP?pingcap.com總結
以上是生活随笔為你收集整理的统计各个函数的耗时_Prometheus 常用函数 histogram_quantile 的若干“反直觉”问题...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: echarts迁徙图 vue_vue中高
- 下一篇: ast抽象语法树_新抽象语法树(AST)