redis onExpire 事件仅由一个实例处理
redis onExpire event handled by only one instance
我在集群 (JGroups) 中有一个应用程序 运行 的 2 个实例,并且在 redis 的 onExpire 事件上注册了一个侦听器,问题是侦听器是由这两个实例触发的。如何让它只由一个实例处理?
我找到了解决问题的方法,方法是创建一个新的缓存来锁定 onExpired 的执行,只针对一个实例。在事件执行实现中,我正在检查实例是否可以像下面那样执行它
class InvalidationListener implements CacheEntryExpiredListener<String, .....> {
.....
@Override
public void onExpired(Iterable<CacheEntryEvent<? extends String, ? extends ....>> events) {
events.forEach(event -> {
try {
....
boolean canExecute = cacheLock.putIfAbsent(key, InetAddress.getLocalHost().getHostAddress());
if (canExecute) {
logger.info("This instance will execute the onExpired ");
....
} else {
logger.info("onExpired already executed by another instance");
}
} catch (IOException e) {
logger.error("An error occured in onExpired event", e);
}
});
}
}
解释:
运行 onExpired 的第一个实例会将锁定条目设置为 true 并执行过期实现,然后任何其他实例都不会更改值 (putIfAbsent),因为它已经是 true 然后它将 return false并且它永远不会重复到期实施执行。
锁定入口键与过期键相同,值是实例的IP地址,只是为了将来在Redis中的可追溯性。
PS:每个cacheLock条目将在15秒后过期以释放Redis中的内存。
我在集群 (JGroups) 中有一个应用程序 运行 的 2 个实例,并且在 redis 的 onExpire 事件上注册了一个侦听器,问题是侦听器是由这两个实例触发的。如何让它只由一个实例处理?
我找到了解决问题的方法,方法是创建一个新的缓存来锁定 onExpired 的执行,只针对一个实例。在事件执行实现中,我正在检查实例是否可以像下面那样执行它
class InvalidationListener implements CacheEntryExpiredListener<String, .....> {
.....
@Override
public void onExpired(Iterable<CacheEntryEvent<? extends String, ? extends ....>> events) {
events.forEach(event -> {
try {
....
boolean canExecute = cacheLock.putIfAbsent(key, InetAddress.getLocalHost().getHostAddress());
if (canExecute) {
logger.info("This instance will execute the onExpired ");
....
} else {
logger.info("onExpired already executed by another instance");
}
} catch (IOException e) {
logger.error("An error occured in onExpired event", e);
}
});
}
}
解释: 运行 onExpired 的第一个实例会将锁定条目设置为 true 并执行过期实现,然后任何其他实例都不会更改值 (putIfAbsent),因为它已经是 true 然后它将 return false并且它永远不会重复到期实施执行。 锁定入口键与过期键相同,值是实例的IP地址,只是为了将来在Redis中的可追溯性。
PS:每个cacheLock条目将在15秒后过期以释放Redis中的内存。