Swift中的一致性哈希算法(补充)


    总结一下,理解算法时的几个问题,搞懂这些基本上就算理解Swift rebalnce的算法了。

Swift如何保证文件的随机存储和保持系统中的平衡性?

例如有4dev(编号 01,  2,  3218次幂262144虚节点,我们都知道builder和ring中存储了一个数据结构_replica2part2dev,它表明了partition到replica到dev的映射关系,即某个文件的某个副本存储到哪个dev上,如下图

系统要做的是根据策略来生成随机的分布,让一个文件的三个副本可以存储到3个不同的dev上去。



builder文件到底存的什么?

其实builder文件里存储了一个字典型的数据结构,其中包含了整个系统所有的重要的数据。

                'part_power': self.part_power,

                'replicas': self.replicas,

                'min_part_hours': self.min_part_hours,

                'parts': self.parts,

                'devs': self.devs,

                'devs_changed': self.devs_changed,

                'version': self.version,

                '_replica2part2dev': self._replica2part2dev,

                '_last_part_moves_epoch': self._last_part_moves_epoch,

                '_last_part_moves': self._last_part_moves,

                '_last_part_gather_start': self._last_part_gather_start,

                '_remove_devs': self._remove_devs

ring文件里到底存了什么?

ring文件只存储记录part分布的数据

 

def serialize_v1(self, file_obj):

        # Write out new-style serialization magic and version:

        file_obj.write(struct.pack('!4sH', 'R1NG', 1))

        ring = self.to_dict()

        json_text = json.dumps(

            {'devs': ring['devs'], 'part_shift': ring['part_shift'],

             'replica_count': len(ring['replica2part2dev_id'])})

        json_len = len(json_text)

        file_obj.write(struct.pack('!I', json_len))

        file_obj.write(json_text)

        for part2dev_id in ring['replica2part2dev_id']:

            file_obj.write(part2dev_id.tostring())

文件对应的part如何生成

一个上传文件的请求,proxy会来决定哪个node(dev)来存储这个文件和它的副本。然后向选好的dev发送请求。

例如 admin账户,向test容器中,上传一个名字为update.c的文件。会根据/admin/test/update.c + 设置的HASH_PATH_SUFFIX 生成一个md5 的值 然后解析成一个数字 例如35564 这个就是part,然后在_replica2part2dev 中查找它的三个replica所在的dev  ,然后向这三个dev发送请求。

def get_nodes(self, account, container=None, obj=None):

        key = hash_path(account, container, obj, raw_digest=True)

#md5(/account/contianer/obj + HASH_PATH_SUFFIX).digest()

        if time() > self._rtime:

            self._reload()

        part = struct.unpack_from('>I', key)[0] >> self._part_shift

        seen_ids = set()

        return part, [self._devs[r[part]] for r in self._replica2part2dev_id

                      if not (r[part] in seen_ids or seen_ids.add(r[part]))]

sort_key

dev对应的sort_key影响它分配的方式,系统生成一个字符串,它分成三段,进行排序,第一段为dev_want,第二段随机数,第三段dev_id,系统根据这个三段排序,然后查找最想want的dev

   

def _sort_key_for(self, dev):

        # The maximum value of self.parts is 2^32, which is 9 hex

        # digits wide (0x100000000). Using a width of 16 here gives us

        # plenty of breathing room; you'd need more than 2^28 replicas

        # to overflow it.

        # Since the sort key is a string and therefore an ascii sort applies,

        # the maximum_parts_wanted + parts_wanted is used so negative

        # parts_wanted end up sorted above positive parts_wanted.

        return '%016x.%04x.%04x' % (

            (self.parts * self.replicas) + dev['parts_wanted'],

            randint(0, 0xffff),

            dev['id'])

parts_wanted = (sum_part/sum_weight )*dev_weith-dev_pars

系统设置的part减去已经分配的part 生成想要得到的part



转载于:https://my.oschina.net/zhouxingxing/blog/83749

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值