Shedlock分布式定时任务漏执行问题排查求助
场景描述
使用Shedlock实现分布式锁,应用部署在20台机器上,期望定时任务每5分钟在任意一台机器执行一次。
定时任务代码
@Scheduled(cron = "0 */5 * * * *") @SchedulerLock(name = "executeTaskLock", lockAtLeastFor = "1m", lockAtMostFor = "4m") public void executeTask() throws Exception { LockAssert.assertLocked(); // 任务执行逻辑,耗时约400ms - 2s }
配置代码
@Bean public JedisPool jedisPoolForSchedulerLocking() { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(2); jedisPoolConfig.setMaxIdle(2); jedisPoolConfig.setMinIdle(1); jedisPoolConfig.setMaxWaitMillis(500); return new JedisPool(jedisPoolConfig, {host}, {port}, {timeout}, {port}); } @Bean public LockProvider lockProvider(@Qualifier("jedisPoolForSchedulerLocking") JedisPool jedisPool) { return new JedisLockProvider(jedisPool, "PRD"); }
问题现象
定时任务偶尔出现漏执行情况,例如12:25、12:30正常执行后,直到12:45才再次执行,中间漏掉2次任务。实际任务执行时长仅400ms-3s,lockAtLeastFor设为1分钟、lockAtMostFor设为4分钟,配置看似符合要求,但无法定位问题。根据Shedlock官方文档,任务允许重复执行但不应出现漏执行。
依赖信息(pom.xml)
<dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.42.0</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-redis-jedis</artifactId> <version>4.42.0</version> </dependency> <java.version>1.8</java.version> <spring-boot.version>2.2.1.RELEASE</spring-boot.version>
问题分析与解决方案
1. 关键配置错误:JedisPool构造参数错误
配置代码中JedisPool的构造函数最后一个参数被错误设置为{port},正确参数应为Redis的密码({password})。这会导致Jedis连接池初始化异常,无法正常连接Redis,进而使分布式锁逻辑失效,极端情况下所有机器都无法获取锁,导致任务漏执行。
修复方式:
修正JedisPool构造参数,将最后一个{port}替换为Redis密码:
return new JedisPool(jedisPoolConfig, {host}, {port}, {timeout}, {password});
2. Redis连接池资源不足
当前连接池maxTotal=2、maxWaitMillis=500ms,20台机器同时触发定时任务抢锁时,连接池容量过小且等待超时时间过短,会导致大量机器无法获取Redis连接,抢锁失败,最终没有机器执行任务。
调整建议:
调大连接池参数,提升并发处理能力:
jedisPoolConfig.setMaxTotal(15); // 按需调整,建议10-20 jedisPoolConfig.setMaxWaitMillis(2000); // 延长等待时间至2秒
3. 日志排查
开启Shedlock的DEBUG级日志,查看抢锁过程中的详细日志,确认是否存在连接超时、锁获取失败等异常信息。例如在logback.xml中添加:
<logger name="net.javacrumbs.shedlock" level="DEBUG"/>
4. 系统时钟同步检查
确认20台机器的系统时钟是否同步,时钟漂移可能导致锁的过期时间计算错误,影响锁的释放与获取逻辑。可通过NTP服务确保所有机器时钟一致。
5. 版本兼容性验证
当前使用的Shedlock 4.42.0与Spring Boot 2.2.1.RELEASE理论上兼容,但可考虑升级到Shedlock的稳定新版本,排查是否存在已知的锁逻辑bug。
内容的提问来源于stack exchange,提问作者tusharRawat

