Redis命令之HGetAll性能问题解决方案

最近工作中,系统压测遇到一个性能瓶颈问题,通过最终排查,发现应用接口中使用了大量的Hgetall命令从Redis中查询数据信息,导致Redis单实例OPS达到秒钟7W次,Redis服务器CPU使用率达到上限,遇到性能问题。

HGETALL key

起始版本:2.0.0

时间复杂度:O(N) where N is the size of the hash.

返回 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

起始版本:2.6.0

时间复杂度: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 版本会被编码在序列化值当中,如果因为 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。

序列化的值不包括任何生存时间信息。

返回值

如果 key 不存在,那么返回 nil。</br> 否则,返回序列化之后的值。

例子

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

 

 

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值