zk - zookeeper实现分布式锁代码

87 阅读5分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序不断追求完美的过程。

分布式锁的原理其实很简单,当然从根本上说所有锁的实现原理其实是一致的,无论多么复杂的锁,底层都是CAS。这里遵循CAS的原则实现了一个zookeeper的分布式锁。

public class ZKTest {

    public static void main(String[] args) {
        for (int i=0; i<8; i++) {
            new Thread(ZKTest::run).start();
        }
    }

    private static void run() {
        String serviceId = serviceId();
        ZooKeeper zk = zk();
        boolean lock = getLock(zk, serviceId);
        if (lock) {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getId() + " " + i);
            }
        }
        close(zk);
    }

    private static void close(ZooKeeper zk) {
        try {zk.close();} catch (Exception e) {e.printStackTrace();}
    }

    private static boolean getLock(ZooKeeper zk, String serviceId) {
        while (!isLeader(zk, serviceId)) {
            toBeLeader(zk, serviceId);
        }
        return true;
    }

    private static String serviceId() {
        return Long.toString(new Random().nextLong());
    }

    private static ZooKeeper zk() {
        try {
            ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 15000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (!Event.EventType.None.equals(event.getType())) {
                        System.out.println("watchEvent : " + event);
                    }
                }
            });
            return zk;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static final String MASTER = "/master";

    private static boolean isLeader(ZooKeeper zk, String serviceId) {
        try {
            byte[] data = zk.getData(MASTER, true, new Stat());
            if (null != data && new String(data).equals(serviceId)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean toBeLeader(ZooKeeper zk, String serviceId) {
        try {
            String path = zk.create(MASTER, serviceId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            System.out.println("path : " + path);
            if (MASTER.equals(path)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }
}

输出结果:

threadId : 18 no : 0
threadId : 18 no : 1
threadId : 18 no : 2
threadId : 18 no : 3
threadId : 18 no : 4
threadId : 18 no : 5
threadId : 18 no : 6
threadId : 18 no : 7
threadId : 18 no : 8
threadId : 18 no : 9
threadId : 18 no : 10
threadId : 18 no : 11
threadId : 18 no : 12
threadId : 18 no : 13
threadId : 18 no : 14
threadId : 18 no : 15
threadId : 18 no : 16
threadId : 18 no : 17
threadId : 18 no : 18
threadId : 18 no : 19
threadId : 18 no : 20
threadId : 18 no : 21
threadId : 18 no : 22
threadId : 18 no : 23
threadId : 18 no : 24
threadId : 18 no : 25
threadId : 18 no : 26
threadId : 18 no : 27
threadId : 18 no : 28
threadId : 18 no : 29
threadId : 18 no : 30
threadId : 18 no : 31
threadId : 18 no : 32
threadId : 18 no : 33
threadId : 18 no : 34
threadId : 18 no : 35
threadId : 18 no : 36
threadId : 18 no : 37
threadId : 18 no : 38
threadId : 18 no : 39
threadId : 18 no : 40
threadId : 18 no : 41
threadId : 18 no : 42
threadId : 18 no : 43
threadId : 18 no : 44
threadId : 18 no : 45
threadId : 18 no : 46
threadId : 18 no : 47
threadId : 18 no : 48
threadId : 18 no : 49
threadId : 18 no : 50
threadId : 18 no : 51
threadId : 18 no : 52
threadId : 18 no : 53
threadId : 18 no : 54
threadId : 18 no : 55
threadId : 18 no : 56
threadId : 18 no : 57
threadId : 18 no : 58
threadId : 18 no : 59
threadId : 18 no : 60
threadId : 18 no : 61
threadId : 18 no : 62
threadId : 18 no : 63
threadId : 18 no : 64
threadId : 18 no : 65
threadId : 18 no : 66
threadId : 18 no : 67
threadId : 18 no : 68
threadId : 18 no : 69
threadId : 18 no : 70
threadId : 18 no : 71
threadId : 18 no : 72
threadId : 18 no : 73
threadId : 18 no : 74
threadId : 18 no : 75
threadId : 18 no : 76
threadId : 18 no : 77
threadId : 18 no : 78
threadId : 18 no : 79
threadId : 18 no : 80
threadId : 18 no : 81
threadId : 18 no : 82
threadId : 18 no : 83
threadId : 18 no : 84
threadId : 18 no : 85
threadId : 18 no : 86
threadId : 18 no : 87
threadId : 18 no : 88
threadId : 18 no : 89
threadId : 18 no : 90
threadId : 18 no : 91
threadId : 18 no : 92
threadId : 18 no : 93
threadId : 18 no : 94
threadId : 18 no : 95
threadId : 18 no : 96
threadId : 18 no : 97
threadId : 18 no : 98
threadId : 18 no : 99

threadId : 21 no : 0
threadId : 21 no : 1
threadId : 21 no : 2
threadId : 21 no : 3
threadId : 21 no : 4
threadId : 21 no : 5
threadId : 21 no : 6
threadId : 21 no : 7
threadId : 21 no : 8
threadId : 21 no : 9
threadId : 21 no : 10
threadId : 21 no : 11
threadId : 21 no : 12
threadId : 21 no : 13
threadId : 21 no : 14
threadId : 21 no : 15
threadId : 21 no : 16
threadId : 21 no : 17
threadId : 21 no : 18
threadId : 21 no : 19
threadId : 21 no : 20
threadId : 21 no : 21
threadId : 21 no : 22
threadId : 21 no : 23
threadId : 21 no : 24
threadId : 21 no : 25
threadId : 21 no : 26
threadId : 21 no : 27
threadId : 21 no : 28
threadId : 21 no : 29
threadId : 21 no : 30
threadId : 21 no : 31
threadId : 21 no : 32
threadId : 21 no : 33
threadId : 21 no : 34
threadId : 21 no : 35
threadId : 21 no : 36
threadId : 21 no : 37
threadId : 21 no : 38
threadId : 21 no : 39
threadId : 21 no : 40
threadId : 21 no : 41
threadId : 21 no : 42
threadId : 21 no : 43
threadId : 21 no : 44
threadId : 21 no : 45
threadId : 21 no : 46
threadId : 21 no : 47
threadId : 21 no : 48
threadId : 21 no : 49
threadId : 21 no : 50
threadId : 21 no : 51
threadId : 21 no : 52
threadId : 21 no : 53
threadId : 21 no : 54
threadId : 21 no : 55
threadId : 21 no : 56
threadId : 21 no : 57
threadId : 21 no : 58
threadId : 21 no : 59
threadId : 21 no : 60
threadId : 21 no : 61
threadId : 21 no : 62
threadId : 21 no : 63
threadId : 21 no : 64
threadId : 21 no : 65
threadId : 21 no : 66
threadId : 21 no : 67
threadId : 21 no : 68
threadId : 21 no : 69
threadId : 21 no : 70
threadId : 21 no : 71
threadId : 21 no : 72
threadId : 21 no : 73
threadId : 21 no : 74
threadId : 21 no : 75
threadId : 21 no : 76
threadId : 21 no : 77
threadId : 21 no : 78
threadId : 21 no : 79
threadId : 21 no : 80
threadId : 21 no : 81
threadId : 21 no : 82
threadId : 21 no : 83
threadId : 21 no : 84
threadId : 21 no : 85
threadId : 21 no : 86
threadId : 21 no : 87
threadId : 21 no : 88
threadId : 21 no : 89
threadId : 21 no : 90
threadId : 21 no : 91
threadId : 21 no : 92
threadId : 21 no : 93
threadId : 21 no : 94
threadId : 21 no : 95
threadId : 21 no : 96
threadId : 21 no : 97
threadId : 21 no : 98
threadId : 21 no : 99

....................

由于zookeeper是全局一致的,所以,本程序无论是在单个服务器上,还是在集群中效果是一致的,都可以保证线程安全。

在这里插入图片描述