2019独角兽企业重金招聘Python工程师标准>>>

PG 的状态机和peering过程

首先来解释下什么是pg peering过程?

当最初建立PG之后,那么需要同步这个pg上所有osd中的pg状态。在这个同步状态的过程叫做peering过程。同样当启动osd的时候,这个osd上所有的pg都要进行peering过程,同步pg的状态。peering过程结束后进入pg的Active状态,如果需要进行数据恢复则进行数据的恢复工作。

那么从PG的创建或者扫描开始,PG就开始设置了自己的初始状态,到最后的完全同步,这期间使用一个叫做state_machine的机制进行标记和处理,然后加上事件机制进行通信。最后达到active+clean。

下面是一个pg的所有状态,pg的状态管理全部都交给一个叫做recoverymachine的成员来管理,pg的所有的状态是一个类似树形的结构,每个状态可能存在子状态,子状态还可能存在子状态如下图。

pg的状态变化是一套状态机,根据不同的状态接收到不同的事件进行相互的转化。

一、PG状态变化的时机:

a.创建pg后,会经过一系列的PG的状态变化,由Initial最后演化成Active+clean状态。

b.就是osd启动后,会进行PG扫描,扫描后会重新在本osd上建立PG,然后在经过一系列的pg状态变化,最后达到clean状态。

c.当其他osd启动后,如果和本osd处于同一个PG内,会收到pg成员变化事件,处理该事件则本osd上的pg状态也会重新被设置,再次经历状态变化,最后达到平衡的clean状态。

二、pg的状态演化过程

下面经过一个pg状态变化的过程说起,这个过程叫做PG的peering过程。peering的过程其实就是pg状态从初始状态然后到active+clean的变化过程。一个osd启动之后,上面的pg开始工作,状态为initial,这时进行比对所有osd上的pglog和pg_info,对pg的所有信息进行同步,选举primary osd和replica osd,peering过程结束,然后把peering的结果交给recovering,有recovering过程进行数据的恢复工作(如下图)。primary osd与replica osd经过一系列的状态事件的交互,最后达到active状态。

来看看这些事件,貌似很多,但是结合流程去看就简单的多了。

三、pg状态变化实例讲解

3.1 pg状态的管理结构:

1)pg在创建或者扫描时都会重新的把pg的结构创建起来,上一节在pg创建的时候已经说了,由monitor 会发送事件给osd,osd会处理事件,并且完成pg的创建工作。这里和故障恢复有密不可分的关系,下一节讲述数据的故障恢复。

2)创建pg的时候 会初始化一个叫做recovery_state的成员,该成员就是用来控制pg的状态变化和处理事件的机制。recover_state中存在一个成员叫做recovery_machie,该成员继承了boost::statechart::state_machine状态机,该状态机 就是用来处理状态变化的。

pg 与state_machine的关系如下图。

该途中表明了几个数据结构之间的关系。

3.2 数据的pg状态变化过程

3.2.1  NULL -> initial

1).来看一下申请PG的时候 对PG结构的初始化。在PG进行初始化的时候就对recoverystate(this)。

2075:recoverystate的构造函数。

2078:对于machine进行初始化。这时初始化machine的状态为Initial状态。

3.2.2  initial  -> reset -> Started

2).创建PG之后,就要对PG的发送一系列的事件了,首先是创建事件,调取函数handle_create()。在handle_create中主要发送了两个事件。

5758:handle_create()处理函数。

5761:申请一个 Initialize d的事件evt。

5762:本端的recoverystate处理该事件。handle_event中调用machine. process_event ()。交由状态机进行处理。当状态为Initial的machine遇见Initialize事件会转化状态为reset状态。因为在initial状态里定义了 ,如果收到了Initialize事件则将状态转化为reset。

1567:定义了如果在Initial状态的时候,收到了Initialize事件,则转化为Reset状态。

目前是已经为Reset的状态了。带着这个状态再回到handle_create中。

5763:这里定义了第二个事件 ActMap 的evt2.

5764:通过recoverystate.handle_event()再次交给machine。但是这时machine的状态已经变成了Reset了,由Reset状态开始处理Actmap事件。在reset的事件处理函数中boost::statechart::result PG::RecoveryState::Reset::react(const ActMap&),最后将状态转化为了Started。transit< Started >()。然后来看Started状态,转化成该状态后又继续处理状态,在定义Started的时候默认设置了一个子状态start。

3.2.3 Started(start) ->Started( primary(Peering(GetInfo)))

3).来看一下当进入start时是怎么来处理的。

6010:开始处理进入start状态后的处理。

6016:找到对应处理的PG。

6017:如果当前的osd在本pg里是 primary。

6020:向本状态发送事件MakePrimary()事件。

