OpenStack_Swift源代码分析——创建Ring及加入�设备源代码算法具体分析
1 创建Ring 代码具体分析
在OpenStack_Swift——Ring组织架构中我们具体分析了Ring的具体工作过程,以下就Ring中添加�设备,删除设备,已经又一次平衡的实现过程作具体的介绍。
首先看RingBuilder类
def __init__(self, part_power, replicas, min_part_hours):
#why 最大 2**32
if part_power > 32:
raise ValueError("part_power must be at most 32 (was %d)"
% (part_power,))
if replicas < 1:
raise ValueError("replicas must be at least 1 (was %.6f)"
% (replicas,))
if min_part_hours < 0:
raise ValueError("min_part_hours must be non-negative (was %d)"
% (min_part_hours,)) self.part_power = part_power
self.replicas = replicas
self.min_part_hours = min_part_hours
self.parts = 2 ** self.part_power #分区数量即虚拟节点数量
self.devs = [] #用来存放设备的加入�的设备都会加入到devs里
self.devs_changed = False
self.version = 0
self._last_part_moves_epoch = None
self._last_part_moves = None self._last_part_gather_start = 0
self._remove_devs = []
self._ring = None
当中devs里面没一个dev含有的属性为: dev = {'weight': 100.0, 'zone': 0, 'ip': '127.0.0.1', 'region': 0, 'parts': 0, 'id': 0, 'meta': 'some meta data', 'device': 'sda1', 'parts_wanted': 96, 'port': 6000}
当中part_wanted 是在加入�设备后设备须要的虚拟节点数,parts为设备已经被分配的虚拟节点。
在swift-ring-builder object.builder create 18 3 1
会调用Command类的create方法,详细看此方法:
def create(self):
"""
swift-ring-builder object.builder create 18 3 1
swift-ring-builder <builder_file> create <part_power> <replicas>
<min_part_hours>
Creates <builder_file> with 2^<part_power> partitions and <replicas>.
<min_part_hours> is number of hours to restrict(限制) moving a partition more
than once(不止一次).
"""
if len(argv) < 6:
print Commands.create.__doc__.strip()
exit(EXIT_ERROR)
builder = RingBuilder(int(argv[3]), float(argv[4]), int(argv[5]))
backup_dir = pathjoin(dirname(argv[1]), 'backups')
try:
mkdir(backup_dir)
except OSError as err:
if err.errno != EEXIST:
raise
builder.save(pathjoin(backup_dir, '%d.' % time() + basename(argv[1])))
builder.save(argv[1]) #序列化
exit(EXIT_SUCCESS)
在第一次创建时,首先会推断/etc/swift下是否有object.builder文件,没有须要创建此文件,并依据命令中个的 18 3 1 来实例化RingBuilder,最后将builder序列化。
2 为Ring加入�设备
创建了.builder文件后,就须要加入�设备,以下为加入�一个设备的命令:swift-ring-builder object.builder add z2-127.0.0.1:6020/sdb2 100
当中 add 指明为加入�设备 z2 为zone2,127.0.0.1:6020/sdb2为设备ip地址,绑定的port以及设备中存储文件的磁盘,100为设备的权重
以下看加入�设备的详细实现:
这种方法在main方法中药推断/etc/swift下是否有object.builder文件,在第一步create中我们已经创建了此文件,如今仅仅须要将他反序列化回来并用存的数据来实例化RingBuilder类,然后调用Commands类的add方法:
def add(self):
"""
swift-ring-builder <builder_file> add
[r<region>]z<zone>-<ip>:<port>[R<r_ip>:<r_port>]/<device_name>_<meta>
<weight>
[[r<region>]z<zone>-<ip>:<port>[R<r_ip>:<r_port>]/<device_name>_<meta>
<weight>] ... Where <r_ip> and <r_port> are replication ip and port. or swift-ring-builder <builder_file> add
[--region <region>] --zone <zone> --ip <ip> --port <port>
--replication-ip <r_ip> --replication-port <r_port>
--device <device_name> --meta <meta> --weight <weight> Adds devices to the ring with the given information. No partitions will be
assigned to the new device until after running 'rebalance'. This is so you
can make multiple device changes and rebalance them all just once.
"""
if len(argv) < 5 or len(argv) % 2 != 1:
print Commands.add.__doc__.strip()
exit(EXIT_ERROR) for new_dev in _parse_add_values(argv[3:]):
for dev in builder.devs:
if dev is None:
continue
if dev['ip'] == new_dev['ip'] and \
dev['port'] == new_dev['port'] and \
dev['device'] == new_dev['device']:
print 'Device %d already uses %s:%d/%s.' % \
(dev['id'], dev['ip'], dev['port'], dev['device'])
print "The on-disk ring builder is unchanged.\n"
exit(EXIT_ERROR)
dev_id = builder.add_dev(new_dev) #调用RingBuilder类的add_dev方法
print('Device %s with %s weight got id %s' %
(format_device(new_dev), new_dev['weight'], dev_id)) builder.save(argv[1])
exit(EXIT_SUCCESS)
将新加入�的设备会加入到devs[]中,当中会调用add_dev,以下看此方法的详细实现
def add_dev(self, dev):
"""
Add a device to the ring. This device dict should have a minimum of the
following keys: ====== ===============================================================
id unique integer identifier amongst devices. Defaults to the next
id if the 'id' key is not provided in the dict
weight a float of the relative weight of this device as compared to
others; this indicates how many partitions the builder will try
to assign to this device
region integer indicating which region the device is in
zone integer indicating which zone the device is in; a given
partition will not be assigned to multiple devices within the
same (region, zone) pair if there is any alternative
ip the ip address of the device
port the tcp port of the device
device the device's name on disk (sdb1, for example)
meta general use 'extra' field; for example: the online date, the
hardware description
====== =============================================================== .. note::
This will not rebalance the ring immediately as you may want to
make multiple changes for a single rebalance. :param dev: device dict :returns: id of device
dev = {'weight': 100.0, 'zone': 0, 'ip': '127.0.0.1', 'region': 0, 'parts': 0, 'id': 0, 'meta': 'some meta data', 'device': 'sda1', 'parts_wanted': 96, 'port': 6000}
"""
if 'id' not in dev:
dev['id'] = 0
if self.devs:
dev['id'] = max(d['id'] for d in self.devs if d) + 1
if dev['id'] < len(self.devs) and self.devs[dev['id']] is not None:
raise exceptions.DuplicateDeviceError(
'Duplicate device id: %d' % dev['id'])
# Add holes to self.devs to ensure self.devs[dev['id']] will be the dev
while dev['id'] >= len(self.devs):
self.devs.append(None)
dev['weight'] = float(dev['weight'])
dev['parts'] = 0
self.devs[dev['id']] = dev
self._set_parts_wanted() #设置part_wanted
self.devs_changed = True
self.version += 1
return dev['id']
此方法主要是获得weight,并为设备dev中的id赋值,以及part_wanted赋值。当中part_wanted值的计算为:
((self.parts * self.replicas / sum(d['weight'] for d in self._iter_devs())) * dev['weight']) - dev['parts']
parts=2**power(此处在create方法中的18) replicas为备份数,此处为3
即part_wanted=((虚拟节点数*备份数/全部已加入�的节点的weight和)*当前设备的weight)-已被分配给此设备的虚拟节点数
至此 创建Ring和为Ring加入�设备解说完毕,再完毕这两个步骤后,就须要平衡环,并为replica2part2dev(备份到分区到设备的映射)赋值,平衡算法是Ring 的核心算法,在下一篇文章中详细解说。
因为本人水平有限,文中难免出现理解错误,敬请指正、交流,谢谢!
OpenStack_Swift源代码分析——创建Ring及加入�设备源代码算法具体分析的更多相关文章
- Openck_Swift源代码分析——添加、删除设备时算法详细的实现过程
1 初始加入设备后.上传Object的详细流程 前几篇博客中,我们讲到环的基本原理即详细的实现过程,加入我们在初始创建Ring是执行例如以下几条命令: •swift-ring-builder obj ...
- 线程系列1--Java创建线程的几种方式及源码分析
线程--创建线程的几种方式及源码分析 开始整理下线程的知识,感觉这块一直是盲区,工作中这些东西一直没有实际使用过,感觉也只是停留在初步的认识.前段时间一个内推的面试被问到,感觉一脸懵逼.面试官说,我的 ...
- Linux内核分析-创建新进程的过程
分析Linux内核创建一个新进程的过程 task_struct结构体分析 struct task_struct{ volatile long state; //进程的状态 unsigned long ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- 基于binlog来分析mysql的行记录修改情况(python脚本分析)
最近写完mysql flashback,突然发现还有有这种使用场景:有些情况下,可能会统计在某个时间段内,MySQL修改了多少数据量?发生了多少事务?主要是哪些表格发生变动?变动的数量是怎 ...
- 背景建模技术(二):BgsLibrary的框架、背景建模的37种算法性能分析、背景建模技术的挑战
背景建模技术(二):BgsLibrary的框架.背景建模的37种算法性能分析.背景建模技术的挑战 1.基于MFC的BgsLibrary软件下载 下载地址:http://download.csdn.ne ...
- 从flink-example分析flink组件(1)WordCount batch实战及源码分析
上一章<windows下flink示例程序的执行> 简单介绍了一下flink在windows下如何通过flink-webui运行已经打包完成的示例程序(jar),那么我们为什么要使用fli ...
随机推荐
- PS制作独特火焰立体文字
效果图中的文字部分并不复杂,为简单的立体字,用图层样式及手工复制就可以做好.火焰部分稍微有点复杂,用动感及火焰素材叠加,然后再加上火花及炫光等渲染出动感效果即可.最终效果 素材下载:本教程中需要用到的 ...
- mysql Partition(分区)初探
mysql Partition(分区)初探 表数据量大的时候一般都考虑水平拆分,即所谓的sharding.不过mysql本身具有分区功能,可以实现一定程度 的水平切分. mysql是具有MERG ...
- Python还是很重要的,不能丢。学习IF和WHILE
number = 23 guess = int(input('Enter an interger : ')) if guess == number: print('Congratulations, y ...
- android系统如何自适应屏幕大小
1.屏幕相关概念 1.1分辨率 是指屏幕上有横竖各有多少个像素 1.2屏幕尺寸 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 android将屏幕大小分为四个级别 ...
- 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)
The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...
- CAS单点登录配置[5]:测试与总结
终于要结束了... 测试 1 我们同时打开Tomcat6和Tomcat7,如果报错请修改. 打 开浏览器,输入http://fighting.com/Client1,进入CAS登录界面,这里我们先输入 ...
- [置顶] 【Git入门之一】Git是神马?
1.Git是神马? 一个开源的分布式版本控制系统,可以有效的高速的控制管理各种从小到大的项目版本.他的作者就是大名鼎鼎的Linux系统创始人Linus. 2.分布式又是神马? 先看看集中式.简单说来, ...
- ctagst简单应用,将Vim改造:Ctags,Taglist,Cscope,OmniCppComplete,SuperTab,Winmanager,NERDTree,MiniBufExplorer,vimrc
vim + ctags $ ctags #给同一个目录下的所有文件建立tags 这时在tags文件所在的目录下打开源文件阅读,vim就会自动调用tags文件.如果tags文件不在当前目录下,能在命令模 ...
- hadoop2.2编程:序列化
测试序列化后的长度 提示:需要用到的类,以及继承关系如下: 1.java.lang.Object |__ java.io.OutputStream |__ java.io.ByteArrayOutpu ...
- Base64上传图片
#region 上传图片 [HttpPost]/// <summary>/// 上传文件 jpg图片/// </summary>/// <param name=" ...