京东零售 / hotkey 热点key探测工具使用

简介: 京东零售 / hotkey 热点key探测工具使用

1、安装etcd

在etcd下载页面下载对应操作系统的etcd,https://github.com/etcd-io/etcd/releases 使用3.4.x以上。

2、启动worker(集群) 下载并编译好代码,将worker打包为jar,启动即可。如:

java -jar $JAVA_OPTS worker-0.0.1-SNAPSHOT.jar --etcd.server=${etcdServer}

worker可供配置项如下:

etcdServer为etcd集群的地址,用逗号分隔

JAVA_OPTS是配置的JVM相关,可根据实际情况配置

threadCount为处理key的线程数,不指定时由程序来计算。

workerPath代表该worker为哪个应用提供计算服务,譬如不同的应用appName需要用不同的worker进行隔离,以避免资源竞争。

3、启动控制台

下载并编译好dashboard项目,创建数据库并导入resource下db.sql文件。 配置一下application.yml里的数据库相关和etcdServer地址。

启动dashboard项目,访问ip:8081,即可看到界面。

其中节点信息里,即是当前已启动的worker列表。

规则配置就是为各app设置规则的地方,初次使用时需要先添加APP。在用户管理菜单中,添加一个新用户,设置他的APP名字,如sample。之后新添加的这个用户就可以登录dashboard给自己的APP设置规则了,登录密码默认123456。

如图就是一组规则,譬如其中as__开头的热key的规则就是interval-2秒内出现了threshold-10次就认为它是热key,它就会被推送到jvm内存中,并缓存60秒,prefix-true代表前缀匹配。那么在应用中,就可以把一组key,都用as__开头,用来探测。

4、client端接入使用

引入client的pom依赖。

在应用启动的地方初始化HotKey,譬如

@PostConstruct
public void initHotkey() {
    ClientStarter.Builder builder = new ClientStarter.Builder();
    ClientStarter starter = builder.setAppName("appName").setEtcdServer("http://1.8.8.4:2379,http://1.1.4.4:2379,http://1.1.1.1:2379").build();
    starter.startPipeline();
}

其中还可以setCaffeineSize(int size)设置本地缓存最大数量,默认5万,setPushPeriod(Long period)设置批量推送key的间隔时间,默认500ms,该值越小,上报热key越频繁,相应越及时,建议根据实际情况调整,如单机每秒qps10个,那么0.5秒上报一次即可,否则是空跑。该值最小为1,即1ms上报一次。

注意:

如果原有项目里使用了guava,需要升级guava为以下版本,否则过低的guava版本可能发生jar包冲突。或者删除自己项目里的guava的maven依赖,guava升级不会影响原有任何逻辑。

<dependency>
 <groupId>com.google.guava</groupId>
 <artifactId>guava</artifactId>
 <version>28.2-jre</version>
 <scope>compile</scope>
</dependency>

有时可能项目里没有直接依赖guava,但是引入的某个pom里引了guava,也需要将guava排除掉。

如果原有项目使用了fastjson,需要降为2.0.0版本以下, 在2.0.0版本以上,com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer类已经删除。 导致JSON工具类com.jd.platform.hotkey.common.tool.FastJsonUtils初始化时找不到类。 规则配置的json转换有问题。 推荐使用与HotKey相同的版本:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.70</version>
</dependency>

使用:

主要有如下4个方法可供使用

boolean JdHotKeyStore.isHotKey(String key)

Object JdHotKeyStore.get(String key)

void JdHotKeyStore.smartSet(String key, Object value)

Object JdHotKeyStore.getValue(String key)

1 boolean isHotKey(String key) ,该方法会返回该key是否是热key,如果是返回true,如果不是返回false,并且会将key上报到探测集群进行数量计算。该方法通常用于判断只需要判断key是否热、不需要缓存value的场景,如刷子用户、接口访问频率等。

2 Object get(String key),该方法返回该key本地缓存的value值,可用于判断是热key后,再去获取本地缓存的value值,通常用于redis热key缓存

3 void smartSet(String key, Object value),方法给热key赋值value,如果是热key,该方法才会赋值,非热key,什么也不做

4 Object getValue(String key),该方法是一个整合方法,相当于isHotKey和get两个方法的整合,该方法直接返回本地缓存的value。 如果是热key,则存在两种情况,1是返回value,2是返回null。返回null是因为尚未给它set真正的value,返回非null说明已经调用过set方法了,本地缓存value有值了。 如果不是热key,则返回null,并且将key上报到探测集群进行数量探测。

最佳实践:

1 判断用户是否是刷子

if (JdHotKeyStore.isHotKey(“pin__” + thePin)) {
        //限流他,do your job
    }

2 判断商品id是否是热点

Object skuInfo = JdHotKeyStore.getValue("skuId__" + skuId);
       if(skuInfo == null) {
           JdHotKeyStore.smartSet("skuId__" + skuId, theSkuInfo);
       } else {
              //使用缓存好的value即可
        }

或者这样:

if (JdHotKeyStore.isHotKey(key)) {
              //注意是get,不是getValue。getValue会获取并上报,get是纯粹的本地获取
              Object skuInfo = JdHotKeyStore.get("skuId__" + skuId);
              if(skuInfo == null) {
                  JdHotKeyStore.smartSet("skuId__" + skuId, theSkuInfo);
              } else {
                  //使用缓存好的value即可
              }
         }

项目中的例子:

正常1秒点击1次,返回的都是notHot

连续疯狂点击发送,请求这个接口时,就会返回isHot

目录
相关文章
|
大数据
《会员通、服务通、商品通、营销通,全域大数据解决方案有秘诀》电子版地址
会员通、服务通、商品通、营销通,全域大数据解决方案有秘诀
169 0
《会员通、服务通、商品通、营销通,全域大数据解决方案有秘诀》电子版地址
|
vr&ar 双11
热点 | IP时代,看互联网电视怎么玩儿
以小米47英寸电视为例,甫一推出,便开出2999元低价。而乐视随即宣布将50寸的电视价格定为2499元……负责超级电视业务的乐视致新高级副总裁彭钢面对媒体时曾直言不讳,低价是取得销售业绩的最好利器。
146 0
|
存储 人工智能 算法
|
存储 缓存 NoSQL
热点Key的发现与解决之道
在2018数据库直播大讲堂峰会-Redis专场中阿里云数据库组的梁盼从热点Key产生的原因,造成的问题开始讲解。通过在热点Key问题解决上以往的方法与阿里的方法的对比,形象的表述了阿里云在解决热点Key问题上所提方案的可行性与优越性。
7502 1