Redis 大 key 要如何处理?

面试官:Redis 大 key 要如何处理?

一般来说,下面两种情况被称为大key

  • String类型的值大于10KB
  • Hash、List、Set、ZSet类型的元素个数超过5000个

大Key会造成以下问题:

  • 客户端超时阻塞:由于Redis执行命令是单线程处理,然后在操作大key时会比较耗时,阻塞其他命令的执行
  • 引发网络阻塞:每次获取大key产生的网络流量较大,如果一个key的大小是1MB,每次访问量是1000,那么每秒会产生1000MB的流量,这对普通千兆网卡的服务器是灾难性的
  • 阻塞工作线程:如果使用del删除大key时,会阻塞工作线程,这样没法处理后续命令
  • 内存分布不均,集群模型在slot分片均匀情况下,会出现数据和查询倾斜情况,部分有大key的Redis节点占用内存多,QPS也会比较大。

怎么找到大key呢?

  1. 通过 redis-cli --bigkeys 命令查找大key:最好在从节点或者业务低峰阶段进行扫描查询,以免影响实例正常运行该方法也存在不足,只能返回每种类型中最大的那个Key,且对于集合类型来说只统计集合元素个数多少而非实际占用的内存。

redis-cli -h 127.0.0.1 -p6379 -a "password" -- bigkeys
  1. 使用 scan 命令查找大Key使用scan命令对数据库扫描,然后用type命令获取返回的每一个key的类型。对于String类型,可以直接使用strlen命令获取字符串的长度,也就是占用的空间字节数对于集合类型来说,有两种方法可以获得它占用的内存大小:
  2. 如果能够预先从业务层知道集合元素的平均大小,那么可以使用下面的命令获取集合元素的个数,然后乘以集合元素的平均大小,这样就可获得集合占用的内存大小了。List类型:`LLEN`;Hash 类型:`HLEN` ;Set 类型:`SCARD` ;Set 类型:`SCARD`。
  3. 如果不能提前知道写入集合元素大小,可以使用 memory usage命令,查询一个键值对占用的内存空间。
  4. 使用RdbTools工具查找大keyRdbTools第三方开源工具可以用来解析Redis的RDB文件,找到其中的大key。比如下面这条命令,将大于10Kb的Key输出到一个表格文件
rdb dump.rdb -c memory --bytes 10240 -f redis.csv

如何删除大Key呢?

删除操作的本质是要释放键值对占用的内存空间。释放内存后为了更加高效的管理内存空间,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配,这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序

所以如果一下子释放了大量内存,空闲地址块链表操作时间就会增加,相应的就会造成redis主线程的阻塞。主线程阻塞,其他所有请求都可能会超时,超时越来越多,会造成redis连接耗尽,产生各种异常。

因此删除一个大key,要小心。

  1. 分批次删除。
  2. 对于删除大Hash,使用hscan命令,每次获取100个字段,再用hdel命令,每次删除1个字段。
  3. 对于删除大List,通过ltrim命令,每次删除少量元素
  4. 对于删除大 Set,使用 sscan 命令,每次扫描集合中 100 个元素,再用 srem 命令每次删除一个键。
  5. 对于删除大 ZSet,使用 zremrangebyrank 命令,每次删除 top 100个元素。
  6. 异步删除
  7. Redis4.0开始,可以采用异步删除法,用unlink命令代替del来删除。这样Redis会将这个key放入到一个异步线层中进程删除,不会阻塞主线程。
重生之八股仙帝 文章被收录于专栏

曾有一千古奇人,精修八股文,成遁世之高人,彻天彻地畅游天地间。 今人皆忙忙,急于求成,岂不知八股乃道门口径,背负天人,若经熟读背诵,更能开拓智慧之门,探寻未来之路。 天下繁华,不尽长夜,唯有读书为伴,熟读八股文更是攀登高峰之路。磨砺文字,升腾智慧,唯有勤玉立志,始可破天荒,登临九重不竭之巅! 吾辈修炼之路,虽曲折荆棘,但信念不曾磨灭,唯有铭记八股精髓,方能指引灵魂归宿,成就一生辉煌!

全部评论
m
1
送花
回复
分享
发布于 2023-08-30 19:53 四川
感谢🙏
点赞
送花
回复
分享
发布于 2023-08-30 18:45 四川
滴滴
校招火热招聘中
官网直投
你好老哥,那大key不可避免,如何进行优化呢
点赞
送花
回复
分享
发布于 2023-08-31 09:23 天津
我们这边校招需要牛人 ,https://www.nowcoder.com/share/jump/1359800161693547815197
点赞
送花
回复
分享
发布于 2023-09-01 14:58 浙江

相关推荐

时间:约一小时1. 无自我介绍2. 项目相关(15 min)    1. 整体介绍下,需求、背景是什么?    2. 你主要负责哪一块?    3. 算法是调用接口还是自己做?    4. 做项目中遇到的困难?    5. 6.824 介绍下?3. 八股    1. 介绍负载均衡算法?    2. 数据包到网卡后发生什么?    3. 你觉得负载均衡服务器瓶颈在哪里?    4. 零拷贝具体技术?    5. 进程和线程区别?    6. 用线程的优势?    7. 线程的问题?    8. Java 中网络有问题会不会崩(具体问的忘了)?    9. 为什么项目里要用单线程,会不会占不满 CPU?    10. Java 中内存溢出一般怎么处理?    11. TCP 和 UDP 区别?    12. 介绍 TCP 可靠传输?    13. TCP 怎么确定要发送的数据量?    14. TCP 报文最长多少(MTU)?    15. 怎么确定的 1500?    16. 发送端是根据什么来控制发送速率的?    17. 讲一下拥塞避免算法?    18. 拥塞避免算法有什么问题?    19. 如果拥塞发生后没有惩罚措施会发生什么?    20. syn flood 攻击?    21. 如何解决 syn 攻击?    22. syn-cookie 具体怎么做?    23. Python、C、Java 各自的区别和用途?    24. NIO 是什么?    25. 单线程阻塞情况有遇到过吗?    26. 介绍下路由表?    27. 设计路由表?    28. 介绍下 Java 里 HashMap?    29. 16 是节点数量嘛?    30. 哈希冲突怎么解决的?4. 算法:面试官说不会用腾讯会议出题,就没问了,换成口述设计路由表
点赞 评论 收藏
转发
11 156 评论
分享
牛客网
牛客企业服务