日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

發(fā)布時間:2023/11/27 生活经验 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ceph存储 PG的状态机 源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

      • PG 的狀態(tài)機和peering過程
        • 1. PG 狀態(tài)機變化的時機
        • 2. pg的狀態(tài)演化過程
        • 3. pg狀態(tài)變化實例講解
          • 3.1 pg狀態(tài)的管理結(jié)構(gòu)
          • 3.2 數(shù)據(jù)的pg狀態(tài)變化過程
            • 3.2.1 NULL -> initial
            • 3.2.2 initial -> reset -> Started
            • 3.2.3 Started(start) ->Started( primary(Peering(GetInfo)))
            • 3.2.4 GetInfo->GetLog
            • 3.2.5 GetLog->GetMissing
            • 3.2.6 GetMissing->Active(Activating)
            • 3.2.7 Active(Activating)-> WaitLocalRecoveryReserved->WaitRemoteRecoveryReserved-> Active(recovering)
            • 3.2.8 recovering->recoverd->clean

PG 的狀態(tài)機和peering過程

首先來解釋下什么是pg peering過程?

當最初建立PG之后,那么需要同步這個pg上所有osd中的pg狀態(tài)。在這個同步狀態(tài)的過程叫做peering過程。同樣當啟動osd的時候,這個osd上所有的pg都要進行peering過程,同步pg的狀態(tài)。peering過程結(jié)束后進入pg的Active狀態(tài),如果需要進行數(shù)據(jù)恢復則進行數(shù)據(jù)的恢復工作。

那么從PG的創(chuàng)建或者掃描開始,PG就開始設(shè)置了自己的初始狀態(tài),到最后的完全同步,這期間使用一個叫做state_machine的機制進行標記和處理,然后加上事件機制進行通信。最后達到active+clean。

下面是一個pg的所有狀態(tài),pg的狀態(tài)管理全部都交給一個叫做recoverymachine的成員來管理,pg的所有的狀態(tài)是一個類似樹形的結(jié)構(gòu),每個狀態(tài)可能存在子狀態(tài),子狀態(tài)還可能存在子狀態(tài)如下圖

pg的狀態(tài)變化是一套狀態(tài)機,根據(jù)不同的狀態(tài)接收到不同的事件進行相互的轉(zhuǎn)化

1. PG 狀態(tài)機變化的時機

a.創(chuàng)建pg后,會經(jīng)過一系列的PG的狀態(tài)變化,由Initial最后演化成Active+clean狀態(tài)。

b.就是osd啟動后,會進行PG掃描,掃描后會重新在本osd上建立PG,然后在經(jīng)過一系列的pg狀態(tài)變化,最后達到clean狀態(tài)。

c.當其他osd啟動后,如果和本osd處于同一個PG內(nèi),會收到pg成員變化事件,處理該事件則本osd上的pg狀態(tài)也會重新被設(shè)置,再次經(jīng)歷狀態(tài)變化,最后達到平衡的clean狀態(tài)

2. pg的狀態(tài)演化過程

下面經(jīng)過一個pg狀態(tài)變化的過程說起,這個過程叫做PG的peering過程。peering的過程其實就是pg狀態(tài)從初始狀態(tài)然后到active+clean的變化過程。一個osd啟動之后,上面的pg開始工作,狀態(tài)為initial,這時進行比對所有osd上的pglog和pg_info,對pg的所有信息進行同步,選舉primary osd和replica osd,peering過程結(jié)束,然后把peering的結(jié)果交給recovering,有recovering過程進行數(shù)據(jù)的恢復工作(如下圖)。primary osd與replica osd經(jīng)過一系列的狀態(tài)事件的交互,最后達到active狀態(tài)



3. pg狀態(tài)變化實例講解

3.1 pg狀態(tài)的管理結(jié)構(gòu)
  1. pg在創(chuàng)建或者掃描時都會重新的把pg的結(jié)構(gòu)創(chuàng)建起來,上一節(jié)在pg創(chuàng)建的時候已經(jīng)說了,由monitor 會發(fā)送事件給osd,osd會處理事件,并且完成pg的創(chuàng)建工作。這里和故障恢復有密不可分的關(guān)系,下一節(jié)講述數(shù)據(jù)的故障恢復。

  2. 創(chuàng)建pg的時候會初始化一個叫做recovery_state的成員,該成員就是用來控制pg的狀態(tài)變化和處理事件的機制。recover_state中存在一個成員叫做recovery_machie,該成員繼承了boost::statechart::state_machine狀態(tài)機,該狀態(tài)機就是用來處理狀態(tài)變化的。