6022:如果当前的osd在本pg里是replica。

6025:向本状态发送事件MakeStray。

4).接下来看看start状态如何来处理MakePrimary和MakeStray的事件吧,下面来看。

1653:如果接受到MakePrimary事件,则将状态start转化为Primary状态。

1654:如果接受到Makestray事件,则将状态start转化为stray状态。

接下来按着Primary osd的流程走。在进入Primary状态之后,在Primary状态存在一个子状态叫做Peering状态。并且Peering也同样存在一个子状态叫做GetInfo。在GetInfo的函数PG::RecoveryState::GetInfo::GetInfo()中做了哪些事情。

7375:创建当前pg的OSD集合。为数据的恢复做准备。下一节数据恢复时会讲述。

7379:发送请求到所有的副本osd中,请求pg_info信息,发送事件MQuery& query,query的类型是pg_query_t::INFO 。然后发送的请求都会记录在peer_info_request队列中。

7381:如果想其他的osd发送的查询pg_info事件,那一定会添加到peer_info_request队列中,所以这里就不为空,然后就结束了。此时状态就到这里,目前是GetInfo的状态。等待replica osd获取pg_info结束后,再将结果通过事件发送给primary osd。

3.2.4   GetInfo->GetLog

5).当primary osd接到事件MNotifyRec& infoevt,然后对该事件展开处理。在GetInfo的状态下处理该事件,在处理该事件的时候会对拉取的pginfo进行处理,最后如果所有的副本都成功的将信息返回了,则会本端再次发起事件post_event(GotInfo());当GetInfo状态收到事件GotInfo(),则会转换状态为GetLog。现在交给了GetLog状态来继续处理,在进入GetLog中,做了如下的操作。

7621:这里要进行选择acting。包括了选择auth_osd、primary选择,副本选择(计算backfill osd,recover osd)。

7635:判断auth 是不是正在处理的本osd上,如果是自己的话,那自己本身就是最全的log,所以不需要拉取log。

7637:因为不用拉取其他osd上的log,所以这里直接发送Gotlog事件,说明不需要拉取log,可以进入下一个状态了。

7673:由于自己本事auth osd,所以不是最全的log,所以要从其他osd上拉取log,这里准备事件g_query_t::LOG,发送到目标auth osd上拉取。

3.2.4   GetLog->GetMissing

6).本端使用handle_pg_query 处理g_query_t::LOG,将其封装成为MOSDPGLog消息,该消息发送到目标auth osd后,有auth osd解封消息,并且构造PG::MLogRec事件,发送给auth_osd处理,在auth_osd上形成MQuery& query 交给pg的state_machine处理,处理该事件,pg->fulfill_log(),获取本地log,然后通过消息MOSDPGLog发还给primary osd。这时primary 接到auth_osd发送过来的消息,并且消息携带auth_log的信息。在primary解析成为MLogRec 信息。这时primary osd的状态为GetLog,开始处理MLogRec 事件。直接出发post_event(GotLog())事件,当GetLog接收到Gotlog事件的时候,先要合并proc_master_log(),然后转换状态为GetMissing状态。

GetMissing的处理,在GetMissing中开始拉取所有副本的log信息,发送事件,等待所有的副本将自己的log和missing准备好发送给primary osd。这时primary osd处于GetMissing状态处理MLogRec事件,处理时proc_replica_log(),合并副本的log。

7974:当接受的log事件时候,将peer_missing_requested 队列中对应osd的计数删除。这个队列方便统计哪些osd没有及时的反馈消息。

7975:接收事件后,开始处理事件,proc_replica_log()合并副本的INFO,log,missing等信息。

7978:判断是否需要更新up_thru。

7983:如果需要更新up_thru。则发送NeedupThru事件。

7989:如果不需要更新up_thru,则发送Activate()事件。

3.2.6 GetMissing->Active(Activating)

7). 假设这里发送了Activate()事件,GetMissing状态会对Activate事件直接将状态转化为Active状态,在进入Active后会调用PG::activate的处理。在Activete的处理中有两件事儿.。a.准备事务的回调准备工作,申请注册C_PG_ActivateCommitted。b.准备想其他的osd发送合并后的log,将权威的log封装成MOSDPGLog,发送给副本,然后提交事务。

这时其他osd副本接收到MOSDPGLog事件,将解释为本地的MLogRec,副本osd的pg状态为stray,接收到MLogRec事件后。主要做的有三件事儿:a.合并接收到的log到本地log中,b.准备发送事件Activate,c.转化到状态ReplicaActive。最后由ReplicaActive状态处理事件Activate。这时同样会调用PG::activate()处理。这里主要准备了两件事儿,1.准备申请注册事务的回调处理函数C_PG_ActivateCommitted,2.准备进行数据恢复时的各种状态设置。完成后提交事务操作,等待事务完成。

