• 缓存热key问题


    热key问题是指:突然有几十万甚至更大的请求去访问redis上的某个特定key。这样会造成流量过于集中,达到Redis单实例瓶颈(一般是10W QPS级别),或者物理网卡上限,从而导致这台redis的服务器Hold不住,直到缓存服务器垮掉。

    那我们怎么发现热key?怎么处理热key?

    1 监控热key
    1、按业务场景,预估热点key

    秒杀业务中, 秒杀的商品(抢茅台)、券(大额满减券-满300-199)、权益资源(霸王餐、腾讯视频VIP)都是热点key,这种需要对业务的预估和理解,缺点是预估往往有偏差,总会有想不到的地方成为热点,或者突发的状况。

    2、客户端收集

    这个方式就是在操作redis之前,加入一行代码进行数据统计。那么这个数据统计的方式有很多种,也可以是给外部的通讯系统发送一个通知信息。缺点就是对客户端代码造成入侵。

    3、代理层收集

    缓存层之前加一层proxy代理层(比如Twemproxy),代理层做缓存统一入口。优点:对代码无入侵;缺点:架构复杂,缓存架构需要代理层设计。

    4、redis监控命令

    redis本身提供了相应的监控命令

    monitor命令:可以实时抓取出redis服务器接收到的命令,然后写代码统计出热key。

    缺点:该命令在高并发的条件下,不仅有内存暴增的隐患,还会降低redis的性能。

    hotkeys命令:redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可,操作方便。缺点:该参数在执行的时候,如果key比较多,执行起来比较慢。

    这种可以提供工具功能,分析热key后通知到业务系统。没有研究过,大家感兴趣可以分享下实现思路。这种工具功能一般由组件部门提供工具能力,例如引入Redis工具maven依赖,实现热点key的业务处理方法。

    5、网络抓包分析

    Redis客户端使用TCP协议与服务端进行交互,通信协议采用的是RESP。自己写程序监听端口,按照RESP协议规则解析数据,进行分析。缺点就是开发成本高,维护困难,有丢包可能性。

    6、大数据流式计算技术实时统计

    业务系统访问Redis打印日志,然后把日志采集到大数据平台,然后基于大数据领域的流式计算技术来进行实时数据访问次数的统计,比如storm、spark streaming或flink,这些技术都是可以的。例如1秒之内,某条数据突然访问次数超过了1000(可配置),就把这条数据判定为热点数据,通知到业务系统。

      2 处理热点key

    1、使用本地缓存(二级缓存)。

    在你发现热key以后,把热key加载到系统的JVM中,针对这种热key请求,会直接从jvm中取,而不会走到redis层。

    应用集群中单台机器配置可能是4C8G,留给本地缓存的空间是很少的,所以本地不适合存放大量数据,只存放热点缓存数据。

    本地缓存需要设置过期时间,避免OOM,可以使用Ehcache缓存几分钟。JVM热点缓存内存占用或热点Key数量达到一定阈值后,需要考虑及时释放内存占用,避免热点缓存评估不合理导致大量数据存放到JVM,要预留内存存放最热点的数据。

    使用本地缓存的方案,需要考虑数据库数据变化后,如何快速清理本地缓存。本地缓存加载和缓存清理,都可以结合Zookeeper去实现。

    具体要结合系统业务特性,合理选择实现方案。

    2、备份热key

    网上提供的思路备份热点key到多组Redis节点,就是请求的时候缓存key加个随机数让其请求到不同的Redis节点,这种方案,可能要考虑以下几点问题:

    1.Redis机器实例少,key+随机数的方式可能分散不均,路由到同一组Redis分片概率大,可以考虑指定Redis分片节点。

    指定分片节点使用Redis分片的一致性hash算法实现,根据分片shardname请求到对应节点。

    Redis分片的一致性hash算法是将每个分片根据hash规则计算hash值,均匀分布在hash环上,一个redis物理节点默认划分为160个虚拟节点(索引:0~159),每个节点的默认权重为1,redis一致性hash算法将对分片名称、权重和虚拟节点组合进行hash值计算,分片名称和权重之间以*号连接,构造hash环时将所有redis的分片节点进行hash值计算,并构造TreeMap有序存储分片的hash值和分片实例,在根据缓存key路由redis节点时,先计算缓存key的hash值,然后从redis分片的TreeMap中获取hash值大于等于缓存key的hash值的第一个节点作为该缓存key的路由节点。所以当缓存key计算出的hash值和redis节点计算出的hash值一致时,该缓存就必然路由至执行的redis节点。

    例如使用key路由, key的生成规则=Key+*+节点权重+虚拟节点索引,即节点名称如果是shardName,权重是1,虚拟节点索引为0时(虚拟节点索引可以为0~159中的任意一个整数),该节点对应的缓存key就为shardName*10。

    2.缓存一致性问题,如果存储层数据变化,如何清理存放在多组分片上的缓存,保证缓存和数据库的一致性。思路是确定热点key的时候,就明确下需要路由的Redis节点分片列表,如果存储层数据变化的时候,把热点key对应的所有节点都清理一遍。

    3、熔断限流保护

    熔断限流也是极端情况下需要考虑的事情。面对高并发可以加一个对热点数据访问的限流熔断保护措施,限定缓存集群每秒最多的请求次数。

    案例:商品中心架构演进分享的时候提到了关于商品数据热点的问题,当主站有秒杀活动时,秒杀商品调用量会达到数十万次,由于key相同会落到统一组redis上,导致单组redis访问压力过大,影响整个集群。

    商品中心的解决方案:

    1.前端核心系统本地缓存N分钟,减少穿透到商品中心

    2.采用jvm缓存+redis+hbase存储架构,减少穿透至redis。

    商品中心的案例是按业务场景预估热点key,处理热点key使用二级缓存的方案。这种不能解决冷商品突然变成热商品导致的热key问题,他们最后提供的思路是让组件部门开发根据发现热key,通知业务系统,再由业务系统存放到本地缓存,思路都差不多,解决热key问题,还是要根据业务场景评估最合理的方案。

  • 相关阅读:
    Matlab图像处理
    asp.net+sqlserver团购网站c#
    数字孪生赋能实景三维中国建设分论坛成功举办
    Python实现PU口袋活动更新提醒
    Apache PLC4X 副总裁宣布个人停止对项目提供免费支持;Linux 5.17 增加对中国 Soc 的支持;IPython 8.0 发布 | 开源日报
    AttributeError: module ‘torch._C‘ has no attribute ‘_cuda_setDevice‘
    华为云确定性运维,为政务云平台稳定可靠运行保驾护航
    五个维度着手MySQL的优化,我和面试官都聊嗨了
    js将list数据按日期分组
    【Java项目】如何设计一个用户签到系统?并且这个签到系统支持7天,14天等不同天数的连续签到功能?
  • 原文地址:https://blog.csdn.net/weixin_69413377/article/details/126129096