zoukankan      html  css  js  c++  java
  • 深入云存储系统Swift核心组件:Ring数据结构及构建、重平衡操作


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

    Ring数据结构

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

    1. List of Devices,表示集群中设备的列表
    2. Partition Assignment List表示partitiondevice的指派;
    3. 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

      用于存放每个replicadevice间映射关系。在Ring类内部被称为_replica2part2dev_id,列表中含有replica数量(3)array(I),array(I)的长度等于ringpartition数量,在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 keydict类数据,其中:

     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文件的方法,需要用到两个相关选项:

    1. 构建相关的builder文件:swift-ring-builder <builder_file> create <part_power> <replicas><min_part_hours>
    2. 添加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目录中,所有需要使用ringserver进程会每15秒(默认值)检查一遍ring文件的修改时间mtime,如果发现和内存中的不一致,则重新加载ring文件到内存中去。

      举例说明

      现在再增加一台存储节点node4并作为zone5,使用相同权重的devcie。那么每个存储节点上的partition数是52428.8。需要从每台存储节点上随机地移除13107.2partition到收集列表,然后再重新分配这些parttionnode4上。当有partitionreplica被重分配时,重分配的时间将被记录。在RingBuilder使用min_part_hours来限制在规定时间内,同一个partition不会被移动两次。

      由于收集用来重新分配partition是基于随机rebalacne进程并不能一次就可以完美地重平衡ring。为了达到一个较为平衡的ringrebalacne进程被重复执行直到接近完美(小于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.gzcontainer.ring.gzobject.ring.gz到集群的各节点的/etc/swift目录下。这样我们就完成了Ring的重平衡(rebalance)。

  • 相关阅读:
    Linux内核RPC请求过程
    二分图
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 文本加密
    Java蓝桥杯 算法提高 九宫格
    Java蓝桥杯 算法提高 九宫格
  • 原文地址:https://www.cnblogs.com/yuxc/p/2568584.html
Copyright © 2011-2022 走看看