您的位置:首页 > 理论基础 > 数据结构算法

深入云存储系统Swift核心组件:Ring数据结构及构建、重平衡操作

2012-06-28 18:30 507 查看
  在上一篇深入云存储系统Swift核心组件:Ring实现原理剖析中,我们分析了Ring的设计原理,深入探讨了Swift如何通过Ring组件来实现冗余的、可扩展的目的。本文旨在分析在实际swift的运行中,如何来构建Ring文件。

Ring数据结构

  Ring 的数据结构由三个顶层域构成,其中:

List of Devices,表示集群中设备的列表;

Partition Assignment List,表示partition到device的指派;

Partition Shift Value,表示计算数据hash的移位量。

1.List of Devices

  设备列表在Ring类内部被称为devs。在设备列表中的每一项是带有以下键的字典:

                       表1:Devs键值说明

id

integer

在device列表中的索引

zone

integer

设备所在的zone

weight

float

device与其他device的相对权重。这常常直接与device和其它device的磁盘空间数量的比有关

ip

string

device的服务器IP地址

port

int

服务器进程所使用的TCP端口用来提供该设备的服务请求

device

string

服务器上device的磁盘名称。例如:sdb1

meta

string

存储设备额外信息的通用字段。该信息并不直接被服务器进程使用,但是在调试时会派上用场。例如,安装的日期和时间和硬件生产商可以存储在这。

2.Partition Assignment List

  用于存放每个replica与device间映射关系。在Ring类内部被称为_replica2part2dev_id,列表中含有replica数量(3)的array(‘I’),array(‘I’)的长度等于ring的partition数量,在array(‘I’)中的每个值为List of Devices中的索引id。

3.Partition Shift Value

  Partition Shift Value在Ring类内部称为_part_shift。该值用于转换一个MD5 hash值来计算对于该哈希值的数据所在的partition。使用hash值的前4个字节用于计算。例如,为了计算路径/account/container/object的虚节点,Python代码如下:


partition = unpack_from('>I',md5('/account/container/object').digest())[0] >> self._part_shift



  其中>表示big-endian byte order,I表示长度为4 byte unsigned int

  举例:我们以SAIO安装下的ring文件为例,使用python读取/etc/swift/object.ring.gz存放的数据,获得的是以devs、 part_shift、 replica2part2dev_id 为key的dict类数据,其中:


devs=

[{'device': 'sdb1',

'id': 0,

'ip': '127.0.0.1',

'meta': '',

'port': 6010,

'weight': 1.0,

'zone': 1},

{'device': 'sdb2',

'id': 1,

'ip': '127.0.0.1',

'meta': '',

'port': 6020,

'weight': 1.0,

'zone': 2},

{'device': 'sdb3',

'id': 2,

'ip': '127.0.0.1',

'meta': '',

'port': 6030,

'weight': 1.0,

'zone': 3},

{'device': 'sdb4',

'id': 3,

'ip': '127.0.0.1',

'meta': '',

'port': 6040,

'weight': 1.0,

'zone': 4}]

part_shift=4

replica2part2dev_id=[array(‘I’, [3, 2...]) array(‘I’, [0, 1...]), array(‘I’, [1, 3...])]



构建Ring文件

  假设我们配置了一个4个node组成的集群,分别为node0、node1、node2、node3,在这个集群中,我们为4个存储节点配置了2^18个partition,平均每个存储节点分配65536个partition。

  需要使用swift-ring-bulider命令来构建ring文件,关于swift-ring-builder命令的详细用法,在shell下直接敲该命令即可获得提示。这里只涉及构建新Ring文件的方法,需要用到两个相关选项:

构建相关的builder文件:swift-ring-builder <builder_file> create <part_power> <replicas><min_part_hours>

添加node到builder文件:swift-ring-builder <builder_file> add z<zone>-<ip>:<port>/<device_name>_<meta> <weight>

例如,该集群目前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 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 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 rebalance



Ring的Rebalance机制

  当集群中发生存储节点宕机、新增(删)存储节点、新增(删)zone等必须改变partition和node间的映射关系时,就需要对Ring文件进行更新,也就是在swift文档中见到的rebalance一词。

  在基于原有的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)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: