You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

@SnapLock注解下多实例定时任务重复执行问题排查

多实例下snap-scheduler分布式锁失效排查方案

针对你在Railway部署两个实例后,snap_lock表出现同一定时任务方法的两条执行记录的问题,以下是具体排查方向和验证步骤:

1. 数据库与Schema一致性检查

首先确认两个实例是否操作同一数据库的同一Schema:

  • 对比两个实例的spring.datasource.hikari.schema配置值,PostgreSQL对Schema名称大小写敏感(未用双引号包裹时默认小写),确保完全一致;
  • 直接连接数据库执行查询:
    SELECT * FROM snap_lock WHERE task_key = 'REPORT_CURRENT_TIME';
    
    查看两条记录的task_method字段是否完全相同。如果task_method不同,说明snap-scheduler对方法的标识生成存在差异(比如代理类、类加载器导致全限定类名不一致)。

2. 分布式锁原子性验证

snap-scheduler的数据库锁依赖原子性的INSERT/UPDATE操作避免并发插入:

  • 检查snap-scheduler版本是否支持INSERT ... ON CONFLICT DO UPDATE逻辑(这是PostgreSQL实现分布式锁的标准原子操作);
  • 验证snap_lock表的主键约束是否生效:
    SELECT conname, conkey FROM pg_constraint WHERE conrelid = 'snap_lock'::regclass;
    
    确认主键是(task_key, task_method),确保同一任务的同一方法无法插入重复记录。

3. 时区一致性排查

定时任务和锁过期时间依赖时区统一,若两个实例时区不一致会导致锁判断失效:

  • 在代码中添加日志验证JVM时区:
    log.info("JVM TimeZone: {}", TimeZone.getDefault().getID());
    
    确认两个实例均为Europe/Kiev;
  • 验证数据库时区:
    SHOW timezone;
    
    确保数据库时区与JVM时区一致;
  • 对比两条锁记录的lock_until字段,若时间差对应时区偏移量,说明时区不一致导致锁过期判断错误。

4. 部署环境与配置验证

  • 确认两个实例引入的snap-scheduler版本完全一致,不同版本可能存在锁逻辑差异;
  • 检查SnapAppConfig是否正确初始化了数据库锁相关Bean,确保启用的是分布式锁而非本地锁;
  • 验证Railway部署的两个实例是否共享同一数据库资源,不存在网络隔离或数据库副本导致的独立操作。

5. 方法标识生成问题处理

若排查发现两条记录的task_method不同(比如一个是代理类方法名):

  • 将定时任务方法从protected改为public,避免Spring CGLIB代理生成不同的类方法标识;
  • 若需保留protected修饰符,可查看snap-scheduler文档,确认是否支持手动指定task_method标识,或配置忽略代理类的方法签名生成策略。

内容的提问来源于stack exchange,提问作者Mykhaylo Terokhin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 14:25:35