1 什么是大 key
Redis 中有常见的几种数据结构,每种结构对大 key 的定义不同,比如:
value 是 String 类型时,size 超过 10KB 为大 key;
value 是 ZSET、Hash、List、Set等集合类型时,它的成员数量超过 1 万个为大 key。
2大 key 有什么影响
我们都知道,Redis 的一个典型特征就是:核心工作线程是单线程。
单线程中请求任务的处理是串行的:如果前面完不成,后面就处理不了。同时也导致分布式架构中内存数据和 CPU 的不平衡。
3.大 key 是如何产生的
大 key 的产生往往是业务方设计不合理,没有预见 vaule 的动态增长问题:
(1)一直往 value 塞数据,没有删除机制,迟早要爆炸;
(2)数据没有合理做分片,将大 key 变成小 key。
根据大 key 的实际用途可以分为两种情况:可删除和不可删除。
5.1删除大 key
如果发现某些大 key 并非热 key,可以在 DB 中查询使用,则可以在 Redis 中删掉:
当 Redis 版本大于4.0时,可使用 UNLINK 命令安全地删除大 key,该命令能够以非阻塞的方式,逐步地清理传入的 key。
Redis UNLINK 命令类似 DEL 命令,表示删除指定的 key。如果指定 key 不存在,命令会对此忽略。UNLINK 命令不同于 DEL 命令之处在于,它是异步执行的,因此不会阻塞。UNLINK 命令是非阻塞删除,非阻塞删除简言之,就是将删除操作放到另外一个线程去处理。
当 Redis 版本小于 4.0 时,避免使用阻塞式命令 KEYS。而是建议通过 SCAN 命令执行增量迭代扫描 key,然后判断进行删除。
Redis Scan 命令用于迭代数据库中的数据库键。SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
当 vaule 是 string 时,比较难拆分。可使用序列化、压缩算法将 key 的大小控制在合理范围内,但是序列化和反序列化都会带来更多时间上的消耗;
当 value 是 string,且压缩之后仍然是大 key,则需要进行拆分。一个大 key 分为不同的部分,记录每个部分的 key,使用 multiget 等操作实现事务读取;
当 value 是 list/set 等集合类型时,根据预估的数据规模来进行分片。不同的元素计算后分到不同的片。