搜尋
首頁資料庫Redis淺談Redis變慢的原因及檢驗方法

推薦學習:Redis影片教學

#原因1:實例記憶體達到上限

排查思路

如果你的Redis 實例設定了記憶體上限maxmemory,那麼也有可能導致Redis 變慢。

當我們把 Redis 當做純快取使用時,通常會為這個實例設定一個記憶體上限 maxmemory,然後設定一個資料淘汰策略。而當實例的記憶體達到了 maxmemory 後,你可能會發現,在此之後每次寫入新數據,操作延遲變大了。

導致變慢的原因

當Redis 記憶體達到maxmemory 後,每次寫入新的資料之前,Redis 必須先從實例中踢出一部分數據,讓整個實例的記憶體維持在maxmemory 之下,然後才能把新資料寫進來。

這個踢出舊資料的邏輯也是需要消耗時間的,而具體耗時的長短,要取決於你配置的淘汰策略:

  • allkeys-lru:不管key是否設定了過期,淘汰最近最少訪問的key
  • volatile-lru:只淘汰最近最少訪問、並設定了過期時間的key
  • allkeys-random:不管key 是否設定了過期,隨機淘汰key
  • volatile-random:只隨機淘汰設定了過期時間的key
  • allkeys-ttl:不管key 是否設定了過期,淘汰即將過期的key
  • noeviction:不淘汰任何key,實例記憶體達到maxmeory 後,再寫入新資料直接回傳錯誤
  • allkeys-lfu:不管key 是否設定了過期,淘汰存取頻率最低的key(4.0 版本支援)
  • volatile-lfu:只淘汰訪問頻率最低、並設定了過期時間key(4.0 版本支援)

        具體使用哪種策略,我們需要根據特定的業務場景來配置。一般最常使用的是allkeys-lru / volatile-lru 淘汰策略,它們的處理邏輯是,每次從實例中隨機取出一批key(這個數量可配置),然後淘汰一個最少訪問的key,之後把剩下的key 暫存到一個池子中,繼續隨機取一批key,並與先前池子中的key 比較,再淘汰一個最少訪問的key。以此往復,直到實例記憶體降到 maxmemory 之下。

        需要注意的是,Redis 的淘汰資料的邏輯與刪除過期key 的一樣,也是在命令真正執行之前執行的,也就是說它也會增加我們操作Redis 的延遲,而且,寫OPS越高,延遲也會越明顯。

另外,如果此時你的 Redis 實例中還儲存了 bigkey,那麼在淘汰刪除 bigkey 釋放記憶體時,也會耗時比較久。

看到了麼? bigkey 的危害到處都是,這也是前面我提醒你盡量不儲存 bigkey 的原因。

解決方案

  • 避免儲存bigkey,降低釋放記憶體的耗時
  • 淘汰策略改為隨機淘汰,隨機淘汰比LRU要快很多(視業務狀況調整)
  • 分割實例,把淘汰key 的壓力分攤到多個實例上
  • 如果使用的是Redis 4.0 以上版本,開啟layz-free 機制,把淘汰key 釋放記憶體的操作放到後台執行緒執行(設定lazyfree-lazy-eviction = yes)

原因2:開啟記憶體大頁

#排查想法

  • 我們都知道,應用程式向作業系統申請記憶體時,是按記憶體頁申請的,而常規的記憶體頁大小是4KB。
  • Linux 核心從 2.6.38 開始,支援了記憶體大頁機制,該機制允許應用程式以 2MB 大小為單位,向作業系統申請記憶體。
  • 應用程式每次向作業系統申請的記憶體單位變大了,但這也意味著申請記憶體的耗時變長。

導致變慢的原因

