Redis:Big Key问题


关键词

  • 发现:(预估,redis-cli --bigkeys命令,rdbtools分析rdb生成csv文)
  • 处理:(string减少字符串长度 [MongoDB或缓存到CDN] ;list、hash、set、zset等减少成员数;多线程删除unlink)

一、常见场景和大key的影响

大key指的是存储的值(Value)非常大,常见场景:

  • 热门话题下的讨论
  • 大V的粉丝列表
  • 序列化后的图片
  • 没有及时处理的垃圾数据

大key的影响:

大key会大量占用内存,在集群中无法均衡
Redis的性能下降,主从复制异常
在主动删除或过期删除时会操作时间过长而引起服务阻塞

二、如何发现大key

1、redis-cli --bigkeys命令。可以找到某个实例5种数据类型(String、hash、list、set、zset)的最大key。但如果Redis 的key比较多,执行该命令会比较慢
2、获取生产Redis的rdb文件,通过rdbtools分析rdb生成csv文件,再导入MySQL或其他数据库中进行分析统计,根据size_in_bytes统计bigkey

三、大key的处理

优化big key的原则就是string减少字符串长度,list、hash、set、zset等减少成员数。

1、string类型的big key,尽量不要存入Redis中,可以使用文档型数据库MongoDB或缓存到CDN上。
如果必须用Redis存储,最好单独存储,不要和其他的key一起存储。采用一主一从或多从。

2、单个简单的key存储的value很大,可以尝试将对象分拆成几个key-value, 使用mget获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多次操作中,降低对redis的IO影响。

3、hash, set,zset,list 中存储过多的元素,可以将这些元素分拆。(常见)

以hash类型举例来说,对于field过多的场景,可以根据field进行hash取模,生成一个新的key,例如原来的
hash_key:{filed1:value, filed2:value, filed3:value ...},可以hash取模后形成如下
key:value形式
hash_key:1:{filed1:value}
hash_key:2:{filed2:value}
hash_key:3:{filed3:value}
...
取模后,将原先单个key分成多个key,每个key filed个数为原先的1/N

4、删除大key时不要使用del,因为del是阻塞命令,删除时会影响性能。
使用 lazy delete (unlink命令)(多线程:redis4.0+)
删除指定的key(s),若key不存在则该key被跳过。但是,相比DEL会产生阻塞,该命令会在另一个线程中回收内存,因此它是非阻塞的。 这也是该命令名字的由来:仅将keys从key空间中删除,真正的数据删除会在后续异步操作。

redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> UNLINK key1 key2 key3
(integer) 2
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