使用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一段时间,再次尝试获取锁。或者在竞争锁失败之后,添加对该锁的监听事件,一旦所被释放,立即争抢。
上面,通过创建临时节点就可以达到排他锁的作用。这里,使用临时顺序节点,是为了用顺序来维持一个天然的先来先抢占的队列。通过获取全部顺序节点并排序,就知道谁是下一个获取锁的对象。