副本结构Swift 1.8.0(Grizzly) 中region的理解

近来研究副本结构,稍微总结一下,以后继续补充:

    在Swift 1.8.0(Grizzly)的新特性中有这么一条:Added support for a region tier above zones,即swift可以答应开发者将zones组织成一个组停止管理了,这个组就是region。

    这两天在看Swift G版Ring部分的源码的时候,也发现device字典中增长了region属性,因此决定细心的理解一下这个层次观点。

    首先推荐两篇文章,我对region的理解从这两篇文章中获益颇多:

    第一篇是Swift的主要贡献者、region特性的贡献者SwiftStack的文章:A Globally Distributed OpenStack Swift Cluster;

    第二篇不止介绍了region的观点,更将region层次下的proxy server等工作流程停止了具体描述。(这篇需要翻墙-。-)

 

    The Ring without Multi-regions

    标准的Swift ring是一个答应你将存储设备划分为buckets或者zones的数据结构。在介绍包含regions观点的Ring之前,让我们先来回想一下没有添加region观点版本的Ring结构:

    在Essex版本中,Ring builder严格的保障同一个对象的不同的副本分布在不同的zones中,否则Ring的创建过程没法完成。因此,Swift developer就必须在集群中部署至少和副本数一样多的zones以保障Ring可以被胜利创建。

    在Folsom版本中,Ring文件的结构被停止了改动,并重新定义了ring balancing的算法,从而极大的提高了Ring创建的效率。在这个版本中,原本严格的保障副本分布在不同zones中的策略被替换成了另一种更为灵活的算法,这个新的算法将zones、nodes、devices组织,从而形成tiers的结构停止分配。

 

    The Ring with Multi-tiers

    以下代码是swift 1.7.6(Folsom)中结构tiers结构的代码(common.ring.utils.py)。

def tiers_for_dev(dev):
    """
    Returns a tuple of tiers for a given device in ascending order by
    length.

    :returns: tuple of tiers
    """
    t1 = dev['zone']
    t2 = "{ip}:{port}".format(ip=dev.get('ip'), port=dev.get('port'))
    t3 = dev['id']

    return ((t1,),
            (t1, t2),
            (t1, t2, t3))
Folsom版本的ring balancer将同一个对象的副本分配到尽可能远的位置(as-far-as-possible or as-unique-as-possible)。当然,最完善的计划是将这些副本放置到不同的zones中([zone] tier),但是如果只有一个zone可以使用时,那么就尽量将副本分配到不同的nodes中([zone ip:port] tier),相似的,当如果只有一个node可以使用时,那么就尽量将副本分配到这个节点上的不同devices([zone ip:port device] tier)。

    这种“as-unique-as-possible”的算法,具有支撑 geographically distributed cluster 的潜质(每向上一层,就增大了一个地理范围),它可以便利的将一个小的集群扩展成一个大集群。因此,我们可以通过增长另一个region tier到这个层次中实现集群的地理分布支撑。一个region本质上是一组共享雷同位置的zones,这组zones可所以一个机架,也可所以一个数据中心。

    下图是“as-unique-as-possible”策略下,不同规模Swift中副本寄存策略的示意图,其中绿色圆点代表一个副本,椭圆代表一个disk,一个立方体代表一个node...

    副本和结构

 

    The Ring with Multi-regions -> A Globally Distributed Cluster

    通过量tiers结构的Ring的介绍,region的观点就非常好理解了。

    为了创建一个global cluster,SwiftStack为swift增长了region的观点。Region扩展了Tier的层次,是一个比zone更大的区域,一组zones构成的tier是一个region。

    一个寰球的、支撑副本的集群可以通过将storage nodes部署在不同的region中停止创建。同一个region中的zones之间的延迟是绝对较低的,Proxy nodes会对距离它近的region具有亲和性(local affinity,优先拜访),并根据storage nodes所在的region采用“悲观写”的方法将数据写入近来region的storage nodes。如果需要的话,客户端可以通过选项执行一个跨区域(疏忽local affinity)的读/写操作。

    如下,为swift 1.8.0 中结构tiers结构的代码(common.ring.utils.py)。

def tiers_for_dev(dev):
    """
    Returns a tuple of tiers for a given device in ascending order by
    length.

    :returns: tuple of tiers
    """
    t1 = dev['region']
    t2 = dev['zone']
    t3 = "{ip}:{port}".format(ip=dev.get('ip'), port=dev.get('port'))
    t4 = dev['id']

    return ((t1,),
            (t1, t2),
            (t1, t2, t3),
            (t1, t2, t3, t4))
    每日一道理
