探讨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怎么样呢,经测试还是不行。那么我们就索性做一个单例:
事实证明也是不起作用的,貌似就无解了这个东西,我们怎么才能在hz实例化之后再注册监听呢?我们将监听类作为内部类写到工具类里面,在put方法被调用的时候手动注册监听,为了避免多次注入我们首先加一个标识,这样程序运行期间保证只注入一次。经测试这种方法是可行的,就是有点绕,代码过于恶心就不贴了,还是希望官方能给予一个良好的支持。如果大家有什么好的思路欢迎交流。
——我只是个敲代码的不要黑我
营销系统会承接来自收银台的活动查询的请求,理论上是一个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方法被调用的时候手动注册监听,为了避免多次注入我们首先加一个标识,这样程序运行期间保证只注入一次。经测试这种方法是可行的,就是有点绕,代码过于恶心就不贴了,还是希望官方能给予一个良好的支持。如果大家有什么好的思路欢迎交流。
——我只是个敲代码的不要黑我
相关文章推荐
- Unity手游之路<十二>手游资源热更新策略探讨
- EasyUI tree-grid 数回显问题实现探讨
- 探讨J2ME 流媒体的实现
- iPhone消息推送机制实现与探讨
- wcf应用分布式WEB部署策略实现
- 基于多线程的大容量MMORPG主逻辑服务器实现策略
- 用策略模式实现一个冒险游戏
- 使用实体框架、Dapper和Chain的仓储模式实现策略
- Android初级教程通过简要分析“土司”源码,来自实现定义土司理论探讨
- 策略模式与简单工厂的C++实现
- Java 生成任意位数永不重复的随机数策略实现
- 《大话设计模式》java实现之策略模式
- 深入探讨PHP下拉框选择的实现方法
- 策略模式实现对数据的排序
- 探讨Web组件化的实现
- (转)策略回测的框架、实现、测试
- 一个策略模式的实现
- Unity手游之路<十三>手游代码更新策略探讨
- 栈的弹出函数pop()实现方案探讨