首页 > 数据库 >Redis BigKey与MoreKey优化详解

Redis BigKey与MoreKey优化详解

来源:互联网 2026-07-10 08:41:01

1.MoreKey 先聊一个很多新手容易踩的坑——MoreKey问题。简单说,就是当Redis里key的数量特别多的时候,你顺手敲了个KEYS *想看看都有啥,结果Redis直接卡死。为什么?因为Redis是单线程的,执行KEYS这种O(n)的遍历算法时,它会一把抓起所有key,一次性吐给你。如果实

1.MoreKey

先聊一个很多新手容易踩的坑——MoreKey问题。简单说,就是当Redis里key的数量特别多的时候,你顺手敲了个KEYS *想看看都有啥,结果Redis直接卡死。为什么?因为Redis是单线程的,执行KEYS这种O(n)的遍历算法时,它会一把抓起所有key,一次性吐给你。如果实例里有千万级甚至更多的key,这一把操作就能让Redis堵上好一会儿,其他所有读写指令都得排队等着,严重的还会引发超时、缓存雪崩,甚至数据库宕机。

所以生产环境里,KEYS *这个指令基本就是定时冲击波,千万别碰。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

那怎么避免误操作?Redis配置文件里可以直接把危险命令禁掉。在redis.conf的SECURITY配置项里,把KEYSFLUSHDBFLUSHALL这些命令rename掉,或者直接禁用,省得手滑。

Redis BigKey与MoreKey优化详解

真要遍历所有key怎么办?官方给出了SCAN命令。SCAN是个基于游标的迭代器,每次调用只返回一小批key和一个新游标,你拿着新游标继续迭代,直到游标变成0才算结束。这样就不会阻塞Redis,而且还能自己控制每次返回多少数据,性能影响小得多。

Redis BigKey与MoreKey优化详解

SCAN命令的核心用法:每次返回一个包含两个元素的数组——第一个是新游标,第二个是这次迭代到的所有key。如果新游标返回0,说明迭代结束了。

有个细节你可能没注意到:SCAN的遍历顺序不是从数组第0位走到末尾,而是用了“高位进位加法”来遍历。这样设计是为了配合字典在扩容和缩容时,避免槽位重复或遗漏。挺巧妙的,感兴趣可以深挖一下。

Redis BigKey与MoreKey优化详解

总之,日常开发中只要需要遍历大量key,记得用SCAN系列命令,别再用KEYS *给自己挖坑了。

2.BigKey

BigKey,顾名思义就是那些value特别大的键。注意,不是key名字长,而是它存的值巨大。可能是单个字符串特别大,也可能是list、set、hash、zset这类集合里元素数量惊人。Redis是单线程,操作BigKey的时候会像大货车堵在单车道——其他所有指令都得等它办完事才能走,性能直接崩。

多大才算BigKey? 业界一般有个经验值:

  • string类型,value超过10KB就算bigkey(最大值虽然允许到512MB,但别真塞那么大)
  • list、hash、set、zset这些,元素数量超过5000个就算bigkey
  • 具体上限:list最多2^32-1个元素(约42亿),hash和set也是这个量级,但正常业务根本用不到那么多,超过5000就得小心了

3.Bigkey危害、产生与发现

3.1 危害

  • 内存不均:集群模式下,某个节点因为存了大key,内存飙升,其他节点却空闲,负载失衡。
  • 请求阻塞:操作大key耗时太长,阻塞后续请求,造成连锁反应。
  • 网络拥塞:大key的传输数据量大,占带宽,影响其他服务。
  • 删除阻塞:删除BigKey特别是带着过期时间的,也可能阻塞Redis,得小心处理。

3.2 产生原因

常见场景:

  • 社交类应用,明星的粉丝列表,随着热点事件粉丝数暴增,一个key存几百万粉丝ID。
  • 汇总统计,比如某个报表的日、月、年累计数据,全塞进一个key里。

3.3 如何发现

最简单的方式:用redis-cli --bigkeys命令。它会扫描整个实例,给出每种数据结构里最大key的Top 1,同时列出每种数据类型的键总数和平均大小。

redis-cli --bigkeys -a 111111
redis-cli -h 127.0.0.1 -p 6379 -a 111111 --bigkeys
# 加上 -i 参数,每100条scan指令休眠0.1秒,避免ops飙升
redis-cli -h 127.0.0.1 -p 7001 --bigkeys -i 0.1

--bigkeys有个局限:它只报告最大的那个,如果你想知道所有超过10KB的key,它就帮不上忙了。这时候得用memory usage key命令,手动计算每个key占用的字节数。

memory usage key

4. 大key如何删除

删除大key不能胡来,直接del可能会卡死。不同数据类型有各自的渐进式删除方案:

  • String:通常直接del就行,如果实在太大了,用unlink key异步删除,不阻塞。
  • hash:用hscan每次取少量field,再用hdel逐个删除。
  • list:用ltrim逐步裁剪,直到全部清空。
  • set:用sscan每次取少量元素,再用srem逐个删除。
  • zset:用zscan每次取少量元素,再用zremrangebyrank按排名范围删除。

5.BigKey生产调优

在生产环境里,预防比事后补救更重要。几个常用策略:

  • 分割BigKey:把一个超大的hash拆成多个小hash,用分片key来管理。
  • 清理BigKey:如果不需要了,用UNLINK异步删除,避免阻塞。Redis 4.0以上版本都支持。
  • 监控内存:设置内存使用率告警,提前发现大key苗头。
  • 定期清理:对于会持续膨胀的key(比如日志、粉丝列表),定期清理过期或无效数据。
  • 选对数据结构:别图省事把所有东西塞进一个大list或hash里,该拆就拆。

还有Redis配置文件里关于lazy freeing的优化,看这张图:

Redis BigKey与MoreKey优化详解

阻塞和非阻塞删除命令的区别:

Redis BigKey与MoreKey优化详解

配置文件里相关的几个参数:

lazyfree-lazy-eviction:内存达到阈值时,淘汰键是否异步
lazyfree-lazy-expire:过期key删除是否异步
lazyfree-lazy-server-del:服务端主动del是否异步
replica-lazy-flush:从节点全量同步清空db是否异步
lazyfree-lazy-user-del:让del默认变成unlink行为

注意:操作大key时,尽量别在主节点上搞大规模的扫描或删除,最好在从节点上做,或者挑业务低峰期搞,避免影响线上。

6.总结

MoreKey和BigKey是Redis日常运维里最容易踩的坑,但也是最好解决的——只要养成好习惯,该用SCAN不用KEYS,该拆分就拆分,该异步就异步,Redis就能稳稳地跑。希望这些经验对你有帮助。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。