Redis的BigKey问题
什么是大Key问题?
大key问题其实可以说是大value问题,就是某个key对应的value所占据的存储空间太大了,所以导致我们在操作这个key的时候花费的时间过长(序列化\反序列化),从而降低了redis性能。
- Key对应的value本身的数据量过大:一个Strring类型的value,值为5MB。
- Key对应的value的成员数量过多:一个ZSet类型的key,对应的成员数量有10000个。
- key中成员的数据量过大:一个Hash类型的key,成员数量虽然只有1000个,但是这些成员的总大小太大了。比如达到100MB或者10MB。
单个key的value大小要建议小于10kb,集合类型的key元素数量要小于1000。
带来的问题
网络阻塞: 对大Key执行读请求的时候,少量的QPS就可能导致 带宽使用率 被占满了,导致Redis性能下降,甚至可能导致整个物理机变慢了。
数据倾斜: BigKey所在的Redis实例内存使用率会远超其它实例,无法使数据分片的内存资源达到均衡。
Redis阻塞: 对于元素较多的hash、list、zset等做运算的时候会很耗时,redis又是单线程的,其它请求不会被处理,就会导致主线程阻塞。
CPU压力: Redis中的的数据序列化和反序列化的时候都需要CPU运算,BigKey会导致CPU的使用率飙升,影响Redis实例和本机其它应用的使用。
如何删除BigKey?
由于Redis是单线程的,所以删除一个键值对的时候,如果是bigkey也需要耗费很长时间,导致redis主线程阻塞。 Redis4.0 之后,Redis提供了一个命令unlink,会把该键值对先标记成已删除,然后会去异步地删除该key。如果是 Redis3.0 以前,删除集合类型的话,就先遍历该集合元素,依次删除元素,最后再删除BigKey。
选择合适的数据结构
对于存储一个 对象 ,如果使用json字符串,那么就不够灵活,可以使用Hash结构,既灵活,空间占用也不是很大。
数据量太大的时候,单个hash可能会导致大key问题,hash结构的entry数量尽量不要超过1000;单独用string来存储的话,大量的key又会导致占用太多空间,所以要学会使用 分片哈希 。既节省空间,也避免了大key问题。