目前,有两件事儿需要说明一下,primary osd 提交了事务等待C_PG_ActivateCommitted处理,replica osd 同样提交了事务等待C_PG_ActivateCommitted处理。接下来就来看看这个里边做了哪些工作。

primary osd处理完成后,提交事务回调进入_activate_committed中,

2109:如果这时判断本osd是主osd。

2117:判断是不是所有的osd都返回了提交了结果。

2119:如果是primary osd,并且所有的replica都提交了结果,则进行all_activated_and_committed()处理。

2125:如果不是primary osd,而是replica osd这时就要告诉primary osd,我已经处理好了,发送消息 MOSDPGInfo。

8). 当primary osd接收到MOSDPGInfo消息,解析为MInfoRec事件,这时primary osd的状态为active,接收MInfoRec开始处理。

6998:当向一个osd发送MOSDPGLog后,会在对应osd的序号添加到peer_active的队列中,当osd反馈消息MOSDPGInfo后,会将osd的序号添加到actingbackfill队列中。这里判断是不是所有的osd都处理完成了事务。

7000:如果所有的osd都完成了事务的处理,接下来进入all_activated_and_committed处理中。在all_activated_and_committed中主要是要发送事件通知PG的状态,通知告知已经是AllReplicasActivated事件。

3.2.7  Active(Activating)-> WaitLocalRecoveryReserved->WaitRemoteRecoveryReserved-> Active(recovering)

active接受到AllReplicasActivated事件后,开始处理,这其中主要调用pg-> on_activate ()函数。由于PG是由ReplicatedPG子类继承的,所以这里调用ReplicatedPG::on_activate 进行处理。

9079:判断是否需要进行recovery数据的恢复。

9082:如果需要进行数据恢复,则发送事件DoRecovery()事件。

9085:判断是否需要进行backfill数据恢复。

9088:如果需要进行backfill数据恢复,则需要发送事件RequestBackfill()事件。

9091:即不需要recovery 也不需要backfill 等操作,则发送事件AllReplicasRecovered事件。

9). 假设这里需要进行数据的恢复,这时发送了DoRecovery事件。activ状态接受到事件DoRecovery后进入子状态WaitLocalRecoveryReserved。该状态是active的子状态,仍让处于active状态中。在WaitLocalRecoveryReserved中会进行reserver处理并且发送LocalRecoveryReserved事件,WaitLocalRecoveryReserved接受到该事件后将转化为WaitRemoteRecoveryReserved状态。进入该状态后发RemoteRecoveryReserved事件,处理该事件时再次发送事件AllRemotesReserved,状态转化为Recovering。

6651:进入recovering时要进行的处理。

6658:清除PG的state中的PG_STATE_RECOVERY_WAIT。

6659:设置PG的state 中的 PG_STATE_RECOVERING。

6660:准备将pg 交给osd的recovery线程处理,进行数据恢复,这里是先添加到recovery_wq,然后等待线程处理队列中的pg数据恢复请求。

3.2.8 recovering->recoverd->clean

10). 该队列是由osd->recovery_wq 来实现的,而不是OSDService-> recovery_wq。

该队列的处理线程直接调用函数OSD::do_recovery()进行处理。在其中主要使用pg-> start_recovery_ops进行处理,在start_recovery_ops中判断这个pg已经数据恢复完成的时候。

代码能进行到这里说明已经PG的数据恢复完成。具体的数据恢复过程,后面的章节会讲述。

9510:这时检测状态是不是正在进行数据恢复状态是否为PG_STATE_RECOVERING。

9512:清除状态PG_STATE_RECOVERING。

9513:判断是不是要进行backfill处理?

9522:如果不需要进行backfill处理,这时代表所有的数据恢复都完成了,则发送事件AllReplicasRecovered。

11). 这时recovering状态的pg接收到AllReplicasRecovered事件,则将pg的状态转化为Recovered状态。这时将会再次发送GoClean()事件。PG接收到GoClean()事件,将转化为clean状态。

最后的PG状态就是Active+clean的状态。clean是Active的一个子状态。最终完成了PG的所有状态变换。

转载于:https://my.oschina.net/u/2460844/blog/537511

