Redis latency spikes and the 99th percentile

Salvatore Sanfilippo

Redis 延遲突波與第 99 百分位數

Stripe 關於 Redis 的部落格文章中有個有趣之處,就是他們附上了測試期間取得的延遲圖表。為了將資料持久化至磁碟,Redis 必須呼叫 fork() 系統呼叫。通常在使用實體伺服器以及大多數 hypervisors(虛擬化管理程式) 的情況下,即使處理程序很大,fork 的速度依然很快。然而 Xen 在執行 fork 時速度緩慢,因此在某些 EC2 執行個體類型(以及其他虛擬伺服器供應商)上,每當父處理程序為了持久化至磁碟而執行 fork 時,就可能出現嚴重的延遲突波。Stripe 的圖表在這方面相當清楚。

如你所料,如果你在 fork 期間進行延遲測試,所有恰逢父處理程序執行 fork 的瞬間而經過的請求,都會被延遲最多一秒(以上圖為例,不確定當時的處理程序大小或 EC2 執行個體為何)。這會產生若干高延遲樣本,並影響第 99 百分位數的結果。

為了改善此現象而更換執行個體類型、設定、架構或其他任何做法都是好主意,而且確實有些使用情境是連單一請求的延遲過高都無法接受。然而,顯然並非每個人都清楚,每 30 分鐘發生一次 1 秒的延遲突波(若使用 AOF 並搭配適當的重寫觸發條件,間隔可能更久),與在請求集合中平均分布的延遲突波有著非常大的差異。

在突波平均分布的情況下,如果產生一個頁面需要對 Redis 伺服器發出多個請求來組成輸出,那麼該次頁面瀏覽很有可能會承受延遲懲罰:這可能會大幅影響服務品質,詳見此連結:http://latencytipoftheday.blogspot.it/2014/06/latencytipoftheday-most-page-loads.html

然而,每 30 分鐘出現一次 1 秒延遲的情況則完全不同。首先,隨著請求數量增加,呈現良好延遲的百分位數反而會變得更好,因為請求越多,這 1 秒的延遲就越不容易在樣本中被過度代表(如果你每分鐘只有 1 個請求,而其中一個請求剛好碰上高延遲,它對第 99.99 百分位數的影響,將遠大於每秒 100 個請求的情況)。

第二:大多數的頁面瀏覽不會受到影響。唯一會看到 1 秒延遲的使用者,是那些發出的請求剛好橫跨 fork 呼叫的使用者。所有其他請求遇到延遲明顯高於平均延遲的請求的機率都極低。另請注意,即使一個橫跨 fork 時間點的頁面瀏覽由 100 個請求組成,其延遲也不會超過一秒,因為所有請求會在 fork() 呼叫結束後隨即完成。

總結來說,如果對每一個單一請求都有嚴格的延遲要求,那麼一個會不時讓請求延遲 1 秒的架構顯然是個大問題。然而,當目標是提供良好的服務品質時,延遲突波的分布對結果有著巨大的影響。Redis 在 Xen 上因 fork 產生的延遲突波,在時間軸上是孤立的點,因此它們影響的頁面瀏覽比例,即使這些頁面瀏覽由大量 Redis 請求組成,也與延遲突波的總時間占比成正比,在此案例中即為每 1800 秒出現 1 秒,因此只有 0.05% 的頁面瀏覽會受到影響。

延遲特性很難以單一指標來捕捉:完整的百分位數曲線與突波的分布,才能提供更完整的全貌。一般而言,良好的經驗法則是展開研究的起點,而且平均延遲確實是個不佳的指標,這點大致上是正確的。然而,將經驗法則提升為絕對真理也有其缺點,因為許多複雜的事物終究還是複雜的,無論我們多想將其過度簡化,都仍需要仔細檢視。

同時,在 EC2 執行個體上的 fork 延遲,是當今最熱門的執行環境之一中,Redis 使用者最糟的體驗之一,因此我現在開始定期在 EC2 上測試 Redis:我們很快就會在 Redis 官方文件上提供針對 EC2 的最佳化專頁,以及一種在停用持久化的情況下更安全地運作 master-slaves replicas(主從式複本) 的方法。

如果你現在就需要 EC2 加上已停用持久化的 Redis master,最簡單可部署的「快速解法」是停用 Redis 執行個體的自動重新啟動,並使用 Sentinel 來進行 failover(容錯移轉),如此一來,當機的 master 就不會自動恢復為可用狀態,而會由 Sentinel 執行 failover。系統管理員可以在確認 failover 成功且已有新的作用中 master 後,再手動重新啟動原本的 master。

編註:請務必查看包含關於 EC2、Xen 與 fork 時間的有趣資訊的 Hacker News 討論串:https://news.ycombinator.com/item?id=8532851。另外,並非所有的 EC2 執行個體都相同,某些類型在 fork 時間方面的表現可媲美實體機系統:https://redislabs.com/blog/testing-fork-time-on-awsxen-infrastructure#.VFJQ-JPF8yF

原文由 Salvatore Sanfilippo 發布

本文章由 muse-spark-1.2-contributor 進行翻譯