决定синхронизировать了 2 个应用程序节点之间的方法。为此,我FencedLock从 library 中获取了解决方案HazelCast。我根据文档做了所有事情,节点互相看到并合并到кластер. 该方法也синхронизировался开始工作 1 次,但有时会重复该方法的工作(不经常)。
我无法理解它与什么有关!我通过创建一个分布式对象解决了这个问题IMap,我将它放在方法中,并基于它开始制定方法或忽略它。我认为它更像是一个拐杖。
有没有办法通过fencedLock-i 及其配置来解决这个问题?
PS 请不要链接到任何关键字并将我发送到google,因为文档很少,也没有工作代码示例。我将不胜感激。
hazelCast.yaml 文件:
hazelcast:
network:
join:
multicast:
enabled: true
HazelCastConfiguration 类:
@Configuration
public class HazelCastConfiguration {
@Bean
public com.hazelcast.config.Config hazelCastConfig() {
return new Config();
}
@Bean
public HazelcastInstance hazelcastInstance(Config hazelCastConfig) {
return Hazelcast.newHazelcastInstance(hazelCastConfig);
}
@Bean
public IMap<String, LocalDateTime> timeMap(@Qualifier("hazelcastInstance") HazelcastInstance hazelcastInstance) {
return hazelcastInstance.getMap("hazelcastTimeMap");
}
在方法上面,我挂断Spring Scheduler并设置它cron每 5 秒工作一次。
我添加IMap之前的方法:
@Scheduled(cron = "0/5 * * * * *")
public void sentMessage() {
FencedLock lock = hazelcastInstance.getCPSubsystem().getLock("myLock");
if (lock.tryLock()) {
try {
System.out.println("test message!" + LocalDateTime.now());
} finally {
lock.unlock();
}
}
}
他在 2 个节点之间工作的结果:
节点 1:
节点 2:
添加IMap并定位后,问题就消失了。
添加IMap后的方法:
@Scheduled(cron = "0/5 * * * * *")
public void sentMessage() {
FencedLock lock = hazelcastInstance.getCPSubsystem().getLock("myLock");
if (lock.tryLock()) {
try {
LocalDateTime date = timeMap.get("message");
if (date == null || LocalDateTime.now().isAfter(date)) {
System.out.println("test message!" + LocalDateTime.now());
timeMap.put("message", LocalDateTime.now().plusSeconds(4));
}
} finally {
lock.unlock();
}
}
}


Spring 和 OS 不保证您同时执行
@Scheduled(cron = "0/5 * * * * *")+ 方法的主体很小并且可以快速运行。结果,有时事实证明,在一个节点上,调度调用设法获取锁、打印和释放锁。此时,第二个拿到锁,但没有人持有锁,所以第二个也起作用。
IMap只是解决了这个问题。这个决定不是拐杖,而是很正常的。可以通过更长的时间持有锁来做不同的事情,以便第二个节点有时间唤醒,尝试获取锁并中断。例如
Thread.sleep(100)- 但这也不是 100% 的保证,因为第二个可能迟到 100 毫秒以上 - 例如,他有一个 GC。这甚至可以在您的日志中看到 - 一旦执行在 X.008ms 中,另一次在 X.171ms 中。