ceph的数据存储之路(7) -----PG 的状态机和peering过程相关推荐

  1. ceph的数据存储之路(6) -----pg的创建

    2019独角兽企业重金招聘Python工程师标准>>> PG 的创建过程 PG的创建是由monitor节点发起,形成请求message发送给osd,在osd上创建pg. 一.moni ...

  2. ceph的数据存储之路(4) ----- rbd client 端的数据请求处理

    2016-11-01更新 start:--------------------------------------------------------------------------------- ...

  3. ceph的数据存储之路(10) -----ceph对象存储的ls命令实现及思考

    2019独角兽企业重金招聘Python工程师标准>>> 更新:2016-10-19--------------------------------------- 前面更新的内容可能略 ...

  4. ceph存储 PG的状态机 源码分析

    文章目录 PG 的状态机和peering过程 1. PG 状态机变化的时机 2. pg的状态演化过程 3. pg状态变化实例讲解 3.1 pg状态的管理结构 3.2 数据的pg状态变化过程 3.2.1 ...

  5. numpy序列预处理dna序列_合成生物学快讯2019年第12期:基于DNA的分子数字数据存储...

    本文由中国科学院上海生命科学信息中心 战略情报团队供稿 基于DNA的分子数字数据存储:现状与挑战 编者按:美国华盛顿大学和微软研究院的研究人员2019年8月在Nature杂志发文,对基于DNA的分子数 ...

  6. FlashDB嵌入式数据库之TSDB数据存储解析

    一.驱动层:SFUD(Serial Flash Universal Driver) 是一款开源的串行 SPI Flash 通用驱动库 二.中间层:FAL(FLASH ABSTRACTION LAYER ...

  7. 我的全栈之路-C语言基础之数据存储

    我的全栈之路-C语言基础之数据存储 我的全栈之路 2.1 计算机的计算单位 2.1.1 容量单位 2.1.2 速度单位 2.2 计算机底层为什么只能识别二进制 2.3 进制 2.3.1 进制概述 2. ...

  8. pg数据库表存放在哪里_超详细的PG数据存储结构--逻辑结构和物理存储总结,值得收藏...

    概述 今天主要讲讲PG的数据结构,PG数据存储结构分为:逻辑结构和物理存储. 其中逻辑存储结构是内部的组织和管理数据的方式.物理存储结构是操作系统中组织和管理数据的方式.逻辑存储结构适用于不同的操作系 ...

  9. alin的学习之路:C语言篇(二)(指针注意事项,数据存储方式,位运算)

    @TOC(指针注意事项,数据存储方式,位运算) 1.空指针和野指针 不要操作野指针和空指针 空指针: 不要去操作空指针,对空指针指向的内存赋值等操作 void test01() {char* p = ...

  10. 关于数据存储引擎结构,没有比这篇更详细的

    摘要:常见存储算法结构涵盖:哈希存储,B .B+.B*树存储,LSM树存储引擎,R树,倒排索引,矩阵存储,对象与块,图结构存储等等. 介绍 在存储系统的设计中,存储引擎属于底层数据结构,直接决定了存储 ...

最新文章

  1. 线上接口经常超时,我用线程池+ FutureTask解决了,YYDS
  2. lsm tree java_LSM-tree 基本原理及应用
  3. Android SearchView 搜索框
  4. jzoj3801-[NOIP2014模拟8.23]骰子【数学期望】
  5. poj 2528_2
  6. 【bzoj1010-toy】斜率优化入门模板
  7. Windows Server 2008 R2终端服务器远程授权激活
  8. Django模板层:模板继承 extends标签和block标签,csrf_token标签
  9. Android EditText 常见问题总结
  10. 工欲善其事必先利其器——dreamweaver
  11. xpath获取标签的属性值_爬虫必备技能之网页解析库:xpath用法和实战
  12. Spring中注册Bean的方式有哪些?
  13. hadoop安装教程(一次填完所有的坑)
  14. 嵌入式培训经验分享——网络编程项目实战(在线电子词典)
  15. IIS无法启动计算机上的服务W3SVC如何修复、万维网发布服务(w3svc)已停止解决办法
  16. 将PC端固定布局页面改成移动端流体布局。
  17. 今晚8点,dotnet课堂全新起航,张善友/陈计节/刘腾飞我们一起来聊聊abp的故事...
  18. 阿里云商标注册怎么样?附上申请步骤流程
  19. 程序三大流程:顺序结构、选择结构、循环结构
  20. 服务器打不QQ显示00001,QQ登陆不了显示00001,什么意思

热门文章

  1. SVN文件夹图标显示不正常的解决办法
  2. Eureka微服务之服务核心动作
  3. Deepin 20版 安装教程(Vmware)
  4. 2d unity 多物体 射线_Unity3D 之射线检测
  5. NB-IOT紧急按钮
  6. GitHub生成token
  7. Win7系统怎么开启远程桌面?Win7远程桌面怎么用
  8. excel数据正在计算机,excel数据太多表格太卡-急!Excel数据量大,电脑卡死?
  9. python统计闰年的个数_python 闰年数
  10. ios10前台收到推送_APP在前台收到推送消息时也会弹出提醒?