Redis命令之HGetAll性能問題解決方案

最近工作中,系統壓測遇到一個性能瓶頸問題,通過最終排查,發現應用接口中使用了大量的Hgetall命令從Redis中查詢數據信息,導致Redis單實例OPS達到秒鐘7W次,Redis服務器CPU使用率達到上限,遇到性能問題。


HGETALL key

返回 key 指定的哈希集中所有的字段和值。返回值中,每個字段名的下一個是它的值,所以返回值的長度是哈希集大小的兩倍

返回值

array-reply:哈希集中字段和值的列表。當 key 指定的哈希集不存在時返回空列表。

例子

redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
redis> 





















通過官方文檔,可以瞭解到命令HgetAll的時間複雜度爲O(n)。這意味着Hash的field越多,當使用HgetAll獲取全量數

據時,性能越差,該命令的性能與field字段的數量成正比。

遇到問題後,上網查詢資料,解決方案大致兩種:

1) 藉助MemCached

2) 新增一個field字段,將原Redis key對應的所有數據信息全部存儲在該filed中,然後使用Hmget命令代替HgetAll

但是以上兩種方案,均存在各種弊端,並沒有從根本上解決問題。找公司其他部門技術大拿交流,最終討論出以下方案解決問題:

通過使用Redis dump命令獲取到Redis序列化後的值,獲取到的是字節數組。在應用中將該字節數組按照Redis協議自行解析成需要的HashMap數據。

方案優點:

1)  dump命令的時間複雜度爲O(1),性能優於HgetAll

2)  將字節數組的解析由Redis服務器轉移到了應用服務器,減輕了Redis 服務器CPU的運算壓力

3)  充分利用了應用服務器的CPU,並且應用服務器方便擴容。


DUMP key

序列化給定 key ,並返回被序列化的值,使用 RESTORE 命令可以將這個值反序列化爲 Redis 鍵。

序列化生成的值有以下幾個特點:

  • 它帶有 64 位的校驗和,用於檢測錯誤,RESTORE 在進行反序列化之前會先檢查校驗和。
  • 值的編碼格式和 RDB 文件保持一致。
  • RDB 版本會被編碼在序列化值當中,如果因爲 Redis 的版本不同造成 RDB 格式不兼容,那麼 Redis 會拒絕對這個值進行反序列化操作。

序列化的值不包括任何生存時間信息。

返回值

如果 key 不存在,那麼返回 nil。</br> 否則,返回序列化之後的值。

例子

redis> SET mykey 10
OK
redis> DUMP mykey
"\u0000\xC0\n\u0006\u0000\xF8r?\xC5\xFB\xFB_("
redis> 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章