#
  • 當 Redis 在執行後台 RDB 和 AOF rewrite 時,會採用 fork 子程序的方式來處理。但主進程 fork 子進程後,此時的主進程依舊是可以接收寫入請求的,而進來的寫入請求,會採用 Copy On Write(寫時複製)的方式操作記憶體資料。
  • 也就是說,主程序一旦有數據需要修改,Redis 並不會直接修改現有記憶體中的數據,而是先將這塊記憶體資料拷貝出來,再修改這塊新記憶體的數據,這就是所謂的「寫時複製」。
  • 寫時複製你也可以理解成,誰需要發生寫入操作,誰就需要先拷貝,再修改。
  • 這樣做的好處是,父進程有任何寫入操作,並不會影響子進程的資料持久化(子進程只持久化fork 這一瞬間整個實例中的所有資料即可,不關心新的資料變更,因為子進程只需要一份記憶體快照,然後持久化到磁碟上)。
  • 但是請注意,主進程在拷貝記憶體資料時,這個階段就涉及到新記憶體的申請,如果此時作業系統開啟了記憶體大頁,那麼在此期間,客戶端即便只修改10B 的數據,Redis 在申請記憶體時也會以2MB 為單位向作業系統申請,申請記憶體的耗時變長,進而導致每個寫入請求的延遲增加,影響到Redis 效能。
  • 同樣地,如果這個寫請求操作的是一個 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 機器上開啟這個機制。

原因3:使用Swap

檢查思路

#如果你發現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:                 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 大小的內存,有多少資料已經被換到磁碟上了,如果這兩個值相等,說明這區塊記憶體的資料都已經完全被換到磁碟上了。

如果只是少量資料被換到磁碟上,例如每一塊 Swap 佔對應 Size 的比例很小,那麼影響並不是很大。如果是幾百兆甚至上 GB 的記憶體被換到了磁碟上,那麼你就需要警惕了,這種情況 Redis 的效能肯定會急劇下降。

解決方案

增加機器的內存,讓Redis 有足夠的記憶體可以使用

整理記憶體空間,釋放出足夠的記憶體供Redis 使用,然後釋放Redis 的Swap,讓Redis 重新使用記憶體

    #釋放Redis 的Swap 過程通常要重啟實例,為了避免重啟實例對業務的影響,一般會先進行主從切換,然後釋放舊主節點的Swap,重啟舊主節點實例,待從庫資料同步完成後,再進行主從切換即可。
  • 可見,當 Redis 使用到 Swap 後,此時的 Redis 性能基本上已達不到高性能的要求(你可以理解為武功被廢),所以你也需要提前預防這種情況。
  • 預防的辦法就是,你需要對 Redis 機器的記憶體和 Swap 使用情況進行監控,在記憶體不足或使用到 Swap 時報警出來,及時處理。

原因4:網路頻寬過載 

排查想法

如果以上產生效能問題的場景,你都規避掉了,而且Redis 也穩定運行了很長一段時間,但在某個時間點之後開始,操作Redis 突然開始變慢了,而且一直持續下去,這種情況又是什麼原因導致?

此時你需要排查 Redis 機器的網路頻寬是否過載,是否存在某個實例把整台機器的網路頻寬佔滿的狀況。

導致變慢的原因

網路頻寬過載的情況下,伺服器在 TCP 層和網路層就會出現封包發送延遲、丟包等情況。

Redis 的高效能,除了操作記憶體之外,就在於網路 IO 了,如果網路 IO 存在瓶頸,那麼也會嚴重影響 Redis 的效能。

解決方案

及時確認佔滿網路頻寬Redis 實例,如果屬於正常的業務訪問,那就需要及時擴容或遷移實例了,避免因為這個實例流量太大,影響這個機器的其他實例。

維運層面,你需要對 Redis 機器的各項指標增加監控,包括網路流量,在網路流量達到一定閾值時提前報警,及時確認和擴容。

    原因5:其他原因
  • 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影片教學

以上是淺談Redis變慢的原因及檢驗方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:脚本之家。如有侵權,請聯絡admin@php.cn刪除
REDIS:探索其功能和功能REDIS:探索其功能和功能Apr 19, 2025 am 12:04 AM

