248 Star 1.8K Fork 606

GVP京东零售 / hotkey

 / 详情

关于Client在接收到hotKey的处理建议

Backlog
Bug
Opened this issue  
2020-10-14 15:26
package com.jd.platform.hotkey.client.callback;

import com.jd.platform.hotkey.client.cache.CacheFactory;
import com.jd.platform.hotkey.client.log.JdLogger;
import com.jd.platform.hotkey.common.model.HotKeyModel;

/**
 * 收到来自于worker的新增key,或者etcd的新增和删除key事件
 *
 * @author wuweifeng wrote on 2020-02-24
 * @version 1.0
 */
public class DefaultNewKeyListener implements ReceiveNewKeyListener {

    @Override
    public void newKey(HotKeyModel hotKeyModel) {
        long now = System.currentTimeMillis();
        //如果key到达时已经过去1秒了,记录一下。手工删除key时,没有CreateTime
        if (hotKeyModel.getCreateTime() != 0 && Math.abs(now - hotKeyModel.getCreateTime()) > 1000) {
            JdLogger.warn(getClass(), "the key comes too late : " + hotKeyModel.getKey() + " now " +
                    +now + " keyCreateAt " + hotKeyModel.getCreateTime());
        }
        if (hotKeyModel.isRemove()) {
            //如果是删除事件,就直接删除
            deleteKey(hotKeyModel.getKey());
            return;
        }
        //已经是热key了,又推过来同样的热key,做个日志记录,并刷新一下
        if (JdHotKeyStore.isHot(hotKeyModel.getKey())) {
            JdLogger.warn(getClass(), "receive repeat hot key :" + hotKeyModel.getKey() + " at " + now);
        }
        addKey(hotKeyModel.getKey());
    }

    private void addKey(String key) {
        ValueModel valueModel = ValueModel.defaultValue(key);
        if (valueModel == null) {
            //不符合任何规则
            deleteKey(key);
            return;
        }
        //如果原来该key已经存在了,那么value就被重置,过期时间也会被重置。如果原来不存在,就新增的热key
        JdHotKeyStore.setValueDirectly(key, valueModel);
    }

}

这里接收到同样的Key的处理,我不知道是不是社区版和内部版是有差异还是怎么的,我认为是有问题的,由于你这里接收到同样的Key就会直接去刷新缓存,再结合worker的推送代码来看,社区版的代码中可能会出现以下情形:
步骤一: worker识别到了新的hotKey: key0,并执行了推送,然后删除了worker本地的计数器,并开始重新计数;
步骤二: client接收到了新的hotKey: key0,这是在本地缓存中设置了值,此时hotKey:key0对应的本地缓存值为魔法值;
步骤三: client接收到了hotKey: key0的调用请求,此时client将本地缓存中的真实值以懒加载的模式设置到本地缓存中;
步骤四: 在hotKey的Duration的有效期内,worker再次识别到了同样的hotKey: key0,重复了步骤一的操作;
步骤五: 重复了步骤二的操作,那么此时在之前步骤三中设置的真实值被覆盖,导致client在接收到下一次请求后需要再次懒加载真实值,对于Duration比较长的hotKey反而造成了不利影响.

此时,我理解,对于重复的HotKey应该对Duration执行Refresh操作,而不是直接给定一个魔法值!
从猜想应该是内部版实现了收到hotKey的通知时,主动去加载真实值的逻辑,所以在内部版中是不会有问题的!

Comments (5)

小白猪 created缺陷
Expand operation logs

这个是专门这么设置的,以保证在duration到期后,缓存的值一定被失效。直接refresh后,会导致value可能存在的永不过期,是比较危险的操作。

这个是专门这么设置的,以保证在duration到期后,缓存的值一定被失效。直接refresh后,会导致value可能存在的永不过期,是比较危险的操作。

@tianyaleixiaowu 但是在我的debug下,已经出现了本地缓存的真实值被魔法值覆盖的情况,是否refresh不讨论,但是如果已经是hotKey了,那么此时的策略应该是什么都不做.
我在本地做了以下修改:
输入图片说明

是这样的,如果已经是热key了,client就会不再上报该key,在duration有效期内,不会再次上报,worker也就不会重新推送。
到过期时间剩余2秒内,才会继续上报,此时worker才会推送重复的key过来,然后覆盖掉真实value

是这样的,如果已经是热key了,client就会不再上报该key,在duration有效期内,不会再次上报,worker也就不会重新推送。
到过期时间剩余2秒内,才会继续上报,此时worker才会推送重复的key过来,然后覆盖掉真实value

@tianyaleixiaowu 确实,推送待探测Key是会停掉,但是还仍然有10秒一次的访问次数推送在统计,这个是没有去停止的,因此在Duration时间大于12秒的场景下仍然会出现我所说的问题.

譬如key是设置60秒过期,在判热被推送到client后,58秒内不会收到重复推送,59秒时会收到重复推送,并且真实value被覆盖,需要重新拉取value。
是如此设计的

Sign in to comment

Status
Assignees
Projects
Milestones
Pull Requests
Successfully merging a pull request will close this issue.
Branches
Planed to start   -   Planed to end
-
Top level
Priority
Duration (hours)
Confirm
参与者(2)
303698 tianyalei 1578919857
Java
1
https://gitee.com/jd-platform-opensource/hotkey.git
git@gitee.com:jd-platform-opensource/hotkey.git
jd-platform-opensource
hotkey
hotkey

Search

181749 a2d7925e 1850385 181749 9f8568a7 1850385