pg與state_machine的關(guān)系如下圖

該途中表明了幾個數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系

3.2 數(shù)據(jù)的pg狀態(tài)變化過程
3.2.1 NULL -> initial

1). 來看一下申請PG的時候 對PG結(jié)構(gòu)的初始化。在PG進行初始化的時候就對recoverystate(this)。

2075:recoverystate的構(gòu)造函數(shù)。
2078:對于machine進行初始化。這時初始化machine的狀態(tài)為Initial狀態(tài)。

3.2.2 initial -> reset -> Started

2). 創(chuàng)建PG之后,就要對PG的發(fā)送一系列的事件了,首先是創(chuàng)建事件,調(diào)取函數(shù)handle_create()。在handle_create中主要發(fā)送了兩個事件

5758:handle_create()處理函數(shù)。

5761:申請一個 Initialize d的事件evt。

5762:本端的recoverystate處理該事件。handle_event中調(diào)用machine. process_event ()。交由狀態(tài)機進行處理。當狀態(tài)為Initial的machine遇見Initialize事件會轉(zhuǎn)化狀態(tài)為reset狀態(tài)。因為在initial狀態(tài)里定義了,如果收到了Initialize事件則將狀態(tài)轉(zhuǎn)化為reset


1567:定義了如果在Initial狀態(tài)的時候,收到了Initialize事件,則轉(zhuǎn)化為Reset狀態(tài)。
目前是已經(jīng)為Reset的狀態(tài)了。帶著這個狀態(tài)再回到handle_create中

5763:這里定義了第二個事件 ActMap 的evt2.

5764:通過recoverystate.handle_event()再次交給machine。但是這時machine的狀態(tài)已經(jīng)變成了Reset了,由Reset狀態(tài)開始處理Actmap事件。在reset的事件處理函數(shù)中boost::statechart::result PG::RecoveryState::Reset::react(const ActMap&),最后將狀態(tài)轉(zhuǎn)化為了Started。transit< Started >()。然后來看Started狀態(tài),轉(zhuǎn)化成該狀態(tài)后又繼續(xù)處理狀態(tài),在定義Started的時候默認設(shè)置了一個子狀態(tài)start

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

3). 來看一下當進入start時是怎么來處理的

6010:開始處理進入start狀態(tài)后的處理。
6016:找到對應處理的PG。
6017:如果當前的osd在本pg里是 primary。
6020:向本狀態(tài)發(fā)送事件MakePrimary()事件。
6022:如果當前的osd在本pg里是replica。
6025:向本狀態(tài)發(fā)送事件MakeStray。

4). 接下來看看start狀態(tài)如何來處理MakePrimary和MakeStray的事件吧,下面來看。

1653:如果接受到MakePrimary事件,則將狀態(tài)start轉(zhuǎn)化為Primary狀態(tài)。
1654:如果接受到Makestray事件,則將狀態(tài)start轉(zhuǎn)化為stray狀態(tài)。

接下來按著Primary osd的流程走。在進入Primary狀態(tài)之后,在Primary狀態(tài)存在一個子狀態(tài)叫做Peering狀態(tài)。并且Peering也同樣存在一個子狀態(tài)叫做GetInfo。在GetInfo的函數(shù)PG::RecoveryState::GetInfo::GetInfo()中做了哪些事情。

7375:創(chuàng)建當前pg的OSD集合。為數(shù)據(jù)的恢復做準備。下一節(jié)數(shù)據(jù)恢復時會講述。

7379:發(fā)送請求到所有的副本osd中,請求pg_info信息,發(fā)送事件MQuery& query,query的類型是pg_query_t::INFO。然后發(fā)送的請求都會記錄在peer_info_request隊列中。

7381:如果想其他的osd發(fā)送的查詢pg_info事件,那一定會添加到peer_info_request隊列中,所以這里就不為空,然后就結(jié)束了。此時狀態(tài)就到這里,目前是GetInfo的狀態(tài)。等待replica osd獲取pg_info結(jié)束后,再將結(jié)果通過事件發(fā)送給primary osd。

3.2.4 GetInfo->GetLog

