一、BigKey
1. 1 什么是BigKey
BigKey是指对应的value所占用的内存空间比较大,例如一个字符串类型的value可以最大存到512MB,一个列表类型的value最多可以存储2^32 - 1个元素。如果按照数据结构来细分的话,一般分为字符串类型bigkey和非字符串类型bigkey。
- 字符串类型:体现在单个value值很大,一般认为超过10KB就是BigKey。
- 非字符串类型:哈希、列表、集合、有序集合,体现在元素过多。
[!NOTE]
注:其实BigKey没有明确的大小,一般和集群的带宽以及QPS相关,如果集群整体带宽是1GB,QPS是10,那一个10KB的value也不会有什么影响,因此也算不上BigKey;反之如果集群的带宽是1MB,QPS是1000,那一个10KB的value就会使得可以处理的QPS下降了。
1.2 BigKey危害
BigKey的危害体现在三个方面:
- 内存空间不均匀:即数据可能会倾斜。
- 超时阻塞:由于单线程的特性,操作BigKey比较耗时,也就意味着阻塞Redis的可能性增大。
- 网络拥塞:每次获取BigKey产生的网络流量大,假设一个BigKey为1MB,每秒访问量为1000,那么每秒产生1000MB的流量,对于普通的千兆网卡(按照字节算是128MB/s)的服务器来说简直是灭顶之灾,而且一般服务器会采用单机多实例来部署,也就是说一个BigKey可能会对其他实例造成影响。
BigKey的存在并不是完全致命的,如果这个BigKey存在但是几乎不被访问,那么只有内存空间不均匀的问题存在,相较于另外两个问题没有那么紧急,但是如果一个BigKey是一个热点Key那么带来的危害不可想象。
1.3 怎么处理
1.3.1 分割大键
- 数据拆分:将一个大键分割成多个小键。例如,如果是一个大列表,可以将其拆分为多个小列表。
- 使用集合或哈希:将数据存储在集合或哈希中,合理规划数据结构以避免单个键太大。
1.3.2 定期清理
定期监控大键,并清除不在需要的数据。清除时要注意方法,如果直接使用del命令,因为Redis是单线程执行命令的,所以可能会造成阻塞。
如下表12-3展示了删除512KB-10MB的字符串类型数据所花费的时间,总体来说由于字符串类型结构相对简单,删除速度比较快,但是随着value值的不断增大,删除速度也逐渐变慢。
下表展示了非字符串类类型的数据结构在不同数量级、不同元素大小下对bigkey执行del命令的时间,整体上看元素个数越多、元素越大、删除时间越长,相对于字符串类型,这种删除速度足够可以阻塞Redis。
所以我们在删除的时候,要使用渐进式删除的方法,例如以hash为例子,使用hscan命令,每次获取部分(例如100个)field-value,再利用hdel删除每个field。
部分(例如100个)field-value,再利用hdel删除每个field。