redis&zk分布式锁

12 篇文章 0 订阅

本文主要介绍redis分布式锁,要点1、删除时确认锁防止超时误删除锁 2、锁的续签

看代码吧

public class RedisLock {
    private static String lockkey = "defalut-lock-key";
    private static long locktimeSecond = 30;
    private static ConcurrentHashMap<String, WatchDog> threadCache  = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        lock();

        try {
            Thread.sleep(65000);
        } catch (Exception e) {}

        unLock();
    }

    //lock by default keyname & timeout(in second)
    public static boolean  lock() {
        return lock(lockkey, locktimeSecond);
    }

    //get distibutedLock and start a daemon thread to add ttl
    public static boolean lock(String key, long lockTimeSecond) {
        String state = "";
        try {
            state = JedisConfig.jedis.set(key, String.valueOf(Thread.currentThread().getId()), "NX", "EX", lockTimeSecond);
        } catch (Exception e) {
            e.printStackTrace();
            JedisConfig.close();
        }

        boolean result = state.equals("OK");
        if (!result) return result;

        WatchDog watchDog = new WatchDog(key, String.valueOf(Thread.currentThread().getId()), 15);
        threadCache.put(key, watchDog);
        Thread thread = new Thread(watchDog);
        thread.setDaemon(true);
        thread.start();

        return result;
    }

    //unlock by default keyname
    public static void unLock() {
        unLock(lockkey);
    }

    //unlock distributedLock and stop daemon thread
    public static void unLock(String key) {
        JedisConfig.jedis.eval(LuaScript.checkAndDel(key, String.valueOf(Thread.currentThread().getId())));
        WatchDog watchDog = threadCache.get(key);
        if (watchDog != null) {
            watchDog.stop();
        }
    }

    //watchDog
    static class WatchDog implements Runnable {
        private String key;
        private String value;
        private long lockTime;

        WatchDog(String key, String value, long lockTime) {
            this.key = key;
            this.value = value;
            this.lockTime = lockTime;
        }

        private void stop() {
            Thread.currentThread().interrupt();
        }

        @Override
        public void run() {
            long waitTime = lockTime * 1000 * 2 / 3;
            System.out.println("守护线程启动");
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(waitTime);
                    if ((long) JedisConfig.jedis.eval(LuaScript.checkAndExpire(key, value, lockTime)) == -1) {
                        System.out.println("当前锁不属于当前线程");
                        stop();
                    } else {
                        System.out.println("续签成功");
                    }
                } catch (InterruptedException ie) {
                    System.out.println("守护线程中断");
                } catch (Exception e) {
                    System.out.println("执行异常" + e);
                }
            }
            System.out.println("守护线程结束");
        }
    }
}

zk分布式锁,实现比较简单仅仅是判断锁是否能获取,如果要实现阻塞等待和重试,可以用临时顺序节点,判断当前节点是否是最小的,后一个节点watch前一个,前一个完成了通知下一个。

public class ZkLock {
    private static final String lockPath = "/defalut-lock-rootnode";

    public static boolean lock() {
        return lock(lockPath);
    }

    public static boolean lock(String lockPath) {
        try {
            if (Zkconfig.cf.checkExists().forPath(lockPath) == null) {
                System.out.println("初始化根节点。。。");
                Zkconfig.cf.create().creatingParentsIfNeeded().forPath(lockPath);
            }
        } catch (Exception e) {
            System.out.println("zk初始化异常" + e);
        }

        //创建临时节点
        try {
            Zkconfig.cf.create().withMode(CreateMode.EPHEMERAL).forPath(lockPath + "/lock");
            System.out.println("获取锁成功");
            return true;
        } catch (Exception e) {
            System.out.println("竞争锁失败" + e);
        }
        return false;
    }

    public static void unLock() {
        unLock(lockPath);
    }

    public static void unLock(String lockPath) {
        try {
            if (Zkconfig.cf.checkExists().forPath(lockPath) == null) {
                return;
            }

            Zkconfig.cf.delete().deletingChildrenIfNeeded().forPath(lockPath);
        } catch (Exception e) {
            System.out.println("删除锁失败" + e);
        }
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值