Hazelcast 在群集中的应用程序上运行相同的IsScheduledExecutorService时,如何防止重复任务?
我想了解用于IsScheduledExecutorService以防止重复任务的hazelcast方法之间的区别。 我有两个带有HazelcastInstance的java应用程序。我分别拥有两个hazelcast实例(服务器)的hazelcast集群。 我使用IMap,希望每午夜重置AtomicLongHazelcast 在群集中的应用程序上运行相同的IsScheduledExecutorService时,如何防止重复任务?,hazelcast,hazelcast-imap,Hazelcast,Hazelcast Imap,我想了解用于IsScheduledExecutorService以防止重复任务的hazelcast方法之间的区别。 我有两个带有HazelcastInstance的java应用程序。我分别拥有两个hazelcast实例(服务器)的hazelcast集群。 我使用IMap,希望每午夜重置AtomicLong config.getScheduledExecutorConfig("my scheduler") .setPoolSize(16) .
config.getScheduledExecutorConfig("my scheduler")
.setPoolSize(16)
.setCapacity(100)
.setDurability(1);
class DelayedResetTask implements Runnable, HazelcastInstanceAware, Serializable {
static final long serialVersionUID = -7588380448693010399L;
private transient HazelcastInstance client;
@Override
public void run() {
final IMap<Long, AtomicLong> map = client.getMap(HazelcastConfiguration.mapName);
final ILogger logger = client.getLoggingService().getLogger(HazelcastInstance.class);
logger.info("Show data in cache before reset: " + map.entrySet());
map.keySet().forEach(key -> map.put(key, new AtomicLong(0)));
logger.info("Data was reseted: " + map.entrySet());
}
@Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) { this.client = hazelcastInstance; }
}
private void resetAtMidnight() {
final Long midnight = LocalDateTime.now().until(LocalDate.now().plusDays(1).atStartOfDay(), ChronoUnit.MINUTES);
executor.scheduleAtFixedRate(new DelayedResetTask(), midnight, TimeUnit.DAYS.toMinutes(1), TimeUnit.MINUTES);
}
config.getScheduledExecutorConfig(“我的调度器”)
.setPoolSize(16)
.设定容量(100)
.1(1);
类DelayedResetTask实现可运行、HazelcastInstanceAware、可序列化{
静态最终长serialVersionUID=-7588380448693010399L;
私有实例客户端;
@凌驾
公开募捐{
最终IMap映射=client.getMap(HazelcastConfiguration.mapName);
最终ILogger logger=client.getLoggingService().getLogger(HazelcastInstance.class);
info(“重置前在缓存中显示数据:”+map.entrySet());
forEach(key->map.put(key,new-AtomicLong(0));
logger.info(“数据已重置:+map.entrySet());
}
@凌驾
public void setHazelcastInstance(HazelcastInstance HazelcastInstance){this.client=HazelcastInstance;}
}
午夜时分的私人无效重置(){
最后一个长午夜=LocalDateTime.now().until(LocalDate.now().plusDays(1.atStartOfDay(),ChronoUnit.MINUTES);
executor.scheduleAtFixedRate(新的DelayedResetTask(),午夜,时间单位.DAYS.toMinutes(1),时间单位.MINUTES);
}
我不想在每个实例上并行执行此任务。阅读文档后,我不明白如何在两台服务器上执行一个步骤的重置(没有重复的任务,没有同时在两台服务器上执行)。我可以使用什么方法执行任务
ScheduleonalMembersatFixedRate
或scheduleAtFixedRate
或scheduleOnMembersAtFixedRate
。
如何在群集中的应用程序上运行相同的IsScheduledExecutorService时防止重复任务?您只需要在群集中运行一次代码,因为您要重置的映射可以从任何成员访问。两个成员访问同一个映射实例,只有条目保存在不同的成员中。您可以使用
scheduleAtFixedRate
运行一次
此外,您不需要调用IMap#keySet().forEach()
来遍历映射中的所有条目。相反,您可以使用EntryProcessor
,如下所示:
public static class DelayedResetTask implements Runnable, HazelcastInstanceAware, Serializable {
static final long serialVersionUID = -7588380448693010399L;
private transient HazelcastInstance client;
@Override
public void run() {
final IMap<Long, AtomicLong> map = client.getMap(HazelcastConfiguration.mapName);
final ILogger logger = client.getLoggingService().getLogger(HazelcastInstance.class);
logger.info("Show data in cache before reset: " + map.entrySet());
map.executeOnEntries(new AbstractEntryProcessor() {
@Override
public Object process(Map.Entry entry) {
entry.setValue(new AtomicLong(0));
return null;
}
});
logger.info("Data was reseted: " + map.entrySet());
}
@Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) { this.client = hazelcastInstance; }
公共静态类DelayedResetTask实现可运行、HazelCastInstanceWare、可序列化{
静态最终长serialVersionUID=-7588380448693010399L;
私有实例客户端;
@凌驾
公开募捐{
最终IMap映射=client.getMap(HazelcastConfiguration.mapName);
最终ILogger logger=client.getLoggingService().getLogger(HazelcastInstance.class);
info(“重置前在缓存中显示数据:”+map.entrySet());
map.executeOnEntries(新的AbstractEntryProcessor(){
@凌驾
公共对象进程(Map.Entry){
entry.setValue(新的原子长度(0));
返回null;
}
});
logger.info(“数据已重置:+map.entrySet());
}
@凌驾
public void setHazelcastInstance(HazelcastInstance HazelcastInstance){this.client=HazelcastInstance;}
这是某种错误,但在本例中,我有一个重复。在第一个应用程序中,数据在正确的时间重置(我首先启动),但在第二个应用程序中,数据在错误的时间重置两次(6小时后)。我在两台服务器上都看到了日志“重置前在缓存中显示数据”。我认为这是错误的,但不明白为什么,您只计划了一次吗?如果您每次启动应用程序时都计划了作业,那么它将运行两次。您能确认您只计划了一次吗?我不明白您的意思。我有两个jar(应用程序)使用相同的代码(您在问题中看到了)。我在不同的时间在不同的服务器上运行它们(应用程序)。每个应用程序使用IsScheduledExecutorService(StartRequestCountersScheduler())启动作业。当两个应用程序同时运行时,它们将构建一个群集。您只需在单个群集中调用executor.scheduleAtFixedRate
API一次(仅从一个应用程序),因为每次您调用它时,它都会安排另一个作业。@Alparslan Avci感谢您的回答。我的应用程序中有相同的代码,我不想选择一个领导者或在程序案例中选择节点将启动什么IExecutorService。我在docs Scheduled Executor Service中看到了任务的名称,以防止重复任务。executor、 scheduleAtFixedRate(名为(“我的任务”,new DelayedResetTask()),1,1,TimeUnit.MINUTES);这个解决方案对我有帮助吗?