您的位置:首页 > 其它

探讨Hazelcast分布式map的驱逐策略实现

2017-07-25 10:42 190 查看
1、背景介绍

      营销系统会承接来自收银台的活动查询的请求,理论上是一个1+的请求,通常这是指数级的增加。考虑使用hz做一个前置的缓存,使用请求参数的hash值为key(这里不讨论hash碰撞,事实上这对于业务是没有影响的),考虑到是集群分布所以分布式map是第一选择,无奈的是目前官方对于multiMap的驱逐策略实现是不支持的。

2、解题思路

     虽然分布式map不支持驱逐但是imap是支持驱逐的,能不能借助监听器实现共生呢?

     第一步先做一个工具类封装put方法,在方法内把值备份到分布式map

     @Component("hazelcastHelper")
public class HazelcastHelper {
@Resource(name = "crabMap")
private IMap<Object, Object> hzMap;

@Autowired
private MultiMap<Object, Object> hzMultiMap;

@Value("${multimap_expired_time}")
private int EXPIRED_TIME;

public IMap<Object, Object> getHzMap() {
return hzMap;
}

public MultiMap<Object, Object> getHzMultiMap() {
return hzMultiMap;
}

public HazelcastHelper instance(){
return this;
}

public void put(String key,Object obj){
hzMap.put(key,obj,EXPIRED_TIME, TimeUnit.SECONDS);
hzMultiMap.put(key,obj);
}

第二步 实现一个监听

public class IMapExpiredListener implements EntryAddedListener<String, Object>,
EntryExpiredListener<String,Object>,
EntryRemovedListener<String, Object>, EntryUpdatedListener<String, Object> {
@Autowired
HazelcastHelper hazelcastHelper;
@Override
public void entryAdded(EntryEvent<String, Object> event) {
System.out.println("entryAdded: " + event);
}

@Override
public void entryRemoved(EntryEvent<String, Object> event) {
System.out.println("entryRemoved: " + event);
}

@Override
public void entryUpdated(EntryEvent<String, Object> event) {
System.out.println("entryUpdated: " + event);
}

@Override
public void entryExpired(EntryEvent<String, Object> entryEvent) {
System.out.println("entryExpired: " + entryEvent);
hazelcastHelper.getHzMultiMap().remove(entryEvent.getKey());

第三步 配置监听

<hz:map name="crabMap">
<hz:near-cache time-to-live-seconds="3"/>
<!--<hz:near-cache max-idle-seconds="${multimap_expired_time}"/>-->
<hz:near-cache max-idle-seconds="${multimap_expired_time}"/>
<!--<hz:near-cache time-to-live-seconds="3"/>-->
<hz:entry-listeners>
<hz:entry-listener include-value="false" local="false" class-name="com.wangyin.seapay.crab.biz.rulengine.utils.IMapExpiredListener"/>
<!--<hz:entry-listener implementation="dummyEntryListener" local="true"/>-->
</hz:entry-listeners>
</hz:map>
理论上我们可以实现这种共生的关系,但是实际的测试中我们发现hz是无法注入到监听里面的,原因是在实例化监听器的时候hz并没有完成实例化,那么我们在配置文件中先声明bean怎么样呢,经测试还是不行。那么我们就索性做一个单例:

public class HazelcastUtil extends ApplicationObjectSupport{
public  TriggerRuleJudger triggerRuleJudger;
public LimitRulerJudger limitRulerJudger;
public RewardRuleJudger rewardRuleJudger;
public ProCalculusService proCalculusService;
public HazelcastHelper hazelcastHelper;

private volatile static HazelcastUtil instance;
private HazelcastUtil (){}

public static HazelcastUtil getInstance() {
if (instance == null) {
synchronized (HazelcastUtil.class) {
if (instance == null) {
instance = new HazelcastUtil();
}
}
}
return instance;
}

}


事实证明也是不起作用的,貌似就无解了这个东西,我们怎么才能在hz实例化之后再注册监听呢?我们将监听类作为内部类写到工具类里面,在put方法被调用的时候手动注册监听,为了避免多次注入我们首先加一个标识,这样程序运行期间保证只注入一次。经测试这种方法是可行的,就是有点绕,代码过于恶心就不贴了,还是希望官方能给予一个良好的支持。如果大家有什么好的思路欢迎交流。
                                                                                                                                                                                                                     ——我只是个敲代码的不要黑我
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息