Openck_Swift源码分析——增加、删除设备时算法具体的实现过程

1 初始添加设备后、上传Object的具体流程

前几篇博客中,我们讲到环的基本原理即具体的实现过程,加入我们在初始创建Ring是执行如下几条命令:

?swift-ring-builder object.builder create 5 3 1

?swift-ring-builder object.builder add z1-127.0.0.1:6010/sdb1 100

?swift-ring-builder object.builder add z2-127.0.0.1:6020/sdb2 100

?swift-ring-builder object.builder add z3-127.0.0.1:6030/sdb3 100

?swift-ring-builder object.builder add z4-127.0.0.1:6040/sdb4 100

swift-ring-builder object.builder rebalance

上面几条命令语句中,黑色的为初始创建Ring,绿色部分为向Ring中添加设备,四个设备分别位于不同的Zone中,且权重是一样的。添加完设备后需要对Ring进行平衡,以便得到replica2part2dev_id。其中关于create add rebalance方法的具体实现过程请参考OpenStack_Swift源码分析——Ring的rebalance算法源代码详细分析OpenStack_Swift源码分析——创建Ring及添加设备源码算法详细分析两篇文章。

平衡后得到的replica2part2dev_id 如下图所示:

图1 初始平衡Ring后 replica2part2dev_id的映射

上图中第一行为分配编号(在create时输入的power为5,故为32个分区),三个list分别代表了三个备份。上图中一个设备又同时对应多个不同的分区,如下图所示:

图 2 设备反映射分区

结合图1和图2,一个设备对应读个分区,这些在存储数据时,能更好的解决平衡性问题。

在得到了replica2part2dev_id 后,现在我们向集群中存入一个对象。其过程如下所示:

图3 存入一个对象

向集群中存入对象的流程如下图所示:

图4  存入对象的流程

存入对象时,首先根据对象的名称(account/container/object),计算其hash值,的到hash值后,取hash值的前四字节,且向右移动32-power位得到当前object对应的分区号,如15,得到分区号后,利用分区号到replica2part2dev_id中找到此分区对应的三个设备的Id,如图1所示的设备ID为3 1 4 。根据这三个设备的ID,到devs中找到具体的设备,根据设备的IP,port已经存储文件的磁盘所挂载的文件夹,如sdb1。将数据存如设备中,数据存入设备中的目录结构为srv/node/sdb1/objects/15/hash值后位/hash/.data文件;其中15为分区号,所以文件右移动得到的分区号为15的在该设备中都存入此文件夹下。

2 增加设备

假如系统运行了一段时间后,因需要存储更多的对象,现需要对系统进行扩展,如下,我们现在增加一个设备:

swift-ring-builder object.builder add z1-127.0.0.1:6050/sdb5 100

在zone1里面右增加了一个设备,其权重仍为100,添加设备后,每一个设备的part_wanted值会变化,之前被分配的设备,会因新添加设备后其会超出其先需要的part_wanted故需要把他们收集回来,分配给新增加的设备,收集的具体算法实现请参见我前几篇博客,里面有详细的介绍。添加设备后,重新对Ring进行平衡,平衡后replica2part2dev_id如下图所示:

                  图5 添加设备后映射的变化

如上图(图中红线上部分为添加设备后的新映射,红线下部分为没添加设备前的映射)所示,再添加了设备后,被收集的分区是从第一个备份(第一行)先开始收集,如果第一个备份都被收集完,则再从第二个备份开始收集。现在只添加了一个设备,不会收集到第二个备份的分区,故如绿框中所示后两个分区中分区所对应的设备ID都没有变化。图中小红框和小绿框中所示的,第一次平衡和新加入一个设备后平衡的分区15所对应的设备Id 其中一个由3变为5。这种变化,数据的一致性是如何保证的呢?为保证因重新移动平衡而带来的分区和设备映射的变动,Replicator在保证数据的一致性方面起到至关重要的作用。因为Replicator这个守护进程在每一个服务器上都有运行,故对于设备3
,它首先根据分区文件夹的名字获得分区号然后利用Ring类对外通过的方法,得到此分区对应的设备,此时它发现新的replica2part2dev_id中没有了其本身,这时它会把文件夹名为15及其下的所有文件都删除。而对于分区15所对应是新设备5,它是如何得到这些文件的呢?我们知道,Swift数据的同步是基于推送模式的,也就是4和3 会把其文件夹下的文件推送给设备5。比如设备4,其Replicator,在获得分区15所对应的设备后,和3对比,发现没有文件不同,故不推送数据,而发现5下没有分区15所对应的内容,故其需要将自己分区15所对应的文件推送给它,设备3也是同样的原理。

3 删除设备

