【面试官】如何解决Redis中出现的大key?
一、什么是大key?
首先大key不是key很大而是key对应的value值很大,一般而言如果String类型值大于10KB,Hash,Set,Zset,List类型的元素的个数大于5000个都可以称之为大key.
二、大key的危害
- 客户端超时等待:由于Redis执行命令是单线程处理,然后在操作大key时会比较耗时,那么就会阻塞Redis,从客户端这一视角来看就是很久很久都没有响应
- 引发网络阻塞:每次获取大key产生的流量较大,如果一个key的大小是1MB,每秒访问量为1000,那么每秒会产生1000MB的流量这对于普通千兆网卡是灾难的
- 阻塞工作线程:如果使用del删除大key,会阻塞工作线程这样就没有办法处理后续的命令
- 内存分布不均匀:集群模型在slot分片均匀的情况下,会出现数据和查询倾斜情况,部分有大key的Redis节点占用内存多,QPS比较大
三、定位大key
1、redi-cli --bigkeys
使用时注意事项:最好在从节点上执行该命令或者在Redis实例业务压力的低峰阶段进行扫描查询,因为key很多时会很慢
不足之处
- 这个方法只能返回每种类型中最大的那个bigkey,无法得到大小排到前N位的bigkey
- 对于集合类型来说,这个方法只统计集合元素的多少,而不是实际占用的内存量。因为一个集合中元素个数多,并不一定占用内存就多
2.使用SCAN命令查找大key
- 使用SCAN命令对数据库进行扫描。然后用TYPE命令获取返回的每一个key的类型
- 对于String类型,可以直接使用STRLEN命令获取字符串长度,也就是占用的内存空间字节数
- 对于集合类型来说可以使用MEMORY USAGE命令,查询有关键值对占用的内存空间 基于redis的keys、scan删除ttl为-1的key
3.使用RdbTools
使用第三方开源工具,可以解析Redis快照,找到其中的大key
四、删除大key
1.分批次删除
使用SCAN扫描key,比如删除Hash,先取100字段删除删除再取
在Redis4.0版本开始,可以采用异步删除法用unlink命令代替del删除
这样Redis会将这个key放入到一个异步线程中进行删除,这样不会阻塞主线程
前面两种都是主动删除,这一种是通过配置参数,当认为需要删除的时候就删除了
- lazyfree-lazy-eviction:表示当 Redis 运行内存超过 maxmeory 时,是否开启 lazy free 机制删除;
- azyfree-lazy-expire:表示设置了过期时间的键值,当过期之后是否开启 lazy free 机制删除;
- lazyfree-lazy-server-del:有些指令在处理已存在的键时,会带有一个隐式的 del 键的操作,比如 rename 命令,当目标键已存在,Redis 会先删除目标键,如果这些目标键是一个 big key,就会造成阻塞删除的问题,此配置表示在这种场景中是否开启 lazy free 机制删除;
- slave-lazy-flush:针对 slave (从节点) 进行全量数据同步,slave 在加载 master 的 RDB 文件前,会运行 flushall 来清理自己的数据,它表示此时是否开启 lazy free 机制删除。
建议开启其中的 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-server-del 等配置,这样就可以有效的提高主线程的执行效率
五、如何避免大key
1.对大key进行拆分
将一个Big Key拆分为多个key-value这样的小Key,并确保每个key的成员数量或者大小在合理范围内,然后再进行存储,通过get不同的key或者使用mget批量获取。
2.对大key进行清理
对Redis中的大Key进行清理,从Redis中删除此类数据。Redis自4.0起提供了UNLINK命令,该命令能够以非阻塞的方式缓慢逐步的清理传入的Key,通过UNLINK,你可以安全的删除大Key甚至特大Key
通过监控系统并设置合理的Redis内存报警阈值来提醒我们此时可能有大Key正在产生,如:Redis内存使用率超过70%,Redis内存1小时内增长率超过20%等。
使用序列化、压缩算法将key的大小控制在合理范围内,但是需要注意序列化、反序列化都会带来一定的消耗。如果压缩后,value还是很大,那么可以进一步对key进行拆分。
相关文章
- Redis缓冲池:更高效的数据处理(redis缓冲池)
- 飞速储存:Redis 内存数据库(redis内存数据库)
- 实用教程:利用 SSH 整合 Redis 高效操作指南(ssh整合redis教程)
- 如何使用SSM框架整合Redis提高系统性能?(ssm框架整合redis)
- Redis如何优化存储空间(redis 优化存储空间)
- 如何在Redis中开启持久化配置(打开redis持久化配置)
- 如何使用Redis给存储磁盘添加更大容量(怎么添加redis磁盘)
- 缓存如何快速搭建Redis缓存系统(怎么实现一个redis)
- 如何利用Redis让微博更有效率(微博如何使用的redis)
- 从Redis返回值强制转换(强转redis返回值)
- 使用Redis记住你的密码(记住密码 redis)
- 结合联通Redis极大提升性能(联通redis怎么样)
- 深入浅出Redis缓存原理(简述redis原理)
- 使用Redis轻松查询存储的数据(查询redis存的数据)
- 搭建Windows下Redis集群实现高可用性(win搭建redis集群)
- 如何在本地搭建Redis环境(如何连redis)
- Redis高效存储的利器(关于redis的说法)
- 如何掌握Redis即时查看缓存的技巧(怎么查看缓存redis)
- 监测Redis队列一种有效的方法(如何监听redis的队列)
- 如何恢复Redis数据清晰的解决方案(如何恢复redis数据)
- 学会使用Redis客户端,操作更加高效(如何使用redis客户端)
- 如何让Redis配置落地生效(如何使redis配置生效)
- 更新Redis更新之法以优雅勇敢挑战(如何优雅勇redis)
- MySQL vs Redis 比较两者的非优点(以下不是redis优点)
- Redis 面试指南49 道关键要点(redis面试49题)
- 重启后 Redis 缓存消失记(redis 重启缓存没了)
- 如何设置Redis暂态信息存储(redis配置不持久化)
- 调整调整Redis连接数上限最佳实践(redis连接数大小如何)
- Redis如何有效能处理过期缓存(redis 过期效率)
- Redis缓存唯一且无可取代的解决方案(redis缓存的唯一性)