大Key

zhengbiyu發表於2024-07-06

如何定義

以 Key 的大小和Key中成員的數量來綜合判定,例如:

  • Key本身的資料量過大。例如,一個String型別的Key,它的值為5 MB。

  • Key中的成員數過多。例如,一個ZSET型別的Key,它的成員數量為10,000個。

  • Key中成員的資料量過大。例如,一個Hash型別的Key,它的成員數量雖然只有2,000個但這些成員的Value(值)總大小為100 MB。

危害

  • 記憶體不均:單 Value 較大時候,可能會導致節點之間記憶體使用不均勻,導致負載不均衡。
  • 阻塞請求:redis 為單執行緒,單 Value 較大讀寫需要較長的處理時間,會阻塞後續的請求處理。
  • 阻塞網路:單 Value 較大時會佔用伺服器網路卡較多頻寬,可能導致出口頻寬打滿,影響該伺服器傻姑娘單其它 Redis 例項或應用。
  • 刪除阻塞:對大Key執行刪除操作,易造成主庫較長時間的阻塞,進而可能引發同步中斷或主從切換。

產生的原因

  • 在不適用的場景下使用Redis,易造成Key的value過大,如使用String型別的Key存放大體積二進位制檔案型資料;

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

  • 未定期清理無效資料,造成如HASH型別Key中的成員持續不斷地增加;

  • 使用LIST型別Key的業務消費側發生程式碼故障,造成對應Key的成員只增不減。

處理方案

  • 對大Key進行拆分。例如將含有數萬成員的一個HASH Key拆分為多個HASH Key,並確保每個Key的成員數量在合理範圍。在Redis叢集架構中,拆分大Key能對資料分片間的記憶體平衡起到顯著作用。

  • 對過期資料進行定期清理。堆積大量過期資料會造成大Key的產生,例如在HASH資料型別中以增量的形式不斷寫入大量資料而忽略了資料的時效性。可以透過定時任務的方式對失效資料進行清理。在清理HASH資料時,建議透過HSCAN命令配合HDEL命令對失效資料進行清理,避免清理大量資料造成Redis阻塞。

  • 對大Key進行清理,將不適用Redis能力的資料存至其它儲存,並在Redis中刪除此類資料。
    • Redis 4.0及之後版本:您可以透過UNLINK命令安全地刪除大Key甚至特大Key,該命令能夠以非阻塞的方式,逐步地清理傳入的Key。
    • Redis 4.0之前的版本:建議先透過SCAN命令讀取部分資料,然後進行刪除,避免一次性刪除大量key導致Redis阻塞。

應用

比如100萬個string物件,test1、test2、。。。testN。將100萬個鍵,對映到1000個hash中,每個hash儲存1000個元素。

對映規則:Hash(原key)% 1000得到新key,field為原key,value儲存原物件值。

額外用一組hash記錄field過期時間。

資料讀取時,需要透過hget(Hash(原key)% 1000, field)。

相關文章