集群又运行了一些时间,其中有些设备,因为运行时间较长,设备老化,现需要将其从集群删掉,Swift设备的删除,不是直接的物理删除,先将其weight设置为0,当其weight变为0后,其他的设备的part_wanted就好变大,故在rebalnace时需要先把设备1(加入删除设备1)所对应的分区都收回,然后再重新分配给其他分区。这个过程中replica2part2dev_id变化如下:

图6 删除设备后replica2part2dev_id的变化

如图6所示(绿线上方为删除设备后的新映射,绿线和和蓝线之间为没有删除设备前添加设备后的分区映射,最底下为起初的映射)设备1所对应的所有分区都被收集了。而每一个分区所对应的新的设备都会经过其他两个设备,来将他们文件下的对象推送给新映射的设备。

Openck_Swift源码分析——增加、删除设备时算法具体的实现过程

时间: 2024-10-06 13:48:05

Openck_Swift源码分析——增加、删除设备时算法具体的实现过程的相关文章

leveldb源码分析--插入删除流程

由于网络上对leveldb的分析文章都比较丰富,一些基础概念和模型都介绍得比较多,所以本人就不再对这些概念以专门的篇幅进行介绍,本文主要以代码流程注释的方式. 首先我们从db的插入和删除开始以对整个体系有一个感性的认识,首先看插入: Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { WriteBatch batch; //leveldb中不管单个插入还是多个插入都是以Wri

【Spring源码分析】非懒加载的Bean实例化过程(下篇)

doCreateBean方法 上文[Spring源码分析]非懒加载的Bean实例化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireCapableBeanFactory的doCreateBean方法代码: 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[]

Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe

Nouveau源码分析(三) 向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照. 对于匹配的设备,PCI模块就调用对应的probe函数,也就是nouveau_drm_probe. // /drivers/gpu/drm/nouveau/nouveau_drm.c 281 static int nouveau_drm_probe(struct pci_dev *pdev, 282 const struct

Nouveau源码分析(六):NVIDIA设备初始化之nouveau_drm_load (3)

Nouveau源码分析(六) 上一篇中我们暂时忽略了两个函数,第一个是用于创建nvif_device对应的nouveau_object的ctor函数: // /drivers/gpu/drm/nouveau/core/engine/device/base.c 488 static struct nouveau_ofuncs 489 nouveau_devobj_ofuncs = { 490 .ctor = nouveau_devobj_ctor, 491 .dtor = nouveau_devo

Nouveau源码分析(四):NVIDIA设备初始化之nouveau_drm_load (1)

Nouveau源码分析(四) probe函数成功返回之后,DRM模块就会调用struct drm_driver的load函数,对应nouveau的nouveau_drm_load. 这个函数虽然看起来不是特别长,但每一个调用的函数展开后就会变得非常长了! // /drivers/gpu/drm/nouveau/nouveau_drm.c 364 static int 365 nouveau_drm_load(struct drm_device *dev, unsigned long flags)

Nouveau源码分析(五):NVIDIA设备初始化之nouveau_drm_load (2)

Nouveau源码分析(五) 接着上一篇来,先把nouveau_drm_load再贴出一遍来吧: // /drivers/gpu/drm/nouveau/nouveau_drm.c 364 static int 365 nouveau_drm_load(struct drm_device *dev, unsigned long flags) 366 { 367 struct pci_dev *pdev = dev->pdev; 368 struct nouveau_drm *drm; 369 i

【Spring源码分析系列】启动component-scan类扫描加载过程

原文地址:http://blog.csdn.net/xieyuooo/article/details/9089441/ 在spring 3.0以上大家都一般会配置一个Servelet,如下所示: 1 <servlet> 2 <servlet-name>spring</servlet-name> 3 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas

Appium Server源码分析之作为Bootstrap客户端

Appium Server拥有两个主要的功能: 它是个http服务器,它专门接收从客户端通过基于http的REST协议发送过来的命令 他是bootstrap客户端:它接收到客户端的命令后,需要想办法把这些命令发送给目标安卓机器的bootstrap来驱动uiatuomator来做事情 通过上一篇文章<Appium Server 源码分析之启动运行Express http服务器>我们分析了Appium Server是如何作为一个http服务器进行工作的.那么今天我们就要分析第二点,Appium S

cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)

cocos2d-x源码总目录 http://blog.csdn.net/u011225840/article/details/31743129 源码来自2.x,转载请注明 1.继承结构 首先来看下CCTableView的继承结构 从继承结构上看,CCTableView是一种CCScrollView,所以为了研究CCTableView的源码,清先去了解CCScrollView的源码http://blog.csdn.net/u011225840/article/details/30033501. 其