在做混合云项目时,我们把nova-compute, cinder-volume做成分布式的了,这样就有个问题了,在nova-compute中会有一些文件锁,我们怎样改成分布式锁呢?
方案一:
在数据库中创建一张锁表格,操作每个资源时,需要加锁的话,在锁表格中,把资源的对应的lock字段变成True,别的资源需要操作此资源时,定时向数据库查询lock字段变成Flase,释放锁的时候变成Flase,其他的进程进可以获取到锁了。
方案二:
通过Tooz在python中实现分布式群组和锁管理。
Tooz通过驱动(driver)的形式来提供后端的功能,所有的驱动没有相同的功能鲁棒性,但是要依赖于你的环境,只要有可用的驱动就足够了。像Openstack中大部分的做法一样,我们让部署员/操作员/开发人员来选择他们想使用的的驱动,告诉他们让他们来权衡。
目前,Tooz提供了一下的驱动:
- Kazoo(zookeeper)
- Zake
- memcached
- redis
- SysV IPC (只提供分布式锁功能)
- PostgreSQL(只提供分布式锁功能)
- MySQL(只提供分布式锁功能)
我们先看一个例子,采用Zookeeper作为Tooz的driver。
ooz中提供了分布式的锁机制。一个锁可以由一个名字代表,并且一个锁只能同时被一个节点拥有。
1. 建立锁
[python]
- #! /usr/bin/env python
- import time
- from tooz import coordination
- coordinator = coordination.get_coordinator('kazoo://localhost:2181', b'host-1')
- coordinator.start()
- lock = coordinator.get_lock("test")
- try:
- with lock:
- while True:
- print "Locked in test"
- time.sleep(1)
- except KeyboardInterrupt:
- coordinator.stop()
其中由"test" 来代表这个锁。
2. 申请锁
[python]
- #! /usr/bin/env python
- from tooz import coordination
- coordinator = coordination.get_coordinator('kazoo://localhost:2181', b'host-2')
- coordinator.start()
- lock = coordinator.get_lock("test")
- if lock.acquire(1000):
- print "Lock released"
- coordinator.stop()
其中lock.acquire(1000) 表示申请锁,并在1000s之后超时。
执行结果
1. 建立锁
[python]
- # python lock_server.py
- Locked in test
- Locked in test
- Locked in test
- ....
2. 申请锁
[python]
- # python lock_client.py
3. ctrl+c 第一个进程,lock_client会输出"Lock released"
其实第二种方案中把driver改成mysql,就是第一种方案了。
我们来看一下tooz的介绍:
Tooz的历史背景
在过去的一年多时间里,和我在e'Novance的Yassine Lamgarchal以及其他同事,我们在调研一种解决Openstack中经常遇到的一个问题:多个分布式进程的同步问题。同时,我们共事的其他人继续推动开发一些新的功能,我们希望在同一时间找到一个解决这个新问题的通用解决方案以付清这个技术债。
Yassine写了第一个Openstack需要的群组管理服务的想法,Openstack中的多个项目可以使用它。我在香港的Openstack Summit的olso展厅中演示了这个想法,后来证明这个想法被很好的接收,并在summit的一周后我们在stackforge中创建了Tooz项目
Tooz的目标
Tooz是一个Python库来提供分布式协调API。它主要的目标是处理分布式中的群组和群组中的成员。
Tooz也提供了其他有用的功能:分布式锁。它允许分布式节点可以获取和释放锁以实现同步(比如:访问一个共享资源)
Tooz的架构
如果你对分布式系统比较熟悉,你肯定会想现在不是已经有很多可用的解决方案来解决这个问题,比如:zookeeper, Raft consensus algorithm,甚至是Redis
你会对Tooz不是这些解决方案的一个新的产物感到兴奋,它是在这个方案之上的抽象层。它通过驱动(driver)的形式来提供后端的功能,也并没有尝试做任何加强的功能 。
所有的驱动没有相同的功能鲁棒性,但是要依赖于你的环境,只要有可用的驱动就足够了。像Openstack中大部分的做法一样,我们让部署员/操作员/开发人员来选择他们想使用的的驱动,告诉他们让他们来权衡。
目前,Tooz提供了一下的驱动:
- Kazoo(zookeeper)
- Zake
- memcached
- redis
- SysV IPC (只提供分布式锁功能)
- PostgreSQL(只提供分布式锁功能)
- MySQL(只提供分布式锁功能)
所有的驱动都支持分布式进程,部分驱动还支持分布式网络(Zookeeper,memcached, redis....)部分驱动只能在单节点使用(IPC)
需要注意的是Tooz API都是完全异步的,使它变得更加高效,并可能包含在一个事件循环中。
Tooz的功能
群组管理
Tooz提供了一套API来管理群组成员。基本的操作包括:群组创建、加入群组、离开群组以及查看群组成员。它同时提供了当有成员加入或离开群组时通知的功能。
领导选取
每个群组都有一个被选取的领导。所有的节点都可以决定是否参与选举。如果有领导消失了,其它成员会从当前获选中选择新的领导节点。当一个领导被选取时其它成员可能得到通知,同时各个节点可以随时获取当前组的领导。
分布式锁
当需要在分布式环境中实现进程同步时,你可能需要一种方法来锁定一些资源的访问。分布式锁将会帮助你完成这个功能。
在Openstack中使用Tooz
Ceilometer是Openstack中第一个使用Tooz的项目。它替换了旧的通过RPC来检测alarm evaluator进程是否存活的Alarm系统。Ceilometer采用Tooz中的群组管理功能来协调多个alarm evaluator进程。
另外一个应用场景是在Juno 发行版的Ceilometer在agent central中采用了分布式的polling任务。它同样采用了Tooz中的群组管理功能。
Oslo团队已经在Juno发行版中将Tooz作为Olso项目的一部分。 这意味着会有更多的开发人员来维护它,并且它将作为Openstack发行过程的一部分。
它打开了Tooz走进Openstack的一扇门,我们接下来的计划是为Nova写一个服务群组驱动。
这是一个完整的Tooz文档:http://docs.openstack.org/developer/tooz/ 包含了很多这里描述过的功能的例子,如果你感兴趣就开始学习它吧。
参考文献: