首頁 > 軟體

Redis中什麼是Big Key(大key)問題?如何解決Big Key問題?

2023-03-17 06:06:45

一、什麼是Big Key?

通俗易懂的講,Big Key就是某個key對應的value很大,佔用的redis空間很大,本質上是大value問題。key往往是程式可以自行設定的,value往往不受程式控制,因此可能導致value很大。

redis中這些Big Key對應的value值很大,在序列化/反序列化過程中花費的時間很大,因此當我們操作Big Key時,通常比較耗時,這就可能導致redis發生阻塞,從而降低redis效能。

用幾個實際的例子對大Key的特徵進行描述:

● 一個String型別的Key,它的值為5MB(資料過大);

● 一個List型別的Key,它的列表數量為20000個(列表數量過多);

● 一個ZSet型別的Key,它的成員數量為10000個(成員數量過多);

● 一個Hash格式的Key,它的成員數量雖然只有1000個但這些成員的value總大小為100MB(成員體積過大);

在實際業務中,大Key的判定仍然需要根據Redis的實際使用場景、業務場景來進行綜合判斷。通常都會以資料大小與成員數量來判定。

二、Big Key產生的場景?

1、redis資料結構使用不恰當

將Redis用在並不適合其能力的場景,造成Key的value過大,如使用String型別的Key存放大體積二進位制檔案型資料。

2、未及時清理垃圾資料

沒有對無效資料進行定期清理,造成如HASH型別Key中的成員持續不斷的增加。即一直往value塞資料,卻沒有刪除機制,value只會越來越大。

3、對業務預估不準確

業務上線前規劃設計考慮不足沒有對Key中的成員進行合理的拆分,造成個別Key中的成員數量過多。

4、明星、網紅的粉絲列表、某條熱點新聞的評論列表

假設我們使用List資料結構儲存某個明星/網紅的粉絲,或者儲存熱點新聞的評論列表,因為粉絲數量巨大,熱點新聞因為點選率、評論數會很多,這樣List集合中存放的元素就會很多,可能導致value過大,進而產生Big Key問題。

三、Big Key的危害?

1、阻塞請求

Big Key對應的value較大,我們對其進行讀寫的時候,需要耗費較長的時間,這樣就可能阻塞後續的請求處理。Redis的核心執行緒是單執行緒,單執行緒中請求任務的處理是序列的,前面的任務完不成,後面的任務就處理不了。

2、記憶體增大

讀取Big Key耗費的記憶體比正常Key會有所增大,如果不斷變大,可能會引發OOM(記憶體溢位),或達到redis的最大記憶體maxmemory設定值引發寫阻塞或重要Key被逐出。

3、阻塞網路

讀取單value較大時會佔用伺服器網路卡較多頻寬,自身變慢的同時可能會影響該伺服器上的其他Redis範例或者應用。

4、影響主從同步、主從切換

刪除一個大Key造成主庫較長時間的阻塞並引發同步中斷或主從切換。

四、如何識別Big Key?

1、使用redis自帶的命令識別

例如可以使用Redis官方使用者端redis-cli加上--bigkeys引數,可以找到某個範例5種資料型別(String、hash、list、set、zset)的最大key。
    優點是可以線上掃描,不阻塞服務;缺點是資訊較少,內容不夠精確。

2、使用debug object key命令

根據傳入的物件(Key的名稱)來對Key進行分析並返回大量資料,其中serializedlength的值為該Key的序列化長度,需要注意的是,Key的序列化長度並不等同於它在記憶體空間中的真實長度,此外,debug object屬於偵錯命令,執行代價較大,並且在其執行時,進入Redis的其餘請求將會被阻塞直到其執行完畢。並且每次只能查詢單個key的資訊,官方不推薦使用。

3、redis-rdb-tools開源工具

這種方式是在redis範例上執行bgsave,bgsave會觸發redis的快照備份,生成rdb持久化檔案,然後對dump出來的rdb檔案進行分析,找到其中的大key。

GitHub地址:https://github.com/sripathikrishnan/redis-rdb-tools

優點在於獲取的key資訊詳細、可選引數多、支援客製化化需求,結果資訊可選擇json或csv格式,後續處理方便,其缺點是需要離線操作,獲取結果時間較長。

五、如何解決Big Key問題?

要解決Big Key問題,無非就是減小key對應的value值的大小,也就是對於String資料結構的話,減少儲存的字串的長度;對於List、Hash、Set、ZSet資料結構則是減少集合中元素的個數。

1、對大Key進行拆分

將一個Big Key拆分為多個key-value這樣的小Key,並確保每個key的成員數量或者大小在合理範圍內,然後再進行儲存,通過get不同的key或者使用mget批次獲取。

2、對大Key進行清理

對Redis中的大Key進行清理,從Redis中刪除此類資料。Redis自4.0起提供了UNLINK命令,該命令能夠以非阻塞的方式緩慢逐步的清理傳入的Key,通過UNLINK,你可以安全的刪除大Key甚至特大Key。

3、監控Redis的記憶體、網路頻寬、超時等指標

通過監控系統並設定合理的Redis記憶體報警閾值來提醒我們此時可能有大Key正在產生,如:Redis記憶體使用率超過70%,Redis記憶體1小時內增長率超過20%等。

4、定期清理失效資料

如果某個Key有業務不斷以增量方式寫入大量的資料,並且忽略了其時效性,這樣會導致大量的失效資料堆積。可以通過定時任務的方式,對失效資料進行清理。

5、壓縮value

使用序列化、壓縮演演算法將key的大小控制在合理範圍內,但是需要注意序列化、反序列化都會帶來一定的消耗。如果壓縮後,value還是很大,那麼可以進一步對key進行拆分。

補充知識:key設計

(1)【建議】: 可讀性和可管理性

以業務名(或資料庫名)為字首(防止key衝突),用冒號分隔,比如業務名:表名:id
o2o:order:1

(2)【建議】:簡潔性

保證語意的前提下,控制key的長度,當key較多時,記憶體佔用也不容忽視,例如:
user:{uid}:friends:messages:{mid} 簡化為 u:{uid}


IT145.com E-mail:sddin#qq.com