一. 什么是大key?
通常指数据内存使用量非常大的数据,比如set里放了相当多的数据
ps:我们用set存储了单个用户的文章点赞数据,有个小伙伴天天无聊就在那给文章点赞,点了几百万,那set里就有了几百万数据,这个可能就是一个大key
二. 数据层面的解释--避免大key操作
业务方应尽量避免进行大key操作,如 hgetall 一次获取非常大的hash数据,用 hmset 一次设置非常多的value,用 lrange 一次取一个非常大的 list 或非常多的元素,如果客户端需要用到这些操作对应的API,一次操作的返回结果大小必须是在合理可控的范围内,防止导致节点通信超时、网络堵塞等严重后果。
备注:大key操作通常可见于集群慢日志,同期会伴随缓存调用的高延迟,甚至节点完全阻塞造成的不可用。
参考:根据测试结果,value在超过1KB后性能开始下降,超过10KB后性能下降明显,出现拐点
。
三. 结构层面的大key问题解释
- 1.资源使用不均(该大key可能会使用该实例相当多的内存,浪费相当大的Cpu,)
- 2.带宽使用极大(比如假如我们有个功能展示上面例子中点赞的所有文章,一下查出来全部,肯定会使用非常大的带宽)
- 3.影响该实例其他key的操作(基于redis的单线程处理机制,大家都在排队,前面的慢,自然影响其他数据的操作)
四. 大key如何发现?
- bigkeys命令
bigkeys命令以遍历的方式
分析Redis实例中的所有Key,并返回整体统计信息与每个数据类型中Top1的大Key
- redis-rdb-tools
使用redis-rdb-tools离线分析
工具来扫描RDB持久化文件,虽然实时性略
差,但是完全离线对性能无影响
。 - Redis 4.0 以后的版本:支持 了 memory 命令查看 key 的大小
预估值,不太准确(采用的是多次抽样分析,预估全部数据的量)
五. 如何解决大key问题?
- 1.数据结构拆分,比如我们这里有个活动数据,活动有活动商品数据,这俩就进行了拆分,并没有放一起
- 2.数据分片,比如后面加序号,进行多实例的拆分
六. 大key的删除问题
6.1 Redis 4.0以前大key删除
4.0 以前 string,list,set,hash 不同数据类型的大 key,删除方式有所不同。一般有两种情况:del 命令删除单个很大的 key 和 del 批量删除 大 key。直接 del 命令粗暴的删大 key 容易造成 redis 线程阻塞。4.0 以前要优雅的删除就是针对不同的类型 写脚本,拆分链表,hash 表,分批删除。
6.2 Redis 4.0 以后优雅的删除大 key
- 主动删除
UNLINK xxxkey
unlink 命令是 del 的异步版本,由 Lazyfree 机制实现。Lazyfree 机制的原理是在删除的时候只进行逻辑删除,把 key 释放操作放在 bio (Background I/O)单独的子线程
中惰性处理,减少删除大 key 对 redis 主线程的阻塞,有效地避免因删除大key带来的性能问题。unlink 即使在批量删除 大 key 时,也不会对阻塞造成阻塞。 - 被动删除 被动删除是指 Redis 自身的 key 清除策略,一个 大 key 过期或者被淘汰时,如何被清除,会不会导致阻塞?4.0 以前自动清除是有可能阻塞主线程的。
4.0 以后的版本,被动删除策略是可选的配置参数,允许以 Lazyfree 的方式清除。但是参数默认是关闭的
,可配置如下参数开启。
lazyfree-lazy-expire on # 过期惰性删除
lazyfree-lazy-eviction on # 超过最大内存惰性删除
lazyfree-lazy-server-del on # 服务端被动惰性删除
评论 (0)