gpdb是中央控制節點式的架構,在一個 greenplum 叢集中,有一個 master 節點和多個 segment 節點。master 是中央控制節點,segment 是資料存放節點。所有的segment節點平等,均由master管理。架構如下圖:
greenplum架構圖
當gp master出現問題的時候,可以通過外部的ha監控子產品發現并激活備庫,standby master 正常後删除原來的 master 進行重建備庫。
當有segment被标記為’d’後,master将不會對其做處理,gp執行個體的啟動(重新開機)也會将其忽略。這個時候,整個gp叢集是處于有風險的狀況中:
切過去的mirror壓力增大(需要做change tracking);
節點單點,可靠性風險加大。
這個時候需要及時地對segment進行修複。
gp提供了一系列的控制腳本用于對gp進行操作,其中用于修複segment的是gprecoverseg。使用方式比較簡單,有限的幾個主要參數如下:
-i
主要參數,用于指定一個配置檔案,該配置檔案描述了需要修複的segment和修複後的目的位置。
-f
可選項,指定後,gprecoverseg會将”-i”中指定的或标記”d”的執行個體删除,并從活着的mirror複制一個完整一份到目标位置。
-r
當fts發現有primary當機并進行主備切換,在gprecoverseg修複後,擔當primary的mirror角色并不會立即切換回來,就會導緻部分主機上活躍的segment過多進而引起性能瓶頸。是以需要恢複segment原先的角色,稱為re-balance。
舉個使用的例子:
下面是一個正常的執行個體,
選擇一個kill之後(如3012這個端口的執行個體),執行gprecoverseg,如下:
這個時候連接配接這個執行個體去擷取資訊是失敗的,失敗的原因後面再說。這個時候失敗後會重試5次,當再一次嘗試的時候發現了不同:
會發現,少了一個segment的指令,而這個segment正是剛才kill的segment。繼續往下看執行結果,gprecoverseg執行了下面的內容:
這個執行個體為什麼單獨檢查呢?而且這個時候如果失敗,則會直接退出無法繼續執行。
在一系列的檢查之後,先更新catalog中的操作記錄表:
之後即調用指令進行資料的恢複:
最後再啟動segment,并更新catalog:
這樣即是一個完整的gprecoverseg過程。執行過後,對應的primary和mirror會進入”r”狀态,表示正在做資料同步。
下面來看其中的詳細步驟和原理。
上面的例子中,遺留了幾個問題:
在gprecoverseg過程中,第一次擷取segment狀态是不對的;
第二次擷取segment資訊,比第一次少了一條;
單獨檢查了“-h host2 -p 3013”這個執行個體。
這幾個問題在了解了原理後就很容易了解了。想要了解原理,可以先看下執行的步驟。從代碼看來,其大緻的步驟如下:
gp的腳本用了較多的環境變量,且不同的腳本、不同的地方略有不同。如gprecoverseg用的就是master_data_directory,從master_data_directory指定的目錄中得到master相關的資訊(如port)以進行相關操作。
gprecoverseg的參數,最重要的莫過于”-i”了,其指定了需要做修複的segment,并且可以指定到不同的主機上,例如:
具體執行不再贅述。
調用gp_primarymirror,向活着的segment發送消息,以判斷segment目前的狀态。這是非常重要的一步,也是遇到問題最多的一步,經常會出現問題”unable to connect to database”。事實上,造成這個失敗的原因有很多,比較多的是:
其對應的primary(mirror)也當機;
其對應的primary的狀态不對,如已經有gprecoverseg在進行(或執行失敗,狀态出問題等)。
在做這一步的時候,是依賴gp_segment_configuration中的資料的,即會首先從gp master上擷取相應的資料,與下一步中的描述基本相同。
如果這個segment被标記為”d”,那麼是不會向該segment發起狀态資訊請求。
而如果對應的primary/mirror都當機了,他們的狀态不會同時為”d”(有可能都為”u”,比如同時異常的時候,fts不會更新他們)。是以對标記為”u”實際已經當機的segment連接配接擷取狀态資訊的時候,則會報錯。這個時候就不是gprecoverseg所能處理的問題了,隻能重新開機整個執行個體。
回到前面的問題。第一次執行失敗即因為segment的狀态尚未更新;第二次執行少了一個segment,即狀态被更新為”d”後不進行連接配接。
在檢查完所有狀态為”u”的segment連接配接後,則會針對當機的mirror進行檢查,檢視其對應的主庫是否正常,可以用于修複資料,即是第三個問題的答案。如:
或者這樣
正常情況下,當mirror出現問題,primary發現後會進入changetracking的狀态。在這個狀态裡,primary會記錄下切換狀态時間點之後的變更,用于當mirror恢複時進行資料同步,而不用每次都做一次全量。
包括ip、port、role、status、資料目錄、臨時空間等,如下:
ip/port/role/status/目錄/filespace等資訊,後面的mirror修複清單、臨時空間、操作對象的資訊都依賴于此。
在擷取所有的segment資訊後,會針對配置檔案、參數等相關資訊确定,包括:
segment修複對象
确定segment修複對象和資料源,即primary;需要修複的segment有可能是多個。并擷取需要修複的segment的相關資訊,包括端口、流複制端口、資料目錄、臨時空間、檔案空間等資訊,以及是否強制修複等。
主機環境
在擷取所需要修複的segment清單後,需要確定所在主機環境是可以的,包括端口占用、目錄的占用等有可能沖突的地方。
如果沒有指定主機,則會在已有的主機中選擇一個。
修複的步驟是:
關閉當機的mirror,并清理shared memory
确定需要修複的segment已經被标記為”d”
如有需要,則進行删除,如”-f”的情況
打包壓縮、複制資料到目标位置
關閉sigint、sig_ign,更新中繼資料庫,打開sigint、sig_ign
以上步驟後,即可實作對segment的本地(in-place)或跨機修複。
當修複完segment之後,原先因為primary當機而切到mirror上的segment并不會主動切回來,這個時候有可能出現性能傾斜而影響性能,是以需要做”re-balance”,執行:
執行該指令會将role切換為preferred_role,保證整個叢集的角色平衡而不緻于部分主機primay更多引起性能瓶頸。