推薦學習:Redis影片教學
排查思路
如果你的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)'
輸出結果如下
解決方案 增加機器的內存,讓Redis 有足夠的記憶體可以使用Size: 1256 kB
如果只是少量資料被換到磁碟上,例如每一塊 Swap 佔對應 Size 的比例很小,那麼影響並不是很大。如果是幾百兆甚至上 GB 的記憶體被換到了磁碟上,那麼你就需要警惕了,這種情況 Redis 的效能肯定會急劇下降。
Swap: 4 kB
Swap: 0 kB
Size: 63488 kB
Swap: 0 kB
Size: 0 kB
Size: 65404 kB## 1921024 kB
Swap: 0 kB
...
這個結果會列出Redis 行程的記憶體使用量。
每一行Size 表示Redis 所用的一塊內存大小,Size 下面的Swap 就表示這塊Size 大小的內存,有多少資料已經被換到磁碟上了,如果這兩個值相等,說明這區塊記憶體的資料都已經完全被換到磁碟上了。
整理記憶體空間,釋放出足夠的記憶體供Redis 使用,然後釋放Redis 的Swap,讓Redis 重新使用記憶體
原因4:網路頻寬過載
排查想法此時你需要排查 Redis 機器的網路頻寬是否過載,是否存在某個實例把整台機器的網路頻寬佔滿的狀況。
導致變慢的原因網路頻寬過載的情況下,伺服器在 TCP 層和網路層就會出現封包發送延遲、丟包等情況。
Redis 的高效能,除了操作記憶體之外,就在於網路 IO 了,如果網路 IO 存在瓶頸,那麼也會嚴重影響 Redis 的效能。
解決方案 及時確認佔滿網路頻寬Redis 實例,如果屬於正常的業務訪問,那就需要及時擴容或遷移實例了,避免因為這個實例流量太大,影響這個機器的其他實例。維運層面,你需要對 Redis 機器的各項指標增加監控,包括網路流量,在網路流量達到一定閾值時提前報警,及時確認和擴容。
頻繁的短連接會導致 Redis 大量時間耗費在連接的建立和釋放上,TCP 的三次握手和四次揮手同樣也會增加訪問延遲。
2) 運維監控前面我也提到了,要提前預知Redis 變慢的情況發生,不可或缺的就是做好完善的監控。
監控其實就是對採集 Redis 的各項運行時指標,通常的做法是監控程序定時採集 Redis 的 INFO 信息,然後根據 INFO 信息中的狀態數據做數據展示和警報。
這裡我需要提醒你的是,在寫一些監控腳本,或使用開源的監控元件時,也不能掉以輕心。
在寫入監控腳本存取 Redis 時,盡量採用長連接的方式採集狀態訊息,避免頻繁短連接。同時,你也要注意控制存取 Redis 的頻率,避免影響到業務請求。
在使用一些開源的監控元件時,最好了解一下這些元件的實作原理,以及正確配置這些元件,防止出現監控元件發生Bug,導致短時大量操作Redis,影響Redis 效能的情況發生。
我們當時就發生過,DBA 在使用一些開源元件時,因為配置和使用問題,導致監控程式頻繁地與 Redis 建立和斷開連接,導致 Redis 回應變慢。
3)其它程式爭搶資源
最後需要提醒你的是,你的Redis 機器最好專項專用,只用來部署Redis 實例,不要部署其他應用程序,盡量給Redis 一個相對「安靜」的環境,避免其它程式佔用CPU、記憶體、磁碟資源,導致分配給Redis 的資源不足而受到影響。
推薦學習:Redis影片教學
以上是淺談Redis變慢的原因及檢驗方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!