5). 當primary osd接到事件MNotifyRec& infoevt,然后對該事件展開處理。在GetInfo的狀態(tài)下處理該事件,在處理該事件的時候會對拉取的pginfo進行處理,最后如果所有的副本都成功的將信息返回了,則會本端再次發(fā)起事件post_event(GotInfo());當GetInfo狀態(tài)收到事件GotInfo(),則會轉(zhuǎn)換狀態(tài)為GetLog?,F(xiàn)在交給了GetLog狀態(tài)來繼續(xù)處理,在進入GetLog中,做了如下的操作


7621:這里要進行選擇acting。包括了選擇auth_osd、primary選擇,副本選擇(計算backfill osd,recover osd)。

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

7637:因為不用拉取其他osd上的log,所以這里直接發(fā)送Gotlog事件,說明不需要拉取log,可以進入下一個狀態(tài)了。

7673:由于自己本是auth osd,所以不是最全的log,所以要從其他osd上拉取log,這里準備事件g_query_t::LOG,發(fā)送到目標auth osd上拉取

3.2.5 GetLog->GetMissing

6). 本端使用handle_pg_query 處理g_query_t::LOG,將其封裝成為MOSDPGLog消息,該消息發(fā)送到目標auth osd后,有auth osd解封消息,并且構(gòu)造PG::MLogRec事件,發(fā)送給auth_osd處理,在auth_osd上形成MQuery& query 交給pg的state_machine處理,處理該事件,pg->fulfill_log(),獲取本地log,然后通過消息MOSDPGLog發(fā)還給primary osd。這時primary 接到auth_osd發(fā)送過來的消息,并且消息攜帶auth_log的信息。在primary解析成為MLogRec 信息。這時primary osd的狀態(tài)為GetLog,開始處理MLogRec 事件。直接出發(fā)post_event(GotLog())事件,當GetLog接收到Gotlog事件的時候,先要合并proc_master_log(),然后轉(zhuǎn)換狀態(tài)為GetMissing狀態(tài)。

GetMissing的處理,在GetMissing中開始拉取所有副本的log信息,發(fā)送事件,等待所有的副本將自己的log和missing準備好發(fā)送給primary osd。這時primary osd處于GetMissing狀態(tài)處理MLogRec事件,處理時proc_replica_log(),合并副本的log

7974:當接受的log事件時候,將peer_missing_requested 隊列中對應osd的計數(shù)刪除。這個隊列方便統(tǒng)計哪些osd沒有及時的反饋消息。

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

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

7983:如果需要更新up_thru。則發(fā)送NeedupThru事件。

7989:如果不需要更新up_thru,則發(fā)送Activate()事件。

3.2.6 GetMissing->Active(Activating)

7). 假設(shè)這里發(fā)送了Activate()事件,GetMissing狀態(tài)會對Activate事件直接將狀態(tài)轉(zhuǎn)化為Active狀態(tài),在進入Active后會調(diào)用PG::activate的處理。在Activete的處理中有兩件事兒.。a.準備事務的回調(diào)準備工作,申請注冊C_PG_ActivateCommitted。b.準備想其他的osd發(fā)送合并后的log,將權(quán)威的log封裝成MOSDPGLog,發(fā)送給副本,然后提交事務。

這時其他osd副本接收到MOSDPGLog事件,將解釋為本地的MLogRec,副本osd的pg狀態(tài)為stray,接收到MLogRec事件后。主要做的有三件事兒:a.合并接收到的log到本地log中,b.準備發(fā)送事件Activate,c.轉(zhuǎn)化到狀態(tài)ReplicaActive。最后由ReplicaActive狀態(tài)處理事件Activate。這時同樣會調(diào)用PG::activate()處理。這里主要準備了兩件事兒,
1.準備申請注冊事務的回調(diào)處理函數(shù)C_PG_ActivateCommitted
2.準備進行數(shù)據(jù)恢復時的各種狀態(tài)設(shè)置。完成后提交事務操作,等待事務完成。

目前,有兩件事兒需要說明一下,primary osd提交了事務等待C_PG_ActivateCommitted處理,replica osd同樣提交了事務等待C_PG_ActivateCommitted處理。接下來就來看看這個里邊做了哪些工作

primary osd處理完成后,提交事務回調(diào)進入_activate_committed中,

2109:如果這時判斷本osd是主osd。

2117:判斷是不是所有的osd都返回了提交了結(jié)果。

