1.热key引发的巨大风险
2.以往热key问题怎么解决
3.热key进内存后的优势
4.热key探测关键指标
5.热key探测框架JdHotkey的简介
6.热key探测框架JdHotkey的组成
7.热key探测框架JdHotkey的工作流程
8.热key探测框架JdHotkey的性能表现
9.关于热key探测框架JdHotkey的一些问题
10.JdHotkey的安装部署与使用
1.热key引发的巨大风险
(1)数据层的风险
(2)服务层的风险
在拥有大量并发用户的系统中,热key一直以来都是一个不可避免的问题。某商品突然成爆款、海量用户突然涌入某店铺、秒杀瞬间的大量爬虫请求,这些突发的无法预知的热key都是系统潜在的巨大风险。风险是什么呢?主要是数据层,其次是服务层。
(1)数据层的风险
热key对数据层的冲击显而易见,譬如数据存放在Redis或者MySQL中。以Redis为例,那个未知的热数据会按照Hash规则存放在某个Redis分片上。
平时使用时都是从该分片获取它的数据,由于Redis高性能 + 集群模式,每秒假设该分片能支撑20万次读取,这足以支持大部分的日常使用了。
但是以京东为例的这些头部互联网公司,很容易出现某个爆品。爆品会瞬间引入每秒百万级的请求,当然流量多数会在几秒内就消失。但就是这短短的几秒热key,就会瞬间造成其所在Redis分片集群瘫痪。
原因很简单:Redis作为一个单线程的结构,所有的请求到来后都会去排队。当请求量远大于自身处理能力时,后面的请求就会陷入等待、超时。
由于该Redis分片完全被这个key的请求给打满,导致该分片上所有其他数据操作都无法继续提供服务。也就是热key不仅仅影响自己,还会影响和它合租的数据。很显然,在这个极短的时间窗口内,无法快速扩容10倍来支撑这个热点的。虽然Redis已经很优秀,但这种场景下,Redis却成为了最大的瓶颈。
(2)服务层的风险
热key对服务层的影响也不可小视。比如原本有1000台Tomcat,每台每秒能支撑1000QPS。假设数据层稳定、这样服务层每秒能承接100万个请求。
但是由于某个爆品的出现、或者由于大促优惠活动,突发大批机器人以远超正常用户的速度发起极其密集的请求,这些机器人轻易发出普通用户的百倍请求量,从而大幅挤占正常用户的资源。
原本能承接100万,现在来了150万,其中50万个是机器人请求。那么就导致了至少1/3的正常用户无法访问,带来较差的用户体验。
2.以往热key问题怎么解决
(1)Redis热key的解决方式
(2)刷子爬虫用户的解决方式
(3)限流的方式
下面分别以Redis的热key、刷子用户、限流等典型的场景来看。
(1)Redis热key的解决方式
这种场景的解决方式比较百花齐放,比较常见的有:
一.使用二级缓存
读取到Redis的key-value信息后,就直接写入到JVM缓存多一份。同时设置JVM缓存过期时间,设置淘汰策略譬如队列满时淘汰最先加入的。或者使用Guava Cache或Caffeine Cache进行单机本地缓存。但是这种做法普遍整体命中率偏低。
二.改写Redis源码加入热点探测功能
当Redis服务端发现有热key时就推送到JVM,但这种方法主要是不通用,而且有一定难度。
三.改写Jedis、Letture等Redis客户端的jar
通过本地计算来探测热点key,如果发现是热key那么就在本地缓存起来,然后通知集群内其他机器。
(2)刷子爬虫用户的解决方式
方式一:日常累积黑名单通过配置中心推送到JVM内存,但这种方法存在滞后无法实时感知的问题。
方式二:通过本地累加进行实时计算,单位时间内超过阈值的算刷子。如果服务器比较多,存在用户请求被分散,本地计算不能甄别刷子的问题。
方式三:引入其他组件如Redis,进行集中式累加计算,超过阈值的拉取到本地内存。问题就是需要频繁读写Redis,依旧存在Redis性能瓶颈问题。
(3)限流的方式
一.单机维度的限流多采用本地累加计数
二.集群维度的限流多采用第三方中间件如Sentinel
三.网关维度的限流多使用Nginx + Lua
(4)总结
综上,我们会发现虽然它们都可以归结到热key这个领域内。但是并没有一个统一的解决方案,我们更期望于有一个统一的框架,这个统一的框架能解决所有的需要对热key进行实时感知的场景。
最好是无论是什么key、是什么维度,只要拼接好这个字符串,把它交给框架去探测,并且设定好判定为热key的阈值(比如2秒该字符串出现20次)。那么在毫秒时间内,该热key就能进入到应用的JVM内存中,而且在整个服务集群内保持一致性,要么集群一起都有,要么一起没有。
3.热key进内存后的优势
热key问题归根到底就是如何找到热key,并将热key放到JVM内存的问题。
只要该key在内存里,我们就能极快地对它做逻辑,内存访问和Redis访问的速度不在一个量级。比如刷子用户,可以对其屏蔽、降级、限制访问速度。比如热接口,可以进行限流、返回默认值。比如Redis的热key,可以极大地提高访问速度。
以Redis访问key为例,可以很容易的计算出性能指标。譬如有1000台服务器,某key所在的Redis集群能支撑20万/s的访问。那么平均每台机器每秒大概能访问该key200次,超过的部分就会进入等待。由于Redis的瓶颈,将极大地限制Server的性能。
而如果该key是在本地内存中,读取一个内存中的值,每秒多少万次都是很正常的,不存在数据层的瓶颈。当然,如果通过增加Redis集群规模的形式,也能提升数据的访问上限。但问题是事先不知道热key在哪,而全量增加Redis的规模会大大增加成本。
4.热key探测关键指标
(1)实时性
(2)准确性
(3)集群一致性
(4)高性能
(1)实时性
这个很容易理解,key往往是突发性瞬间就热了,根本不允许手工去配置中心添加热key再推送到JVM。
热key大部分时间不可预知,来得非常迅速。可能某个商家上个活动,瞬间热key就出现了。如果短时间内没能进到内存,就有Redis集群被打爆的风险。
所以热key探测框架最重要的就是实时性,最好是某个key刚准备热,在1秒内它就已进到整个服务集群的内存里,1秒后就不会再去密集访问Redis了。
同理,对于刷子用户也一样,刚开始刷,1秒内就把它给禁掉了。
(2)准确性
这个很重要,也容易实现。累加数量,做到不误探,精准探测,保证探测出的热key是完全符合用户自己设定的阈值。
(3)集群一致性
这个比较重要,尤其是某些带删除key的场景,要能做到删key时整个集群内的该key都会删掉,以避免数据的错误。
(4)高性能
这个是核心之一,高性能带来的就是低成本。热key探测目的就是为了降低数据层负载,提升应用层性能,节省资源。理论上,在不影响实时性的情况下,要完成实时热key探测,所消耗的机器资源越少,那么经济价值就越大。
5.热key探测框架JdHotkey的简介
(1)热key探测框架JdHotkey的特点
(2)热key探测框架JdHotkey的使用
(3)热key探测框架JdHotkey的强实时性和高性能
(4)热key探测框架JdHotkey的架构设计
在经历了多次被突发海量请求压垮数据层服务的场景,并时刻面临大量的爬虫刷子机器人用户的请求,京东根据既有经验设计开发了一套通用轻量级热key探测框架——JdHotkey。
(1)热key探测框架JdHotkey的特点
热key探测框架JdHotkey具有:热数据探测、限流熔断、统计等多种功能。
它很轻量级,既不改Redis源码也不改Redis的客户端jar包。当然,它与Redis没一点关系,完全不依赖Redis,它是一个独立的系统。
(2)热key探测框架JdHotkey的使用
首先部署好JdHotkey热key探测系统,然后在应用的Server代码里引入jar,之后在应用的Server代码中就可以像使用一个本地HashMap来使用该系统。
热key探测框架JdHotkey自身会完成如下一切处理:包括对待测key的上报、对热key的推送、本地热key的缓存、过期淘汰策略。框架只会告知是不是热key,其他的逻辑则由我们自己去实现即可。
相关文章:
https://book.qq.com/book-search/%E5%90%8D%E4%BC%98%E9%A6%86%E7%BD%91%E3%80%9023Y4.com%E3%80%91?c21a
https://book.qq.com/book-search/%E6%B5%B7%E8%A7%92%E7%A4%BE%E5%8C%BA%E3%80%9023Y4.com%E3%80%91?c21b
https://book.qq.com/book-search/%E8%89%B3%E6%AF%8D%E7%BD%91%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c21c
https://book.qq.com/book-search/%E6%9E%9C%E5%86%BB%E4%BC%A0%E5%AA%92%E3%80%9023Y4.com%E3%80%91?c21d
https://book.qq.com/book-search/%E6%9E%9C%E5%86%BB%E4%BC%A0%E5%AA%92%E8%BF%9B23Y4.com%E7%9C%8B?c21e
https://book.qq.com/book-search/%E6%80%A7%E5%B7%B4%E5%85%8B%E8%BF%9B%E3%80%9023Y4.com%E3%80%91?c21f
https://book.qq.com/book-search/%E7%88%B1%E5%A8%81%E5%A5%B6%E7%BD%91%E3%80%9023Y4.com%E3%80%91?c21g
https://book.qq.com/book-search/%E7%A6%81%E6%BC%AB%E5%A4%A9%E5%A0%82%E3%80%9023Y4.com%E3%80%91?c21e
https://book.qq.com/book-search/%E6%92%B8%E6%92%B8%E7%A4%BE%E7%BD%91%E3%80%9023Y4.com%E3%80%91?a21e
https://book.qq.com/book-search/%E6%8A%96%E9%98%B4%E4%B8%8B%E8%BD%BD%E3%80%8A23Y4.com%E3%80%8B?b21e
https://book.qq.com/book-search/%E6%8A%96%E9%98%B4%E7%BD%91%E7%AB%99%E3%80%9023Y4.com%E3%80%91?c21e
(3)热key探测框架JdHotkey的强实时性和高性能
热key探测框架JdHotkey有很强的实时性。默认下,500ms即可探测出待测key是否热key,是就会进到JVM内存中。当然,JdHotkey框架也提供了更快频率的设置方式。通常在非极端场景建议保持默认值即可,更高的频率会带来更大的资源消耗。
热key探测框架JdHotkey还有着强悍的性能表现。一台8核8G机器,在承担该框架热key探测计算任务时,每秒可处理来自数千台服务器发来的高达16万个的待测key。8核单机吞吐量16万,16核机器每秒可达30万+探测量,当然前提是CPU很稳定。
高性能代表了低成本,所以可以仅仅采用10台16核机器,即可完成每秒近300万次的key探测任务。一旦找到了热key,那该数据的访问耗时就和Redis不在一个数量级了。
(4)热key探测框架JdHotkey的架构设计
热key探测框架JdHotkey的架构图如下所示:
6.热key探测框架JdHotkey的组成
(1)etcd集群
(2)Client端jar包
(3)Worker端集群
(4)Dashboard控制台
该框架主要由4个部分组成。
(1)etcd集群
etcd是一个高性能的配置中心,etcd可以以极小的资源占用,提供高效的监听订阅服务。主要用于存放规则配置、Worker的IP、探测出的热key、手工添加的热key。
(2)Client端jar包
就是在服务中添加的引用jar,引入后,就可以以便捷的方式去判断某key是否热是key。同时该jar还完成了:key上报、监听etcd的规则配置的变化、Worker信息变化、热key的变化、对热key进行本地Caffeine缓存等。
(3)Worker端集群
Worker端是一个独立部署的Java程序,启动后会连接etcd,并定期上报自己的IP信息。Client端会通过etcd获取Worker端的地址并进行长连接。之后,Worker端主要就是对各个Client发来的待测key进行累加计算。当达到etcd里设定的rule阈值后,将热key推送到各个Client。
(4)Dashboard控制台
控制台是一个带可视化界面的Java程序,也是连接到etcd。之后在控制台设置各个APP的key规则,譬如2秒出现20次算热key。然后当Worker探测出来热key后,会将key发往etcd。Dashboard也会监听热key信息,进行入库保存记录。同时,Dashboard也可以手工添加、删除热key,供各个Client端监听。
综上,可以看到热key探测框架JdHotkey没有依赖于任何定制化的组件。与Redis更是毫无关系,核心就是靠Netty连接,Client端送出待测key,然后由各个Worker完成分布式计算,算出热key后就直接推送到Client端,非常轻量级。