- 定时生成告警的方法在多实例运行的时候,出现加了redis分布式锁依然重复执行的问题,最终导致重复生成数据。
- 这是因为方法的执行速度过快,导致A实例执行完并删除锁后,实例B才开始加锁的情况。
- 原本的代码逻辑
String key = "ScheduleTask_refreshAlert";
try {
if (!redisUtils.exists(key)) {
if (redisUtils.setnx(key, "1", 10, TimeUnit.MINUTES)){
//要执行的告警数据生成代码
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//移除分布锁
redisUtils.del(key);
}
- 修正后的代码
String key = "ScheduleTask_refreshAlert";
try {
if (!redisUtils.exists(key)) {
if (redisUtils.setnx(key, "1", 10, TimeUnit.MINUTES)){
//要执行的告警数据生成代码
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//延迟五秒删除,避免误删除锁导致在其它实例再次执行告警任务。
Thread.sleep(5 * 1000);
redisUtils.del(key);
}
结论使用redis实现分布式锁的时候,不要在任务执行后立刻删除key。否则当方法执行速度是微秒级别的时候,其它实例很可能成功再次执行方法。