Swift中所谓的Ring就是基于一致性Hash所构建的环。Ring包括以下三种重要的数据结构。

一 相关数据结构说明

1 设备表

设备表中的每一项都对应一个Device,其中记录了该Device的具体位置信息,包括Device ID,所在Region,Zone,IP地址以及端口号,以及用户为该Device定义的权重(Weight)等。Device容量大小不一时,可以通过Weight值保证Partition均匀分布,容量较大的Device拥有拥有更大的权重,也容纳更多的Partition。

比如,一个1T大小的Device有100的权重而一个2T大小的Device有200的权重。

2 设备查询表(Device Lookup Table)

存储Partition的各个副本(默认为3个)与具体Device的映射关系。

从列的维度分析:5,12,1可以这样理解,0号partition的3个副本分别存放在5号、12号、1号设备上。

从行的维度分析:5,0,1,4,12表示针对第1个副本,0,1,2,3,4这5个partition分别存放在5号,0号,1号,4号,12号设备上。

从表格的维度分析:每个表格的信息是设备表中的Device编号,根据这个编号,可以去设备表中检索到该Device的具体连接信息(Device ID、IP以及端口号等信息)。

3 Partition移位值(Partition Shift Value):表示在Hash之后将Object名字二进制移位的位数。

swift 本地数据库 swift 数据结构_swift 本地数据库


二 相关数据结构解释

为了减少由于增加、减少节点所带来的数据迁移,Swift在对象和存储节点的映射之间增加了Partition的概念,使得对象到存储节点的映射过程,变成了由对象到Partition再到存储节点的映射。

Partition的个数一旦确定,在整个运行过程中不会改变的,所以对象到Partition的映射是不会改变的。在增加或者减少节点的情况下,通过改变Partition到存储节点的映射来完成数据的迁移。

对象到Partition这层的映射是通过Hash函数以及二进制移位操作,即这里的Partition Shift Value完成的,Partition到存储节点的映射是通过设备查询表完成的。

三 代码解读

Swift接收到用户请求中包含了数据的路径名称,比如对于Object的请求,可能为“GET account_name/container_name/object_name”,Swift需要将这个路径映射到Partition上:

#swift/common/ring/ring.py
class Ring(object):
    def get_part(self, account, container=None, obj=None):
        """
        获取account/container/object对应的partition
        """
        #首先计算Hash值
        key = hash_path(account, container, obj, raw_digest=True)
        if time() > self._rtime:
            self._reload()
        #然后位移得到partition
        part = struct.unpack_from('>I', key)[0] >> self._part_shift
        return part