Hazelcast 在群集中的应用程序上运行相同的IsScheduledExecutorService时,如何防止重复任务?

Hazelcast 在群集中的应用程序上运行相同的IsScheduledExecutorService时,如何防止重复任务?,hazelcast,hazelcast-imap,Hazelcast,Hazelcast Imap,我想了解用于IsScheduledExecutorService以防止重复任务的hazelcast方法之间的区别。 我有两个带有HazelcastInstance的java应用程序。我分别拥有两个hazelcast实例(服务器)的hazelcast集群。 我使用IMap,希望每午夜重置AtomicLong config.getScheduledExecutorConfig("my scheduler") .setPoolSize(16) .

我想了解用于IsScheduledExecutorService以防止重复任务的hazelcast方法之间的区别。 我有两个带有HazelcastInstance的java应用程序。我分别拥有两个hazelcast实例(服务器)的hazelcast集群。 我使用IMap,希望每午夜重置AtomicLong

    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);这个解决方案对我有帮助吗?