推薦學習:
排查思路
如果你的 Redis 範例設定了記憶體上限 maxmemory,那麼也有可能導致 Redis 變慢。
當我們把 Redis 當做純快取使用時,通常會給這個範例設定一個記憶體上限 maxmemory,然後設定一個資料淘汰策略。而當範例的記憶體達到了 maxmemory 後,你可能會發現,在此之後每次寫入新資料,操作延遲變大了。
導致變慢的原因
當 Redis 記憶體達到 maxmemory 後,每次寫入新的資料之前,Redis 必須先從範例中踢出一部分資料,讓整個範例的記憶體維持在 maxmemory 之下,然後才能把新資料寫進來。
這個踢出舊資料的邏輯也是需要消耗時間的,而具體耗時的長短,要取決於你設定的淘汰策略:
具體使用哪種策略,我們需要根據具體的業務場景來設定。一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略,它們的處理邏輯是,每次從範例中隨機取出一批 key(這個數量可設定),然後淘汰一個最少存取的 key,之後把剩下的 key 暫存到一個池子中,繼續隨機取一批 key,並與之前池子中的 key 比較,再淘汰一個最少存取的 key。以此往復,直到範例記憶體降到 maxmemory 之下。
需要注意的是,Redis 的淘汰資料的邏輯與刪除過期 key 的一樣,也是在命令真正執行之前執行的,也就是說它也會增加我們操作 Redis 的延遲,而且,寫 OPS 越高,延遲也會越明顯。
另外,如果此時你的 Redis 範例中還儲存了 bigkey,那麼在淘汰刪除 bigkey 釋放記憶體時,也會耗時比較久。
看到了麼?bigkey 的危害到處都是,這也是前面我提醒你儘量不儲存 bigkey 的原因。
解決方案
排查思路
導致變慢的原因
解決方案
關閉記憶體大頁機制。
首先,你需要檢視 Redis 機器是否開啟了記憶體大頁:
$ cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never
如果輸出選項是 always,就表示目前開啟了記憶體大頁機制,我們需要關掉它:
$ echo never > /sys/kernel/mm/transparent_hugepage/enabled
其實,作業系統提供的記憶體大頁機制,其優勢是,可以在一定程式上降低應用程式申請記憶體的次數。
但是對於 Redis 這種對效能和延遲極其敏感的資料庫來說,我們希望 Redis 在每次申請記憶體時,耗時儘量短,所以我不建議你在 Redis 機器上開啟這個機制。
排查思路
如果你發現 Redis 突然變得非常慢,每次的操作耗時都達到了幾百毫秒甚至秒級,那此時你就需要檢查 Redis 是否使用到了 Swap,在這種情況下 Redis 基本上已經無法提供高效能的服務了。
導致變慢的原因
什麼是 Swap?為什麼使用 Swap 會導致 Redis 的效能下降?
如果你對作業系統有些瞭解,就會知道作業系統為了緩解記憶體不足對應用程式的影響,允許把一部分記憶體中的資料換到磁碟上,以達到應用程式對記憶體使用的緩衝,這些記憶體資料被換到磁碟上的區域,就是 Swap。
問題就在於,當記憶體中的資料被換到磁碟上後,Redis 再存取這些資料時,就需要從磁碟上讀取,存取磁碟的速度要比存取記憶體慢幾百倍!尤其是針對 Redis 這種對效能要求極高、效能極其敏感的資料庫來說,這個操作延時是無法接受的。
此時,你需要檢查 Redis 機器的記憶體使用情況,確認是否存在使用了 Swap。你可以通過以下方式來檢視 Redis 程序是否使用到了 Swap:
# 先找到 Redis 的程序 ID $ ps -aux | grep redis-server # 檢視 Redis Swap 使用情況 $ cat /proc/$pid/smaps | egrep '^(Swap|Size)'
輸出結果如下
Size: 1256 kB Swap: 0 kB Size: 4 kB Swap: 0 kB Size: 132 kB Swap: 0 kB Size: 63488 kB Swap: 0 kB Size: 132 kB Swap: 0 kB Size: 65404 kB Swap: 0 kB Size: 1921024 kB Swap: 0 kB ...
這個結果會列出 Redis 程序的記憶體使用情況。
每一行 Size 表示 Redis 所用的一塊記憶體大小,Size 下面的 Swap 就表示這塊 Size 大小的記憶體,有多少資料已經被換到磁碟上了,如果這兩個值相等,說明這塊記憶體的資料都已經完全被換到磁碟上了。
如果只是少量資料被換到磁碟上,例如每一塊 Swap 佔對應 Size 的比例很小,那影響並不是很大。如果是幾百兆甚至上 GB 的記憶體被換到了磁碟上,那麼你就需要警惕了,這種情況 Redis 的效能肯定會急劇下降。
解決方案
釋放 Redis 的 Swap 過程通常要重新啟動範例,為了避免重新啟動範例對業務的影響,一般會先進行主從切換,然後釋放舊主節點的 Swap,重新啟動舊主節點範例,待從庫資料同步完成後,再進行主從切換即可。
可見,當 Redis 使用到 Swap 後,此時的 Redis 效能基本已達不到高效能的要求(你可以理解為武功被廢),所以你也需要提前預防這種情況。
預防的辦法就是,你需要對 Redis 機器的記憶體和 Swap 使用情況進行監控,在記憶體不足或使用到 Swap 時報警出來,及時處理。
排查思路
如果以上產生效能問題的場景,你都規避掉了,而且 Redis 也穩定執行了很長時間,但在某個時間點之後開始,操作 Redis 突然開始變慢了,而且一直持續下去,這種情況又是什麼原因導致?
此時你需要排查一下 Redis 機器的網路頻寬是否過載,是否存在某個範例把整個機器的網路頻寬佔滿的情況。
導致變慢的原因
網路頻寬過載的情況下,伺服器在 TCP 層和網路層就會出現封包傳送延遲、丟包等情況。
Redis 的高效能,除了操作記憶體之外,就在於網路 IO 了,如果網路 IO 存在瓶頸,那麼也會嚴重影響 Redis 的效能。
解決方案
1) 頻繁短連線
你的業務應用,應該使用長連線操作 Redis,避免頻繁的短連線。
頻繁的短連線會導致 Redis 大量時間耗費在連線的建立和釋放上,TCP 的三次握手和四次揮手同樣也會增加存取延遲。
2) 運維監控
前面我也提到了,要想提前預知 Redis 變慢的情況發生,必不可少的就是做好完善的監控。
監控其實就是對採集 Redis 的各項執行時指標,通常的做法是監控程式定時採集 Redis 的 INFO 資訊,然後根據 INFO 資訊中的狀態資料做資料展示和報警。
這裡我需要提醒你的是,在寫一些監控指令碼,或使用開源的監控元件時,也不能掉以輕心。
在寫監控指令碼存取 Redis 時,儘量採用長連線的方式採集狀態資訊,避免頻繁短連線。同時,你還要注意控制存取 Redis 的頻率,避免影響到業務請求。
在使用一些開源的監控元件時,最好了解一下這些元件的實現原理,以及正確設定這些元件,防止出現監控元件發生 Bug,導致短時大量操作 Redis,影響 Redis 效能的情況發生。
我們當時就發生過,DBA 在使用一些開源元件時,因為設定和使用問題,導致監控程式頻繁地與 Redis 建立和斷開連線,導致 Redis 響應變慢。
3)其它程式爭搶資源
最後需要提醒你的是,你的 Redis 機器最好專項專用,只用來部署 Redis 範例,不要部署其他應用程式,儘量給 Redis 提供一個相對「安靜」的環境,避免其它程式佔用 CPU、記憶體、磁碟資源,導致分配給 Redis 的資源不足而受到影響。
推薦學習:
以上就是一起聊聊Redis變慢的原因及排查方法的詳細內容,更多請關注TW511.COM其它相關文章!