openstack swift的副本存放位置解析
来源:互联网 发布:淘宝铁十字勋章价格 编辑:程序博客网 时间:2024/04/24 09:18
我们知道在swift中的副本一般是3个,但是对于这三个副本放在哪里?或者存储位置是怎么选择的呢?这段代码是在/common/ring/ring.py文件中的,现在我们来看看这段代码
def get_more_nodes(self, part): """ 根据虚节点生成虚节点对应的其他节点 Generator to get extra nodes for a partition for hinted handoff. 预备节点尽量不在主节点上,这会考虑到设备权重,还有就是预备节点原有的顺序 The handoff nodes will try to be in zones other than the primary zones, will take into account the device weights, and will usually keep the same sequences of handoffs even with ring changes. :param part: partition to get handoff nodes for :returns: generator of node dicts See :func:`get_nodes` for a description of the node dicts. """ if time() > self._rtime: self._reload() primary_nodes = self._get_part_nodes(part)#获得主节点 used = set(d['id'] for d in primary_nodes)#used就是使用的主节点的设备ID same_regions = set(d['region'] for d in primary_nodes)#主节点所在的区域 same_zones = set((d['region'], d['zone']) for d in primary_nodes)#主节点所在的区域 same_ip_ports = set((d['region'], d['zone'], d['ip'], d['port']) for d in primary_nodes)#主节点所使用的其他信息 parts = len(self._replica2part2dev_id[0]) start = struct.unpack_from( '>I', md5(str(part)).digest())[0] >> self._part_shift#获得根据虚节点获得其实位置 inc = int(parts / 65536) or 1 #步长默认是1, # Multiple loops for execution speed; the checks and bookkeeping get # simpler as you go along #hit_all_regions获得主节点的区域和该存储的区域个数是否相同的标记 hit_all_regions = len(same_regions) == self._num_regions #xrange([start], stop[, step]) #chain依次枚举所给的两个数组,我们可以认为handoff_part是副本节点的计算出的二次虚节点号 for handoff_part in chain(xrange(start, parts, inc), xrange(inc - ((parts - start) % inc), start, inc)): if hit_all_regions: # At this point, there are no regions left untouched, so we # can stop looking. break for part2dev_id in self._replica2part2dev_id: if handoff_part < len(part2dev_id): dev_id = part2dev_id[handoff_part] dev = self._devs[dev_id] region = dev['region'] if dev_id not in used and region not in same_regions:#如果不是同一设备同时得到的这个设备ID所在的region,还没有使用,则考虑使用该设备 yield dev used.add(dev_id) same_regions.add(region)#正在使用的区域增减 zone = dev['zone'] ip_port = (region, zone, dev['ip'], dev['port']) same_zones.add((region, zone)) same_ip_ports.add(ip_port) if len(same_regions) == self._num_regions: hit_all_regions = True break #经过上一步,如果使用的zones已经达到上限则不进行操作 hit_all_zones = len(same_zones) == self._num_zones for handoff_part in chain(xrange(start, parts, inc), xrange(inc - ((parts - start) % inc), start, inc)): if hit_all_zones: # Much like we stopped looking for fresh regions before, we # can now stop looking for fresh zones; there are no more. break for part2dev_id in self._replica2part2dev_id: if handoff_part < len(part2dev_id): dev_id = part2dev_id[handoff_part] dev = self._devs[dev_id] zone = (dev['region'], dev['zone']) if dev_id not in used and zone not in same_zones:#如果不是同一设备同时得到的这个设备ID所在的zone,还没有使用,则考虑使用该设备 yield dev used.add(dev_id) same_zones.add(zone) ip_port = zone + (dev['ip'], dev['port']) same_ip_ports.add(ip_port) if len(same_zones) == self._num_zones: hit_all_zones = True break hit_all_ip_ports = len(same_ip_ports) == self._num_ip_ports for handoff_part in chain(xrange(start, parts, inc), xrange(inc - ((parts - start) % inc), start, inc)): if hit_all_ip_ports: # We've exhausted the pool of unused backends, so stop # looking. break for part2dev_id in self._replica2part2dev_id: if handoff_part < len(part2dev_id): dev_id = part2dev_id[handoff_part] dev = self._devs[dev_id] ip_port = (dev['region'], dev['zone'], dev['ip'], dev['port']) if dev_id not in used and ip_port not in same_ip_ports:#如果不是同一设备同时得到的这个设备ID的IP 或者port有一个不一样,还没有使用,则考虑使用该设备 yield dev used.add(dev_id) same_ip_ports.add(ip_port) if len(same_ip_ports) == self._num_ip_ports: hit_all_ip_ports = True break hit_all_devs = len(used) == self._num_devs for handoff_part in chain(xrange(start, parts, inc), xrange(inc - ((parts - start) % inc), start, inc)): if hit_all_devs: # We've used every device we have, so let's stop looking for # unused devices now. break for part2dev_id in self._replica2part2dev_id: if handoff_part < len(part2dev_id): dev_id = part2dev_id[handoff_part] if dev_id not in used: #如果不是同一设备还没有使用,则考虑使用该设备 yield self._devs[dev_id] used.add(dev_id) if len(used) == self._num_devs: hit_all_devs = True break
这样我们就找到了备份数据的选择策略,
1.首先根据原有的虚节点号计算出新的虚节点号
2.遍历得到的虚节点数组中的虚节点号m
3.检查m所在的region是否被该数据使用,没有则添加
4.检查m所在的zone是否被该数据使用,没有则添加
5.检查m所在的IP和PORT是否完全一直,不完全一致则添加
6.检查m所在的设备和该数据所使用的设备是否是同一设备,不是,则添加
7.添加失败,m变换成下一个虚节点,转到步骤3
8.添加成功,可以作为备份节点
而新的虚节点的计算过程是这样的
parts = len(self._replica2part2dev_id[0])start = struct.unpack_from( '>I', md5(str(part)).digest())[0] >> self._part_shift#获得根据虚节点获得其实位置inc = int(parts / 65536) or 1 #步长默认是1,parts则是虚节点的数量?,根据虚节点号计算出MD5值,之后进行移位,得到start,inc则是计算得到的parts对65536的商,如果为0则为1
这样就得到了start parts inc,一个集合是以start作为起点 parts作为终点 步长是inc 得到的中间序列
另一个集合的起点是(inc-((parts-start)%inc)) 终点是start 步长是inc的中间序列
这样我们就可以得到该数据可以存放的节点信息了!!!
0 0
- openstack swift的副本存放位置解析
- HDFS的副本存放策略
- NameNode决定副本的存放的机制
- 容器中存放的均为副本
- 【Swift】数据的存放
- .Jar存放的位置
- 数据存放的位置
- 变量的存放位置
- openstack 通过service 查看每个service的存放log的位置
- Hadoop_HDFS文件读写代码流程解析和副本存放机制
- openstack swift ring文件解析
- HDFS副本存放策略
- HDFS副本存放策略
- skype 的聊天记录存放位置
- Oracle11gR2 sqldeveloper 存放的位置
- chrome Extensions的存放位置
- outlook邮件存放的位置
- 修改AVD的存放位置
- windows 怎样查看计算机本地安装的证书
- Android Intent Action 大全
- Xamarin破解后出现闪退处理
- ADB常用的几个命令
- Objective-C基础教程2(继承和复合)
- openstack swift的副本存放位置解析
- 谈谈iOS Animation
- ASP 连接数据库并对数据库的一些常用操作
- 网站设计的表单提交用POST方式还是GET方式?
- 10本经典JavaScript书籍分层次推荐+打包下载
- 给SQL Server存储过程,传送数组参数的变通办法
- nyoj题目98:成绩转换
- 羊年祝福语(羊年祝福大全)
- VBreport编写步骤