解决了Redis大key问题,同事都夸他牛皮一直报警,结果是某个叫Redis的服务异常了。放下手中的工作,小黑打开电脑查看了一下,终于发现Redis出了个大key问题。想了想还是解决不了,明天去公司解决吧,先继续看电视吧哈哈哈。什么是大钥匙?肯定有很多朋友想知道redis的key能有多大?这里有一个误区。所谓大键问题就是某个键的值比较大,所以本质上是一个大值问题。这样key往往是程序自己设置的,value往往不受程序控制,所以value可能会很大。想象一个场景:在一个在线音乐应用中,一个歌曲列表中有很多用户的收藏。如果有这样一个数据结构:歌曲列表和用户的映射关系存储在redis中。redis的key是歌单id,长度可控,redis的值很小。redis的值是一个列表。该列表包含用户ID。可能有很多用户,导致列表的长度不可控。定义不同。例如,当值为String类型时,大小超过10KB。当value为ZSET、Hash、List、Set等集合类型时,其成员数超过1w。上面的定义不是绝对的,主要是根据value的成员个数和字节数来决定的,业务也可以根据自己的场景来确定标准。我们都知道大键的影响。Redis的一个典型特点是核心工作线程是单线程。单线程中请求任务的处理是串行的,前端无法完成,后面也无法处理,这也导致了分布式架构中内存数据和CPU的不平衡。执行large-key命令的客户端本身耗时明显增加,甚至超时执行与large-key相关的读取或删除操作时,会严重占用带宽和CPU,影响其他客户端的存储。Shard数据不平衡,CPU占用率也不平衡。大键有时是热键,读操作频繁,影响会很大。删除大键时,低版本redis可能会阻塞线程。这样一来,大key的影响还是很明显的,最典型的就是阻塞线程,并发量下降,导致客户端超时,服务端的业务成功率下降。BigKeys是如何生成的BigKeys的产生往往是由于业务方设计不合理,没有预见到Vaule的动态增长:数据一直塞进Value中,没有删除机制,迟早数据会爆炸。如何用小key查找大key增加memory&flow&timeout等指标监控由于大key的值很大,读的时候可能会阻塞线程,所以Redis整体的QPS会下降,客户端超时会增加,网络带宽会减少Up,配置这些告警可以让我们发现大key的存在。bigkeys命令使用bigkeys命令遍历分析Redis实例中的所有Key,返回总体统计和每种数据类型中的Top1大Key。redis-rdb-tools使用redis-rdb-tools离线分析工具扫描RDB持久化文件,虽然实时性稍差,但是完全离线对性能没有影响。redis-rdb-tools是Python编写的一款分析Redisrdb快照文件的工具。它可以将rdb快照文件生成为json文件或者生成报告来分析Redis的使用细节。集成可视化工具基于一些公有云或者公司内部架构的Redis一般都有可视化的页面和分析工具来帮助我们定位bigkey。当然,页面的底层也可能是根据bigkeys或者rdb文件离线分析的结果。如何解决bigkey问题,根据bigkey的实际使用情况分为两种情况:可删除和不可删除。删除bigkey如果发现有些bigkey不是hotkey,在DB中可以查询和使用,可以在Redis中删除:当Redis版本大于4.0时,可以使用UNLINK命令安全删除bigkey.以阻塞的方式,逐级清理传入的Key。RedisUNLINK命令类似于DEL命令,意思是删除指定的key。如果指定的键不存在,该命令将被忽略。UNLINK命令与DEL命令的不同之处在于它是异步执行的,因此不会阻塞。UNLINK命令是非阻塞删除。简而言之,非阻塞删除就是把删除操作放到另一个线程上去处理。当Redis版本低于4.0时,避免使用阻塞命令KEYS。相反,建议使用SCAN命令对键进行增量迭代扫描,然后确定删除它们。RedisScan命令用于遍历数据库中的数据库键。SCAN命令是一个基于游标的迭代器。每次调用后,都会将一个新的游标返回给用户。用户需要在下一次迭代中使用这个新游标作为SCAN命令的游标参数,以继续之前的迭代过程。.压缩和拆分键当值是字符串时,很难拆分。使用序列化和压缩算法将key的大小控制在合理范围内,但是序列化和反序列化会带来更多的时间消耗。当value是一个字符串,压缩后还是一个大的key时,就需要进行拆分。将一个大的key分成不同的部分,记录每个部分的key,通过multiget等操作实现事务性读取。当value为list/set等集合类型时,根据预估的数据大小进行分片,计算后将不同的元素分成不同的分片。总结一下Redis的bigkey问题,在面试或者工作中很常见,非常值得好好了解一下。祝各位老铁半夜不闹钟,上网无BUG!