冰心说道:“爱在左,同情在右,走在生命的两旁,随时撒种,随时开花,将这一径长途,点缀得香花弥漫,使穿枝拂叶的行人,踏着荆棘,不觉得痛苦,有泪可落,却不是悲凉。”
从以上代码中,我们可以清晰的看到region被增长到了最顶层的tier,并作为设备dev的一个新属性,实现为dev字典的一个新key-value对。

    默认情况下,swift集群的region为1,从而保障cluster中一定存在一个region,并用“()”表明一个region,作为tier tree的root。以下代码为tier tree的构建过程,代码的doc string将包含region层次的tier tree结构描述的非常清晰,为了便于理解,所以我就一并贴上来了。

def build_tier_tree(devices):
    """
    Construct the tier tree from the zone layout.

    The tier tree is a dictionary that maps tiers to their child tiers.
    A synthetic root node of () is generated so that there's one tree,
    not a forest.

    Example:

    region 1 -+---- zone 1 -+---- 192.168.101.1:6000 -+---- device id 0
              |             |                         |
              |             |                         +---- device id 1
              |             |                         |
              |             |                         +---- device id 2
              |             |
              |             +---- 192.168.101.2:6000 -+---- device id 3
              |                                       |
              |                                       +---- device id 4
              |                                       |
              |                                       +---- device id 5
              |
              +---- zone 2 -+---- 192.168.102.1:6000 -+---- device id 6
                            |                         |
                            |                         +---- device id 7
                            |                         |
                            |                         +---- device id 8
                            |
                            +---- 192.168.102.2:6000 -+---- device id 9
                                                      |
                                                      +---- device id 10


    region 2 -+---- zone 1 -+---- 192.168.201.1:6000 -+---- device id 12
                            |                         |
                            |                         +---- device id 13
                            |                         |
                            |                         +---- device id 14
                            |
                            +---- 192.168.201.2:6000 -+---- device id 15
                                                      |
                                                      +---- device id 16
                                                      |
                                                      +---- device id 17

    The tier tree would look like:
    {
      (): [(1,), (2,)],

      (1,): [(1, 1), (1, 2)],
      (2,): [(2, 1)],

      (1, 1): [(1, 1, 192.168.101.1:6000),
               (1, 1, 192.168.101.2:6000)],
      (1, 2): [(1, 2, 192.168.102.1:6000),
               (1, 2, 192.168.102.2:6000)],
      (2, 1): [(2, 1, 192.168.201.1:6000),
               (2, 1, 192.168.201.2:6000)],

      (1, 1, 192.168.101.1:6000): [(1, 1, 192.168.101.1:6000, 0),
                                   (1, 1, 192.168.101.1:6000, 1),
                                   (1, 1, 192.168.101.1:6000, 2)],
      (1, 1, 192.168.101.2:6000): [(1, 1, 192.168.101.2:6000, 3),
                                   (1, 1, 192.168.101.2:6000, 4),
                                   (1, 1, 192.168.101.2:6000, 5)],
      (1, 2, 192.168.102.1:6000): [(1, 2, 192.168.102.1:6000, 6),
                                   (1, 2, 192.168.102.1:6000, 7),
                                   (1, 2, 192.168.102.1:6000, 8)],
      (1, 2, 192.168.102.2:6000): [(1, 2, 192.168.102.2:6000, 9),
                                   (1, 2, 192.168.102.2:6000, 10)],
      (2, 1, 192.168.201.1:6000): [(2, 1, 192.168.201.1:6000, 12),
                                   (2, 1, 192.168.201.1:6000, 13),
                                   (2, 1, 192.168.201.1:6000, 14)],
      (2, 1, 192.168.201.2:6000): [(2, 1, 192.168.201.2:6000, 15),
                                   (2, 1, 192.168.201.2:6000, 16),
                                   (2, 1, 192.168.201.2:6000, 17)],
    }

    :devices: device dicts from which to generate the tree
    :returns: tier tree

    """
    tier2children = defaultdict(set)
    for dev in devices:
        for tier in tiers_for_dev(dev):
            if len(tier) > 1:
                tier2children[tier[0:-1]].add(tier)
            else:
                tier2children[()].add(tier)
    return tier2children
 

    更多的关于在multi-regions下swift中各个操作的算法细节,可以拜见我在文章开头处给出的两个blogs链接,其中都有非常具体、图文并茂的介绍,我就不重复造轮子啦 =D

 

文章结束给大家分享下程序员的一些笑话语录: 联想——对内高价,补贴对外倾销的伟大“民族”企业。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值