pythonバージョンの分散錠


この記事は、pythonバージョンの分散ロックを実現し、Javaバージョンは、curatorを使用することができます。pythonバージョンは以下の通りです。
分散システムを開発する際には、分散ロックが必要なコンポーネントといえる。最近いくつか調査と試みをしました。比較して、Zoo Keeperベースの分散式のロックはいいです。
 
IBMの書き込みを参照しました。https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
この中で、Zoo Keeperの共有ロック(すなわち分散式錠)が実現されるという話があります。
共有ロックは同じプロセスで簡単に実現できますが、プロセスをまたいだり、異なるServerの間では実現できません。Zookeeperはこの機能が簡単に実現できます。実現方法もロックが必要なServerはEPHEMERALを作成します。SEQUNTIALディレクトリノードは、その後、GET_Children方法を呼び出して、現在のディレクトリノードリストの中で最小のディレクトリノードが自分で作成したディレクトリノードであるかどうかを取得し、もし自分で作成したならば、このロックを獲得します。そうでなければ、existsメソッドを呼び出し、Zookeeper上のディレクトリノードリストの変化を監視します。自分で作成したノードがリストの中で一番小さい番号のディレクトリノードであるため、ロックを取得するのは簡単です。前の自分で作成したディレクトリノードを削除すればいいです。
 この話を通して、原理は大体分かります。ここでは主にPythonによる分散錠の実現について書きます。
実現する
Googleは、Kazooというpythonオープンソースのカバンがあります。Zoo Keeperに対するサポートがよくできました。
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
 
 まず、GitHubに行きます。ソースのカバンをダウンロードします。展開後、インストールを行います。
python setup.py install
 
OK、準備が完了しました。すべてコードの中にあります。
ファイル名:zk_lock.py
#!/usr/bin/env python2.7  
# -*- coding:utf-8 -*-  
#  
#   Author  :   yunjianfei  
#   E-mail  :   [email protected]  
#   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 uhosts」を変更するだけです。 ”このパラメータは、あなたのZoo Keeperのserverアドレスに変更すればいいです。
 
このテストファイルのcopyを複数のサーバーに同時に実行すると、分散ロックの効果が見られます。
回転:http://yunjianfei.iteye.com/blog/2164888