Hazelcast を使用するのは初めてです。Web アプリケーションのデータ ストレージとして Hazelcast 3.6-EA を使用しています。アプリケーションは複数のインスタンスで実行されるため、複数のスレッドが同じマップで動作しようとするときに、競合状態を回避するためにロック メカニズムを実装する必要があります。
必要な動作は次のとおりです。マップの操作を開始する最初のインスタンスは、マップをロックし、必要な更新を実行する必要があります。もう 1 つのインスタンスは、マップがロックされていることを確認し、更新の実行をスキップする必要があります。
したがって、このようなロックの主な利点は、同じコードが 2 回実行されるのを回避できることです。
public void consumePerformances(Date date) {
Collection<Integer> performancesId = timeformPerformanceService.getPerformancesIds();
timeFormService.getPerformancesByMeetingDate(date, new DataCallback<List<Performance>>() {
@Override
public void onResponse(List<Performance> performances) {
Map<Integer, Performance> newPerformancesMap =
performances.stream().collect(Collectors.toMap(Performance::getPerformanceId, Function.identity()));
newPerformancesMap.entrySet().stream().filter(element -> performancesId.contains(element.getKey()))
.forEach(element -> element.getValue().setUpdateDate(date));
timeformPerformanceService.save(newPerformancesMap.values());
}
@Override
public void onError(Throwable throwable) {
}
});
}
public void save(Collection<Performance> performances) {
LOGGER.info("Save performances to the hazelcast");
IMap<Integer, Performance> map = hazelcastInstance.getMap(PERFORMANCE_CACHE_NAME);
performances.forEach(item -> {
try {
if (map.tryLock(item.getPerformanceId(), 1, TimeUnit.SECONDS, 300, TimeUnit.SECONDS)) {
try {
map.put(item.getPerformanceId(), item);
} finally {
try {
map.unlock(item.getPerformanceId());
} catch (IllegalMonitorStateException e) {
LOGGER.error("Lock was released, due to lease time was expired");
}
}
} else {
LOGGER.info("Lock on key: {} is not released yet", map.get(item.getPerformanceId()));
}
} catch (InterruptedException e) {
LOGGER.error("Lock error. Key could not be equal to null");
}
}
);
}
ロック メカニズムを正しく理解しているかどうか、および上記の実装された動作で目的の結果が得られるかどうか、疑問があります。
詳細な説明をいただければ幸いです。
get(key)
また、スレッドでマップをロックし、もう一方が操作のみを実行している場合の動作を教えてください。