一直以为对swift的ring文件充满好奇,这段时间重新研究swift,正好借此机会好好研究下。
ring文件时一个Gzip的压缩文件,可以通过相关python库直接读取这个文件,代码如下:
gz_file =GzipFile('/etc/swift/object.ring.gz','rb')
这里的gz_file其实就是一个文件句柄,通过read我们可以读取数据进行分析。
1、 前4个字节 ‘RING‘
2、 第5和6个字节版本信息 1
3、 接下来的四个字节是一个字典(设备信息、part-shift、replica_count)的长度信息
4、 接下来就该字典的内容,如下:
{u'devs':[{u'replication_port': 6000,u'zone': 1,u'weight': 1.0,u'ip': u'192.168.246.6',u'region': 1,u'port':6000,u'replication_ip': u'192.168.246.6',u'Meta': u'',u'device':u'vdb',u'id': 0},{u'replication_port': 6000,u'zone': 2,u'ip': u'192.168.246.7',u'port': 6000,u'replication_ip': u'192.168.246.7',u'device': u'vdb',u'id': 1},u'zone': 3,u'ip': u'192.168.246.8',u'replication_ip': u'192.168.246.8',u'id':2},u'ip':u'192.168.246.9',u'replication_ip':u'192.168.246.9',u'id': 3}],
u'part_shift': 14,
u'replica_count': 2}
其中:
devs 指的是这个ring中包含哪些设备,就是通过swift-ring-builder add这个操作加进来的设备;
part_shift: 32-partition_power;
replica_count 指的是副本数;
5、 接下来是replica_count*(2*partition_count)个字节的信息,这部分内容不可直接打印,但load ring文件的时候这部分会转 换成array,作为ring_dict['replica2part2dev_id']的列表项(partition_count = 1 << (32 - ring_dict['part_shift'])),详细 说明如下:ring_dict['replica2part2dev_id']是一个列表,其项目的数目等于replica_count,每一项都是一个array,其形式为 array.array ('H',gz_file.read(2 * partition_count)),array可以打印出来,形式上就是一个数组,每个array包含了partition 个项,每一项的内容就是device的id。
6、至此ring文件就读完了
重点说下ring_dict['replica2part2dev_id']的value的含义。顾名思义,其实就是副本—partition—设备id的映射关系。顶层是 array,每个array对应一个副本;array的大小与partition数目一致;array中每一项对应一个partition;array[partition-num] 得到的就是这个partition的设备id。比如要查询partition=X的设备,方法如下:
Devid=[]
For replica in ring_dict['replica2part2dev_id']:
Devip.append(replica[X])
ring_dict['replica2part2dev_id']其实就是如下的一个二维数组:
在分析的过程中对swift的概念也有所理解:
创建ring时,通过指定的参数即可计算出partition的数据,partition相关的内容也是存放在ring文件中。在对运行中的程序,partition对应于array,array的数量就是备份的次数。我们可以认为每个partition在每个array中对应一个备份。我们可以查询给定partition的位置(备份几次,就会有几个位置)。