Redis命令之HGetAll性能问题解决方案
最近工作中,系統(tǒng)壓測遇到一個性能瓶頸問題,通過最終排查,發(fā)現(xiàn)應(yīng)用接口中使用了大量的Hgetall命令從Redis中查詢數(shù)據(jù)信息,導(dǎo)致Redis單實例OPS達到秒鐘7W次,Redis服務(wù)器CPU使用率達到上限,遇到性能問題。
HGETALL?key
起始版本:2.0.0
時間復(fù)雜度:O(N) where N is the size of the hash.
返回 key 指定的哈希集中所有的字段和值。返回值中,每個字段名的下一個是它的值,所以返回值的長度是哈希集大小的兩倍
返回值
array-reply:哈希集中字段和值的列表。當(dāng) 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的時間復(fù)雜度為O(n)。這意味著Hash的field越多,當(dāng)使用HgetAll獲取全量數(shù)
據(jù)時,性能越差,該命令的性能與field字段的數(shù)量成正比。
遇到問題后,上網(wǎng)查詢資料,解決方案大致兩種:
1) 借助MemCached
2) 新增一個field字段,將原Redis key對應(yīng)的所有數(shù)據(jù)信息全部存儲在該filed中,然后使用Hmget命令代替HgetAll
但是以上兩種方案,均存在各種弊端,并沒有從根本上解決問題。找公司其他部門技術(shù)大拿交流,最終討論出以下方案解決問題:
通過使用Redis dump命令獲取到Redis序列化后的值,獲取到的是字節(jié)數(shù)組。在應(yīng)用中將該字節(jié)數(shù)組按照Redis協(xié)議自行解析成需要的HashMap數(shù)據(jù)。
方案優(yōu)點:
1) ?dump命令的時間復(fù)雜度為O(1),性能優(yōu)于HgetAll
2) ?將字節(jié)數(shù)組的解析由Redis服務(wù)器轉(zhuǎn)移到了應(yīng)用服務(wù)器,減輕了Redis 服務(wù)器CPU的運算壓力
3) ?充分利用了應(yīng)用服務(wù)器的CPU,并且應(yīng)用服務(wù)器方便擴容。
?
?
DUMP?key
起始版本:2.6.0
時間復(fù)雜度:O(1) to access the key and additional O(N*M) to serialized it, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1).
序列化給定 key ,并返回被序列化的值,使用?RESTORE?命令可以將這個值反序列化為 Redis 鍵。
序列化生成的值有以下幾個特點:
- 它帶有 64 位的校驗和,用于檢測錯誤,RESTORE?在進行反序列化之前會先檢查校驗和。
- 值的編碼格式和 RDB 文件保持一致。
- RDB 版本會被編碼在序列化值當(dāng)中,如果因為 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 會拒絕對這個值進行反序列化操作。
序列化的值不包括任何生存時間信息。
返回值
如果 key 不存在,那么返回 nil。</br> 否則,返回序列化之后的值。
例子
redis> SET mykey 10 OK redis> DUMP mykey "\u0000\xC0\n\u0006\u0000\xF8r?\xC5\xFB\xFB_(" redis>?
?
總結(jié)
以上是生活随笔為你收集整理的Redis命令之HGetAll性能问题解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vb.net怎么和mysql连接_解析V
- 下一篇: cocos Builder的一点理解