可以带着下面问题来阅读
1.swift的对象信息存储在什么位置?
2.集群中发生存储节点宕机、新增(删)存储节点、新增(删)zone等必须改变partition和node间的映射关系时需要对哪个文件更新?
swift是openstack的object storage service。
关于代码目录
下图是它的代码目录
其中可以看到几个重要的文件夹:Accout、Ring、Container、obj、proxy。
在物理主机上安装完成的目录为:
- /usr/lib/python2.7/dist-packages/swift# ls
- account common container __init__.py __init__.pyc obj proxy
复制代码
关于使用到的第三方
swift的对象信息使用是SQLite数据库。SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
可以通过下面的方法来输出数据库包含的表- import sqlite3
- cx=sqlite3.connect("./test.db")
- cu=cx.cursor()
- cu.execute("select name from sqlite_master where type='table'")
- print cu.fetchall()
复制代码
如果需要查看某个数据库的某个表的内容,可以通过下列语句来实现,利于我需要查看test.db内container的内容:- import sqlite3
- cx=sqlite3.connect("./test.db")
- cu=cx.cursor()
- cu.execute("select * from container")
- print cu.fetchall()
复制代码
可以通过打开官网的链接详细了解感兴趣的每一个函数,其实可以当做手册来用:http://docs.openstack.org/developer/swift/py-modindex.html但是其中代码并不是全部,如果需要全部的代码,还是需要下载swift的源代码。
关于ring
对于ring的分析有一篇博客分析的比较好:http://www.cnblogs.com/yuxc/archive/2012/06/22/2558312.html#2438073,它的原文在http://greg.brim.net/page/building_a_consistent_hashing_ring.html。
Ring的Rebalance机制
当集群中发生存储节点宕机、新增(删)存储节点、新增(删)zone等必须改变partition和node间的映射关系时,就需要对Ring文件进行更新,也就是在swift文档中见到的rebalance一词。
在源码中对rebalance的定义如下:swift/Common/Ring/Builder.py- def rebalance(self):
- """
- Rebalance the ring.
-
- This is the main work function of the builder, as it will assign and
- reassign partitions to devices in the ring based on weights, distinct
- zones, recent reassignments, etc.
-
- The process doesn't always perfectly assign partitions (that'd take a
- lot more analysis and therefore a lot more time -- I had code that did
- that before). Because of this, it keeps rebalancing until the device
- skew (number of partitions a device wants compared to what it has) gets
- below 1% or doesn't change by more than 1% (only happens with ring that
- can't be balanced no matter what -- like with 3 zones of differing
- weights with replicas set to 3).
-
- :returns: (number_of_partitions_altered, resulting_balance)
- """
- self._ring = None
- if self._last_part_moves_epoch is None:
- self._initial_balance()
- self.devs_changed = False
- return self.parts, self.get_balance()
- retval = 0
- self._update_last_part_moves()
- last_balance = 0
- while True:
- reassign_parts = self._gather_reassign_parts()
- self._reassign_parts(reassign_parts)
- retval += len(reassign_parts)
- while self._remove_devs:
- self.devs[self._remove_devs.pop()['id']] = None
- balance = self.get_balance()
- if balance < 1 or abs(last_balance - balance) < 1 or \
- retval == self.parts:
- break
- last_balance = balance
- self.devs_changed = False
- self.version += 1
- return retval, balance
复制代码
在基于原有的Ring来构造新Ring时,swift-ring-builder首先要重新计算每个设备所需的partition数量。然后,将需要重新分配的partition收集起来。取消分配给被移除设备上的partition并把这些partition添加到收集列表。从拥有比当前所需的partition数多的设备上随机地取消分配多出的partition并添加到收集列表中。最后,将收集列表中的partition使用与初始化分配时类似的方法重新分配。
在本地执行swift-ring-builder命令行来生成新的ring文件,然后把这些文件复制到集群的每个节点的/etc/swift目录中,所有需要使用ring的server进程会每15秒(默认值)检查一遍ring文件的修改时间mtime,如果发现和内存中的不一致,则重新加载ring文件到内存中去。、
举例说明
现在再增加一台存储节点node4并作为zone5,使用相同权重的devcie。那么每个存储节点上的partition数是52428.8。需要从每台存储节点上随机地移除13107.2个partition到收集列表,然后再重新分配这些parttion到node4上。当有partition的replica被重分配时,重分配的时间将被记录。在RingBuilder类内使用min_part_hours来限制在规定时间内,同一个partition不会被移动两次。
由于收集用来重新分配的partition是基于随机的,rebalacne进程并不能一次就可以完美地重平衡ring。为了达到一个较为平衡的ring,rebalacne进程被重复执行直到接近完美(小于1%)或者当rebalacne的提升达不到最小值1%。
具体的操作如下,首先移除旧的ring文件:
rm -f account.builder account.ring.gz backups/account.builder backups/account.ring.gz
.......
然后,重新平衡ring文件:- swift-ring-builder account.builder create 18 3 1
- swift-ring-builder account.builder add z1-192.168.1.50:6002/sdc 100
- swift-ring-builder account.builder add z2-192.168.1.51:6002/sdc 100
- swift-ring-builder account.builder add z3-192.168.1.52:6002/sdc 100
- swift-ring-builder account.builder add z4-192.168.1.54:6002/sdc 100
- swift-ring-builder account.builder add z5-192.168.1.53:6002/sdc 100
- swift-ring-builder account.builder rebalance
-
- swift-ring-builder container.builder create 18 3 1
- swift-ring-builder container.builder add z1-192.168.1.50:6001/sdc 100
- swift-ring-builder container.builder add z2-192.168.1.51:6001/sdc 100
- swift-ring-builder container.builder add z3-192.168.1.52:6001/sdc 100
- swift-ring-builder container.builder add z4-192.168.1.54:6001/sdc 100
- swift-ring-builder container.builder add z5-192.168.1.53:6001/sdc 100
- swift-ring-builder container.builder rebalance
-
- swift-ring-builder object.builder create 18 3 1
- swift-ring-builder object.builder add z1-192.168.1.50:6000/sdc 100
- swift-ring-builder object.builder add z2-192.168.1.51:6000/sdc 100
- swift-ring-builder object.builder add z3-192.168.1.52:6000/sdc 100
- swift-ring-builder object.builder add z4-192.168.1.54:6000/sdc 100
- swift-ring-builder object.builder add z5-192.168.1.53:6000/sdc 100
- swift-ring-builder object.builder rebalance
复制代码
最后,复制account.ring.gz、container.ring.gz、object.ring.gz到集群的各节点的/etc/swift目录下。这样我们就完成了Ring的重平衡(rebalance)。
|