python 版本分布式锁
此文章,實(shí)現(xiàn)python 版本的分布式鎖,java版本的可以使用curator很容易實(shí)現(xiàn),python版本如下
在做分布式系統(tǒng)開發(fā)的時候,分布式鎖可以說是必需的一個組件。最近做了一些調(diào)研和嘗試,經(jīng)過對比,基于ZooKeeper的分布式鎖還是很不錯的。
?
參照了IBM的一個帖子:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
其中有一段話描述了ZooKeeper的共享鎖(即分布式鎖)實(shí)現(xiàn),如下:
共享鎖在同一個進(jìn)程中很容易實(shí)現(xiàn),但是在跨進(jìn)程或者在不同 Server 之間就不好實(shí)現(xiàn)了。Zookeeper 卻很容易實(shí)現(xiàn)這個功能,實(shí)現(xiàn)方式也是需要獲得鎖的 Server 創(chuàng)建一個 EPHEMERAL_SEQUENTIAL 目錄節(jié)點(diǎn),然后調(diào)用 getChildren方法獲取當(dāng)前的目錄節(jié)點(diǎn)列表中最小的目錄節(jié)點(diǎn)是不是就是自己創(chuàng)建的目錄節(jié)點(diǎn),如果正是自己創(chuàng)建的,那么它就獲得了這個鎖,如果不是那么它就調(diào)用 exists(String path, boolean watch) 方法并監(jiān)控 Zookeeper 上目錄節(jié)點(diǎn)列表的變化,一直到自己創(chuàng)建的節(jié)點(diǎn)是列表中最小編號的目錄節(jié)點(diǎn),從而獲得鎖,釋放鎖很簡單,只要刪除前面它自己所創(chuàng)建的目錄節(jié)點(diǎn)就行了。
?通過這段話,大概可以明白其原理。下面我主要寫一下基于Python的分布式鎖實(shí)現(xiàn)。
實(shí)現(xiàn)
Google了一下,有個叫Kazoo的python開源包很好的實(shí)現(xiàn)了對ZooKeeper的支持。
Kazoo is a Python library designed to make working with Zookeeper a more hassle-free experience that is less prone to errors.
?
鏈接如下:https://kazoo.readthedocs.org/en/latest/
GitHub地址:?https://github.com/python-zk/kazoo
?
?首先,我們?nèi)itHub,下載其源碼包。解壓縮之后,進(jìn)行安裝
python setup.py install
?
OK,準(zhǔn)備工作完成,一切盡在代碼中:
文件名:zk_lock.py
#!/usr/bin/env?python2.7?? #?-*-?coding:utf-8?-*-?? #?? #???Author??:???yunjianfei?? #???E-mail??:???yunjianfei1987@gmail.com?? #???Date????:???2014/12/09?? #???Desc????:?? #??import?logging,?os,?time?? from?kazoo.client?import?KazooClient?? from?kazoo.client?import?KazooState?? from?kazoo.recipe.lock?import?Lock??class?ZooKeeperLock():??def?__init__(self,?hosts,?id_str,?lock_name,?logger=None,?timeout=1):??self.hosts?=?hosts??self.id_str?=?id_str??self.zk_client?=?None??self.timeout?=?timeout??self.logger?=?logger??self.name?=?lock_name??self.lock_handle?=?None??self.create_lock()??def?create_lock(self):??try:??self.zk_client?=?KazooClient(hosts=self.hosts,?logger=self.logger,?timeout=self.timeout)??self.zk_client.start(timeout=self.timeout)??except?Exception,?ex:??self.init_ret?=?False??self.err_str?=?"Create?KazooClient?failed!?Exception:?%s"?%?str(ex)??logging.error(self.err_str)??return??try:??lock_path?=?os.path.join("/",?"locks",?self.name)??self.lock_handle?=?Lock(self.zk_client,?lock_path)??except?Exception,?ex:??self.init_ret?=?False??self.err_str?=?"Create?lock?failed!?Exception:?%s"?%?str(ex)??logging.error(self.err_str)??return??def?destroy_lock(self):??#self.release()??if?self.zk_client?!=?None:??self.zk_client.stop()??self.zk_client?=?None??def?acquire(self,?blocking=True,?timeout=None):??if?self.lock_handle?==?None:??return?None??try:??return?self.lock_handle.acquire(blocking=blocking,?timeout=timeout)??except?Exception,?ex:??self.err_str?=?"Acquire?lock?failed!?Exception:?%s"?%?str(ex)??logging.error(self.err_str)??return?None??def?release(self):??if?self.lock_handle?==?None:??return?None??return?self.lock_handle.release()??def?__del__(self):??self.destroy_lock()??def?main():??logger?=?logging.getLogger()??logger.setLevel(logging.INFO)??sh?=?logging.StreamHandler()??formatter?=?logging.Formatter('%(asctime)s?-%(module)s:%(filename)s-L%(lineno)d-%(levelname)s:?%(message)s')??sh.setFormatter(formatter)??logger.addHandler(sh)??zookeeper_hosts?=?"192.168.10.2:2181,?192.168.10.3:2181,?192.168.10.4:2181"??lock_name?=?"test"??lock?=?ZooKeeperLock(zookeeper_hosts,?"myid?is?1",?lock_name,?logger=logger)??ret?=?lock.acquire()??if?not?ret:??logging.info("Can't?get?lock!?Ret:?%s",?ret)??return??logging.info("Get?lock!?Do?something!?Sleep?10?secs!")??for?i?in?range(1,?11):??time.sleep(1)??print?str(i)??lock.release()??if?__name__?==?"__main__":??try:??main()??except?Exception,?ex:??print?"Ocurred?Exception:?%s"?%?str(ex)??quit()測試的時候,只需要改一下“zookeeper_hosts?”這個參數(shù),改為你自己的ZooKeeper的server地址即可.
?
將該測試文件copy到多個服務(wù)器,同時運(yùn)行,就可以看到分布式鎖的效果了。
轉(zhuǎn)自:http://yunjianfei.iteye.com/blog/2164888
轉(zhuǎn)載于:https://blog.51cto.com/5148737/1975603
總結(jié)
以上是生活随笔為你收集整理的python 版本分布式锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到熟人借钱是啥意思
- 下一篇: [转载]Spring配置文件详解一: