淺談Redis常見延遲問題定位與分析
使用復雜度高的命令
如果在使用Redis時,發(fā)現(xiàn)訪問延遲突然增大,如何進行排查?
首先,第一步,建議你去查看一下Redis的慢日志。Redis提供了慢日志命令的統(tǒng)計功能,我們通過以下設(shè)置,就可以查看有哪些命令在執(zhí)行時延遲比較大。
首先設(shè)置Redis的慢日志閾值,只有超過閾值的命令才會被記錄,這里的單位是微妙,例如設(shè)置慢日志的閾值為5毫秒,同時設(shè)置只保留最近1000條慢日志記錄:
# 命令執(zhí)行超過5毫秒記錄慢日志 CONFIG SET slowlog-log-slower-than 5000 # 只保留最近1000條慢日志 CONFIG SET slowlog-max-len 1000
設(shè)置完成之后,所有執(zhí)行的命令如果延遲大于5毫秒,都會被Redis記錄下來,我們執(zhí)行SLOWLOG get 5查詢最近5條慢日志:
127.0.0.1:6379> SLOWLOG get 5 1) 1) (integer) 32693 # 慢日志ID 2) (integer) 1593763337 # 執(zhí)行時間 3) (integer) 5299 # 執(zhí)行耗時(微妙) 4) 1) "LRANGE" # 具體執(zhí)行的命令和參數(shù) 2) "user_list_2000" 3) "0" 4) "-1" 2) 1) (integer) 32692 2) (integer) 1593763337 3) (integer) 5044 4) 1) "GET" 2) "book_price_1000" ...
通過查看慢日志記錄,我們就可以知道在什么時間執(zhí)行哪些命令比較耗時,如果你的業(yè)務(wù)經(jīng)常使用O(N)以上復雜度的命令,例如sort、sunion、zunionstore、keys、scan,或者在執(zhí)行O(N)命令時操作的數(shù)據(jù)量比較大,這些情況下Redis處理數(shù)據(jù)時就會很耗時。
如果你的服務(wù)請求量并不大,但Redis實例的CPU使用率很高,很有可能是使用了復雜度高的命令導致的。
解決方案就是,不使用這些復雜度較高的命令,并且一次不要獲取太多的數(shù)據(jù),每次盡量操作少量的數(shù)據(jù),讓Redis可以及時處理返回。
存儲bigkey
如果查詢慢日志發(fā)現(xiàn),并不是復雜度較高的命令導致的,例如都是SET、DELETE操作出現(xiàn)在慢日志記錄中,那么你就要懷疑是否存在Redis寫入了bigkey的情況。
Redis在寫入數(shù)據(jù)時,需要為新的數(shù)據(jù)分配內(nèi)存,當從Redis中刪除數(shù)據(jù)時,它會釋放對應的內(nèi)存空間。
如果一個key寫入的數(shù)據(jù)非常大,Redis在分配內(nèi)存時也會比較耗時。同樣的,當刪除這個key的數(shù)據(jù)時,釋放內(nèi)存也會耗時比較久。
你需要檢查你的業(yè)務(wù)代碼,是否存在寫入bigkey的情況,需要評估寫入數(shù)據(jù)量的大小,業(yè)務(wù)層應該避免一個key存入過大的數(shù)據(jù)量。
針對bigkey的問題,Redis官方在4.0版本推出了lazy-free的機制,用于異步釋放bigkey的內(nèi)存,降低對Redis性能的影響。即使這樣,我們也不建議使用bigkey,bigkey在集群的遷移過程中,也會影響到遷移的性能,這個后面在介紹集群相關(guān)的文章時,會再詳細介紹到。
集中過期
有時你會發(fā)現(xiàn),平時在使用Redis時沒有延時比較大的情況,但在某個時間點突然出現(xiàn)一波延時,而且報慢的時間點很有規(guī)律,例如某個整點,或者間隔多久就會發(fā)生一次。
如果出現(xiàn)這種情況,就需要考慮是否存在大量key集中過期的情況。
如果有大量的key在某個固定時間點集中過期,在這個時間點訪問Redis時,就有可能導致延遲增加。
Redis的過期策略采用定期刪除+惰性刪除兩種策略;
注意,Redis的定期刪除的定時任務(wù),也是在Redis主線程中執(zhí)行的,也就是說如果在執(zhí)行主動過期的過程中,出現(xiàn)了需要大量刪除過期key的情況,那么在業(yè)務(wù)訪問時,必須等這個過期任務(wù)執(zhí)行結(jié)束,才可以處理業(yè)務(wù)請求。此時就會出現(xiàn),業(yè)務(wù)訪問延時增大的問題,最大延遲為25毫秒。
而且這個訪問延遲的情況,不會記錄在慢日志里。慢日志中只記錄真正執(zhí)行某個命令的耗時,Redis主動過期策略執(zhí)行在操作命令之前,如果操作命令耗時達不到慢日志閾值,它是不會計算在慢日志統(tǒng)計中的,但我們的業(yè)務(wù)卻感到了延遲增大。
解決方案是,在集中過期時增加一個隨機時間,把這些需要過期的key的時間打散即可。
實例內(nèi)存達到上限
有時我們把Redis當做純緩存使用,就會給實例設(shè)置一個內(nèi)存上限maxmemory,然后開啟LRU淘汰策略。
當實例的內(nèi)存達到了maxmemory后,你會發(fā)現(xiàn)之后的每次寫入新的數(shù)據(jù),有可能變慢了。
導致變慢的原因是,當Redis內(nèi)存達到maxmemory后,每次寫入新的數(shù)據(jù)之前,必須先踢出一部分數(shù)據(jù),讓內(nèi)存維持在maxmemory之下。
這個踢出舊數(shù)據(jù)的邏輯也是需要消耗時間的,而具體耗時的長短,要取決于配置的淘汰策略
fork耗時嚴重
如果你的Redis開啟了自動生成RDB和AOF重寫功能,那么有可能在后臺生成RDB和AOF重寫時導致Redis的訪問延遲增大,而等這些任務(wù)執(zhí)行完畢后,延遲情況消失。
遇到這種情況,一般就是執(zhí)行生成RDB和AOF重寫任務(wù)導致的。
生成RDB和AOF都需要父進程fork出一個子進程進行數(shù)據(jù)的持久化,在fork執(zhí)行過程中,父進程需要拷貝內(nèi)存頁表給子進程,如果整個實例內(nèi)存占用很大,那么需要拷貝的內(nèi)存頁表會比較耗時,此過程會消耗大量的CPU資源,在完成fork之前,整個實例會被阻塞住,無法處理任何請求,如果此時CPU資源緊張,那么fork的時間會更長,甚至達到秒級。這會嚴重影響Redis的性能。
綁定CPU
很多時候,我們在部署服務(wù)時,為了提高性能,降低程序在使用多個CPU時上下文切換的性能損耗,一般會采用進程綁定CPU的操作。
但在使用Redis時,我們不建議這么干,原因如下。
綁定CPU的Redis,在進行數(shù)據(jù)持久化時,fork出的子進程,子進程會繼承父進程的CPU使用偏好,而此時子進程會消耗大量的CPU資源進行數(shù)據(jù)持久化,子進程會與主進程發(fā)生CPU爭搶,這也會導致主進程的CPU資源不足訪問延遲增大。
所以在部署Redis進程時,如果需要開啟RDB和AOF重寫機制,一定不能進行CPU綁定操作
使用Swap
如果你發(fā)現(xiàn)Redis突然變得非常慢,每次訪問的耗時都達到了幾百毫秒甚至秒級,那此時就檢查Redis是否使用到了Swap,這種情況下Redis基本上已經(jīng)無法提供高性能的服務(wù)。
我們知道,操作系統(tǒng)提供了Swap機制,目的是為了當內(nèi)存不足時,可以把一部分內(nèi)存中的數(shù)據(jù)換到磁盤上,以達到對內(nèi)存使用的緩沖。
但當內(nèi)存中的數(shù)據(jù)被換到磁盤上后,訪問這些數(shù)據(jù)就需要從磁盤中讀取,這個速度要比內(nèi)存慢太多!
尤其是針對Redis這種高性能的內(nèi)存數(shù)據(jù)庫來說,如果Redis中的內(nèi)存被換到磁盤上,對于Redis這種性能極其敏感的數(shù)據(jù)庫,這個操作時間是無法接受的??梢耘R時關(guān)閉操作系統(tǒng)Swap
網(wǎng)卡負載過高
特點就是從某個時間點之后就開始變慢,并且一直持續(xù)。這時你需要檢查一下機器的網(wǎng)卡流量,是否存在網(wǎng)卡流量被跑滿的情況。
網(wǎng)卡負載過高,在網(wǎng)絡(luò)層和TCP層就會出現(xiàn)數(shù)據(jù)發(fā)送延遲、數(shù)據(jù)丟包等情況。Redis的高性能除了內(nèi)存之外,就在于網(wǎng)絡(luò)IO,請求量突增會導致網(wǎng)卡負載變高。
如果出現(xiàn)這種情況,你需要排查這個機器上的哪個Redis實例的流量過大占滿了網(wǎng)絡(luò)帶寬,然后確認流量突增是否屬于業(yè)務(wù)正常情況,如果屬于那就需要及時擴容或遷移實例,避免這個機器的其他實例受到影響。
到此這篇關(guān)于淺談Redis常見延遲問題定位與分析的文章就介紹到這了,更多相關(guān)Redis 延遲問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
redis?for?windows?6.2.6安裝包最新步驟詳解
這篇文章主要介紹了redis?for?windows?6.2.6安裝包全網(wǎng)首發(fā),使用Windows計劃任務(wù)自動運行redis服務(wù),文章給大家講解的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04Window下對Redis進行開啟與關(guān)閉的操作方法
這篇文章主要介紹了Window下對Redis進行開啟與關(guān)閉的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11Redis Sentinel實現(xiàn)哨兵模式搭建小結(jié)
這篇文章主要介紹了Redis Sentinel實現(xiàn)哨兵模式搭建小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12