Redis效能瓶頸揭秘:如何最佳化大key問題?

一燈架構發表於2023-04-17

image

1. 什麼是Redis大key問題

Redis大key問題指的是某個key對應的value值所佔的記憶體空間比較大,導致Redis的效能下降、記憶體不足、資料不均衡以及主從同步延遲等問題。

到底多大的資料量才算是大key?

沒有固定的判別標準,通常認為字串型別的key對應的value值佔用空間大於1M,或者集合型別的k元素數量超過1萬個,就算是大key。

Redis大key問題的定義及評判準則並非一成不變,而應根據Redis的實際運用以及業務需求來綜合評估。例如,在高併發且低延遲的場景中,僅10kb可能就已構成大key;然而在低併發、高容量的環境下,大key的界限可能在100kb。因此,在設計與運用Redis時,要依據業務需求與效能指標來確立合理的大key閾值。

2. 大key帶來的影響

  1. 記憶體佔用過高。大Key佔用過多的記憶體空間,可能導致可用記憶體不足,從而觸發記憶體淘汰策略。在極端情況下,可能導致記憶體耗盡,Redis例項崩潰,影響系統的穩定性。
  2. 效能下降。大Key會佔用大量記憶體空間,導致記憶體碎片增加,進而影響Redis的效能。對於大Key的操作,如讀取、寫入、刪除等,都會消耗更多的CPU時間和記憶體資源,進一步降低系統效能。
  3. 阻塞其他操作。某些對大Key的操作可能會導致Redis例項阻塞。例如,使用DEL命令刪除一個大Key時,可能會導致Redis例項在一段時間內無法響應其他客戶端請求,從而影響系統的響應時間和吞吐量。
  4. 網路擁塞。每次獲取大key產生的網路流量較大,可能造成機器或區域網的頻寬被打滿,同時波及其他服務。例如:一個大key佔用空間是1MB,每秒訪問1000次,就有1000MB的流量。
  5. 主從同步延遲。當Redis例項配置了主從同步時,大Key可能導致主從同步延遲。由於大Key佔用較多記憶體,同步過程中需要傳輸大量資料,這會導致主從之間的網路傳輸延遲增加,進而影響資料一致性。
  6. 資料傾斜。在Redis叢集模式中,某個資料分片的記憶體使用率遠超其他資料分片,無法使資料分片的記憶體資源達到均衡。另外也可能造成Redis記憶體達到maxmemory引數定義的上限導致重要的key被逐出,甚至引發記憶體溢位。

3. 大key產生的原因

  1. 業務設計不合理。這是最常見的原因,不應該把大量資料儲存在一個key中,而應該分散到多個key。例如:把全國資料按照省行政區拆分成34個key,或者按照城市拆分成300個key,可以進一步降低產生大key的機率。
  2. 沒有預見value的動態增長問題。如果一直新增value資料,沒有刪除機制、過期機制或者限制數量,遲早出現大key。例如:微博明星的粉絲列表、熱門評論等。
  3. 過期時間設定不當。如果沒有給某個key設定過期時間,或者過期時間設定較長。隨著時間推移,value數量快速累積,最終形成大key。
  4. 程式bug。某些異常情況導致某些key的生命週期超出預期,或者value數量異常增長 ,也會產生大key。

4. 怎樣排查大key

4.1 SCAN命令

透過使用Redis的SCAN命令,我們可以逐步遍歷資料庫中的所有Key。結合其他命令(如STRLEN、LLEN、SCARD、HLEN等),我們可以識別出大Key。SCAN命令的優勢在於它可以在不阻塞Redis例項的情況下進行遍歷。

4.2 bigkeys引數

使用redis-cli命令客戶端,連線Redis服務的時候,加上 —bigkeys 引數,可以掃描每種資料型別數量最大的key。

redis-cli -h 127.0.0.1 -p 6379 —bigkeys

4.3 Redis RDB Tools工具

使用開源工具Redis RDB Tools,分析RDB檔案,掃描出Redis大key。

例如:輸出佔用記憶體大於1kb,排名前3的keys。

rdb —commond memory —bytes 1024 —largest 3 dump.rbd

5. 怎麼解決大key

  1. 拆分成多個小key。這是最容易想到的辦法,降低單key的大小,讀取可以用mget批次讀取。
  2. 資料壓縮。使用String型別的時候,使用壓縮演算法減少value大小。或者是使用Hash型別儲存,因為Hash型別底層使用了壓縮列表資料結構。
  3. 設定合理的過期時間。為每個key設定過期時間,並設定合理的過期時間,以便在資料失效後自動清理,避免長時間累積的大Key問題。
  4. 啟用記憶體淘汰策略。啟用Redis的記憶體淘汰策略,例如LRU(Least Recently Used,最近最少使用),以便在記憶體不足時自動淘汰最近最少使用的資料,防止大Key長時間佔用記憶體。
  5. 資料分片。例如使用Redis Cluster將資料分散到多個Redis例項,以減輕單個例項的負擔,降低大Key問題的風險。
  6. 刪除大key。使用UNLINK命令刪除大key,UNLINK命令是DEL命令的非同步版本,它可以在後臺刪除Key,避免阻塞Redis例項。

6. 總結

大Key問題是Redis中常見的問題之一,可能導致效能下降、記憶體佔用過高、阻塞其他操作以及主從同步延遲等問題。本文詳細介紹了大Key產生的原因、影響、檢測方法和解決方案。透過最佳化資料結構設計、設定合理的資料過期策略、最佳化系統架構和配置,以及漸進式刪除大Key等方法,我們可以有效地解決和預防大Key問題,從而提高Redis系統的穩定性和效能。

我是「一燈架構」,如果本文對你有幫助,歡迎各位小夥伴點贊、評論和關注,感謝各位老鐵,我們下期見

image

相關文章