Redisson 分布式锁出现死锁,两种解决方式

项目场景:

多节点应用获取单号,使用Redisson(3.10.1)分布式锁保证单号不会重复。


问题描述

有一台应用已经获取到分布式锁,还没解锁就突然宕机,虽然看门狗默认设置internalLockLeaseTime/lockWatchdogTimeout = 30000毫秒,正常情况会超时解锁,但没有生效(原因不明),此时出现死锁。

public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6372")
                .setPassword("123456")
                .setDatabase(5)
                .setConnectTimeout(10000)
                .setTimeout(10000)
                .setPingConnectionInterval(3000);
        RedissonClient redissonClient = Redisson.create(config);

        System.out.println("=================================================");
        test(redissonClient, false);
//      redissonClient.shutdown();
    }

    private static void test(RedissonClient redissonClient, Boolean flag) {
        // 分布式锁
        RLock lock = redissonClient.getLock("BILL_NO:AAA");
        System.out.println("1、开始 " + lock.getName());
        Boolean isDead = true;
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)) {
                System.out.println("2、执行业务 " + lock.getName());
                isDead = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (flag && lock.isLocked() && lock.isHeldByCurrentThread()) {
                System.out.println("3、解锁 " + lock.getName());
                lock.unlock();
            } else {
                System.out.println("3、不解锁 " + lock.getName());
            }
            System.out.println("4、结束 " + lock.getName());
//            if (isDead) {
//            System.out.println("kill lock " + lock.getName());
//                lock.delete();
//            }
        }
    }
======================================================================================
1、开始 BILL_NO:AAA
2、执行业务 BILL_NO:AAA
3、不解锁 BILL_NO:AAA
4、结束 BILL_NO:AAA

Redisson 分布式锁出现死锁,两种解决方式_第1张图片


解决方案:

  一般情况只有应用线程持有这把锁,才会通过看门狗续期,默认30s会过期回收。无法回收的情况下,说明没有设置超期时间,可以以下处理:
 1、redisson会在db-5创建分布式锁key,可以直接删除key。
 2、使用java脚本,执行 lock.delete()。

你可能感兴趣的:(分布式,redis,java,spring,boot)