Redis脫穎而出是因為其高速、多功能性和豐富的數據結構。 1)Redis支持字符串、列表、集合、散列和有序集合等數據結構。 2)它通過內存存儲數據,支持RDB和AOF持久化。 3)從Redis6.0開始引入多線程處理I/O操作,提升了高並發場景下的性能。

Redis是SQL還是NOSQL數據庫?答案解釋了Redis是SQL還是NOSQL數據庫?答案解釋了Apr 18, 2025 am 12:11 AM

RedisisclassifiedasaNoSQLdatabasebecauseitusesakey-valuedatamodelinsteadofthetraditionalrelationaldatabasemodel.Itoffersspeedandflexibility,makingitidealforreal-timeapplicationsandcaching,butitmaynotbesuitableforscenariosrequiringstrictdataintegrityo

REDIS:提高應用程序性能和可擴展性REDIS:提高應用程序性能和可擴展性Apr 17, 2025 am 12:16 AM

Redis通過緩存數據、實現分佈式鎖和數據持久化來提升應用性能和可擴展性。 1)緩存數據:使用Redis緩存頻繁訪問的數據,提高數據訪問速度。 2)分佈式鎖:利用Redis實現分佈式鎖,確保在分佈式環境中操作的安全性。 3)數據持久化:通過RDB和AOF機制保證數據安全性,防止數據丟失。

REDIS:探索其數據模型和結構REDIS:探索其數據模型和結構Apr 16, 2025 am 12:09 AM

Redis的數據模型和結構包括五種主要類型:1.字符串(String):用於存儲文本或二進制數據,支持原子操作。 2.列表(List):有序元素集合,適合隊列和堆棧。 3.集合(Set):無序唯一元素集合,支持集合運算。 4.有序集合(SortedSet):帶分數的唯一元素集合,適用於排行榜。 5.哈希表(Hash):鍵值對集合,適合存儲對象。

REDIS:對其數據庫方法進行分類REDIS:對其數據庫方法進行分類Apr 15, 2025 am 12:06 AM

Redis的數據庫方法包括內存數據庫和鍵值存儲。 1)Redis將數據存儲在內存中,讀寫速度快。 2)它使用鍵值對存儲數據,支持複雜數據結構,如列表、集合、哈希表和有序集合,適用於緩存和NoSQL數據庫。

為什麼要使用redis?利益和優勢為什麼要使用redis?利益和優勢Apr 14, 2025 am 12:07 AM

Redis是一個強大的數據庫解決方案,因為它提供了極速性能、豐富的數據結構、高可用性和擴展性、持久化能力以及廣泛的生態系統支持。 1)極速性能:Redis的數據存儲在內存中,讀寫速度極快,適合高並發和低延遲應用。 2)豐富的數據結構:支持多種數據類型,如列表、集合等,適用於多種場景。 3)高可用性和擴展性:支持主從復制和集群模式,實現高可用性和水平擴展。 4)持久化和數據安全:通過RDB和AOF兩種方式實現數據持久化,確保數據的完整性和可靠性。 5)廣泛的生態系統和社區支持:擁有龐大的生態系統和活躍社區,

了解NOSQL:Redis的關鍵特徵了解NOSQL:Redis的關鍵特徵Apr 13, 2025 am 12:17 AM

Redis的關鍵特性包括速度、靈活性和豐富的數據結構支持。 1)速度:Redis作為內存數據庫,讀寫操作幾乎瞬時,適用於緩存和會話管理。 2)靈活性:支持多種數據結構,如字符串、列表、集合等,適用於復雜數據處理。 3)數據結構支持:提供字符串、列表、集合、哈希表等,適合不同業務需求。

REDIS:確定其主要功能REDIS:確定其主要功能Apr 12, 2025 am 12:01 AM

Redis的核心功能是高性能的內存數據存儲和處理系統。 1)高速數據訪問:Redis將數據存儲在內存中,提供微秒級別的讀寫速度。 2)豐富的數據結構:支持字符串、列表、集合等,適應多種應用場景。 3)持久化:通過RDB和AOF方式將數據持久化到磁盤。 4)發布訂閱:可用於消息隊列或實時通信系統。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具