Zookeeper 实现一个简单的分布式锁

2,281 阅读1分钟

使用zookeeper实现一个简单的分布式锁:


import time

from kazoo.client import KazooClient
from kazoo.exceptions import NodeExistsError, NoNodeError

zk = KazooClient(hosts='127.0.0.1:2181')
zk.start()


class Lock:

    root_path = '/demo/locks/'

    def __init__(self, name):
        self._name = name
        self._realpath = None

    @property
    def locked(self):
        return self._realpath is not None

    def acquire(self):
        try:
            self._realpath = zk.create(self.root_path + self._name,
                                       ephemeral=True,
                                       sequence=False,
                                       makepath=True)
        except NodeExistsError:
            # 节点已存在
            print('node alread exists')
        else:
            print(self._realpath)

    def release(self):
        try:
            zk.delete(self._realpath)
        except NoNodeError:
            print('no not exists')

        print(f'delete node:{self._realpath} succeed')


def test():
    lock = Lock('some_shared_resouce')
    lock.acquire()
    if lock.locked:
        print('do something')
        time.sleep(5)
        lock.release()
    else:
        print('acquire lock failed')


def main():
    test()

if __name__ == '__main__':
    main()

启动两个Python进程

输出:

/demo/locks/some_shared_resouce
do something
delete node:/demo/locks/some_shared_resouce succeed
node alread exists
acquire lock failed

其中,如果另外一个进程没有获取锁,可以自己sleep一段时间,再次尝试获取锁。或者在竞争锁失败之后,添加对该锁的监听事件,一旦所被释放,立即争抢。


上面,通过创建临时节点就可以达到排他锁的作用。这里,使用临时顺序节点,是为了用顺序来维持一个天然的先来先抢占的队列。通过获取全部顺序节点并排序,就知道谁是下一个获取锁的对象。