2119:如果是primary osd,并且所有的replica都提交了結(jié)果,則進行all_activated_and_committed()處理。

2125:如果不是primary osd,而是replica osd這時就要告訴primary osd,我已經(jīng)處理好了,發(fā)送消息 MOSDPGInfo。

8). 當primary osd接收到MOSDPGInfo消息,解析為MInfoRec事件,這時primary osd的狀態(tài)為active,接收MInfoRec開始處理。

6998:當向一個osd發(fā)送MOSDPGLog后,會在對應osd的序號添加到peer_active的隊列中,當osd反饋消息MOSDPGInfo后,會將osd的序號添加到actingbackfill隊列中。這里判斷是不是所有的osd都處理完成了事務。

7000:如果所有的osd都完成了事務的處理,接下來進入all_activated_and_committed處理中。在all_activated_and_committed中主要是要發(fā)送事件通知PG的狀態(tài),通知告知已經(jīng)是AllReplicasActivated事件

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

active接受到AllReplicasActivated事件后,開始處理,這其中主要調(diào)用pg-> on_activate ()函數(shù)。由于PG是由ReplicatedPG子類繼承的,所以這里調(diào)用ReplicatedPG::on_activate 進行處理。

9079:判斷是否需要進行recovery數(shù)據(jù)的恢復。

9082:如果需要進行數(shù)據(jù)恢復,則發(fā)送事件DoRecovery()事件。

9085:判斷是否需要進行backfill數(shù)據(jù)恢復。

9088:如果需要進行backfill數(shù)據(jù)恢復,則需要發(fā)送事件RequestBackfill()事件。

9091:即不需要recovery也不需要backfill等操作,則發(fā)送事件AllReplicasRecovered事件。

9).假設(shè)這里需要進行數(shù)據(jù)的恢復,這時發(fā)送了DoRecovery事件。activ狀態(tài)接受到事件DoRecovery后進入子狀態(tài)WaitLocalRecoveryReserved。該狀態(tài)是active的子狀態(tài),仍讓處于active狀態(tài)中。在WaitLocalRecoveryReserved中會進行reserver處理并且發(fā)送LocalRecoveryReserved事件,WaitLocalRecoveryReserved接受到該事件后將轉(zhuǎn)化為WaitRemoteRecoveryReserved狀態(tài)。進入該狀態(tài)后發(fā)RemoteRecoveryReserved事件,處理該事件時再次發(fā)送事件AllRemotesReserved,狀態(tài)轉(zhuǎn)化為Recovering。

6651:進入recovering時要進行的處理。

6658:清除PG的state中的PG_STATE_RECOVERY_WAIT。

6659:設(shè)置PG的state中的 PG_STATE_RECOVERING。

6660:準備將pg交給osd的recovery線程處理,進行數(shù)據(jù)恢復,這里是先添加到recovery_wq,然后等待線程處理隊列中的pg數(shù)據(jù)恢復請求。

3.2.8 recovering->recoverd->clean

10). 該隊列是由osd->recovery_wq 來實現(xiàn)的,而不是OSDService-> recovery_wq。

該隊列的處理線程直接調(diào)用函數(shù)OSD::do_recovery()進行處理。在其中主要使用pg-> start_recovery_ops進行處理,在start_recovery_ops中判斷這個pg已經(jīng)數(shù)據(jù)恢復完成的時候。

代碼能進行到這里說明已經(jīng)PG的數(shù)據(jù)恢復完成。

9510:這時檢測狀態(tài)是不是正在進行數(shù)據(jù)恢復狀態(tài)是否為PG_STATE_RECOVERING。

9512:清除狀態(tài)PG_STATE_RECOVERING。

9513:判斷是不是要進行backfill處理?

9522:如果不需要進行backfill處理,這時代表所有的數(shù)據(jù)恢復都完成了,則發(fā)送事件AllReplicasRecovered。

11). 這時recovering狀態(tài)的pg接收到AllReplicasRecovered事件,則將pg的狀態(tài)轉(zhuǎn)化為Recovered狀態(tài)。這時將會再次發(fā)送GoClean()事件。PG接收到GoClean()事件,將轉(zhuǎn)化為clean狀態(tài)

最后的PG狀態(tài)就是Active+clean的狀態(tài)。clean是Active的一個子狀態(tài)。最終完成了PG的所有狀態(tài)變換

總結(jié)

以上是生活随笔為你收集整理的ceph存储 PG的状态机 源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。