1. 程式人生 > >MySQL Group Replication 技術點

MySQL Group Replication 技術點

mysql group replication,組複製,提供了多寫(multi-master update)的特性,增強了原有的mysql的高可用架構。mysql group replication基於mysql外掛架構實現,本身就是一個mysql外掛。

提供的特性:

  • 多寫,寫衝突檢測
  • 良好的擴充套件能力,可動態增刪節點,組成員自動管理
  • 組內高可用
  • 確保組內資料最終一致性【重要】(通過分散式協議和分散式recovery機制保證)

1. 架構

gr_plugin_blocks

組複製基於mysql外掛架構實現,本身作為一個mysql外掛而存在。如上圖所示,藍色和綠色兩部分表示組複製架構。

組複製依賴mysql server主模組(上圖灰色部分)以及mysql的複製架構,包括binary log caches、binary log applier模組、GTID、relay log模組、replication applier threads(組複製distributed recovery第一個階段會使用這些執行緒)和performance_schema(用於儲存監控組複製的狀態資訊)。

上圖架構中各個模組的作用簡單介紹如下:

  • APIs

API層提供了組複製與上層mysql server互動的介面。上層(mysql server)會主動通知下層(組複製)根據它的狀態去做對應的動作,包括server的啟動、恢復、接受連線、提交事務等等。組複製根據這些介面呼叫做出對應的響應動作。

  • Capture、Applier、Recovery

組複製中的三個核心模組,當上層API發生呼叫,將根據呼叫型別路由到下面這三個模組執行相應的邏輯。Capture模組負責追蹤事務執行的上下文資訊;Applier模組負責將遠端事務載入到本地執行;Recovery模組管理組內節點的recovery。

  • Replication Protocol Logics

Replicaiton Protocol Logics模組實現了replication協議的邏輯,邏輯功能包括: 處理衝突檢測、接收並傳播事務到組內去執行。

  • Group Communication System API

提供狀態機(Replication State Machine)的高層抽象API,以此分離與下層協議實現的邏輯。

  • Group Communication Engine

根據上層的狀態機API的抽象,這一層主要提供Paxos協議變種的核心實現。

2. Group

mysql_group_replication_dia

一個Group由若干個mysql節點組成,每個Group有自己的唯一命名來標識,格式為UUID。Group內的mysql節點資料保持一致。一個組可以動態增加和刪除節點。

組成員管理自動化。新增一個節點到一個組裡面,這個節點會自動同步自身資料跟組內其他節點保持一致。保持同步會利用Asynchronous MySQL replication。當一個節點從一個組裡移除,將自動更改group的配置,以讓其他節點知道這個節點的移除。

3. Multi Primary

組複製有兩種執行模式: (1) Single-Primary Mode 和 (2) Multi-Primary Mode,其中Single-Primary Mode表示一個組裡面只有一個節點用於寫,而Multi-Primary Mode下組內所有節點都可以參與寫,事務的提交可以在組內的任意一個節點進行。

multi_primary_example

看起來Multi-Primary模式好像很屌!但是,這個模式下目前存在挺多的使用限制:

3.1 併發寫衝突

Multi-Primary模式下,對於事務的提交,需要組內所有節點進行通訊,共同決定事務是否可以提交。高併發模式下有可能出現分散式提交衝突——不同的節點併發提交的事務操作了同一行資料。group replication提供的樂觀的解決方案是——先提交(時間序靠前的)的事務,能夠正確被提交,而後面提交的事務,將會失敗。

multi_primary_update_conflict

官方建議,避免併發寫衝突的最好的做法是將這些會產生衝突的寫事務放到同一個節點上進行提交。

3.2 併發DDL

MySQL目前不支援事務型別的DDL,也就是說DDL操作不是一個原子操作,在Multi-Primary模式下,DDL操作併發地在多個節點執行,很有可能產生資料不一致的情況。因此,官方提醒,在Multi-Primary下DDL操作最好在同一個節點上執行。

如果執行在Single-Primary模式下,就沒有上面所提到的限制了。

4. Distributed Recovery

當一個新節點(被叫作joiner)加入一個group,需要從group裡面其他節點同步狀態。這個新節點從其他節點獲取這些落後資料,並接受新提交的事務,最終保持與group內其他節點資料一致的這個過程,稱為distributed recovery(DR)。DR過程分為兩個階段:

4.1 階段1

Joiner選擇group裡面的一個節點作為複製源(這個節點被稱作donor),基於原有的非同步複製技術進行recovery。這個過程會建立從donor到joiner的replication channel,joiner不斷接收從donor端傳送的binary log,apply到自身。於此同時,joiner還會監聽並快取group裡面自從它加入以來產生的新事務。階段1結束後,將會關閉之前建立在donor和joiner之間的replication channel。

donor有可能在這個階段掛掉,此時joiner將自動選擇叢集內的其他一個存活節點作為donor,繼續之前的recovery。這個過程無需人為干預。

4.2 階段2

階段2,joiner執行在階段1快取佇列裡的新事務(直到快取佇列為空),然後將joiner的狀態標記為online,表示這個節點的資料已經跟其他節點保持一致,可以被正常訪問。

只有online的節點才能正常接收使用者請求。

4.3 Recovering From a Point-in-time

這裡有個問題: 在階段1,joiner怎麼知道它在什麼時候會完成所有缺失資料的recovery,單單依靠GTID機制是不夠的(依靠GTID機制只能讓joiner知道它是否少了這部分資料)。這個時候,需要有另外一個機制,來代表一個時間點——這個時間點能夠標識階段1的結束,也就是說在這個時間點上,joiner已經完成了從donor上所有缺失資料的recovery,接下來可以進入階段2了。

這個機制,就是binary log view change markers,在階段1傳輸binary log流中,會帶上view change markers。那麼joiner在接受到binary log的時候,就可以利用這些標識來判斷那個時間點的到來。

4.4 View and View Changes

在解釋view change markers之前,需要介紹view change markers關聯的概念: ViewView Changes

  • View

一個Group裡面所有節點在某個時間點上達成的配置,對外表示為一個View。

  • View Changes

View Changes指引起Group配置發生變化的事件,比如新增節點,刪除節點。

每個View有一個唯一標識(View Identifier)進行標識。當發生View Changes時,就會生成這樣一個唯一標識來表示這個新的View。

View changes產生的view ids作為新節點與donor同步資料的臨界點。View change事件對應到binary log裡面是一個新binary log event的實現——view change log event。在這個view change log event裡面攜帶了view id。

假設在之前的multi-primary部署示例完成後,我們通過登陸S2執行以下語句檢索到view change event log:

mysql > show binlog events\G;

可以看到如下view change event log:

*************************** 9. row ***************************
   Log_name: binlog.000001
        Pos: 742
 Event_type: View_change
  Server_id: 1
End_log_pos: 881
       Info: view_id=14817781596395401:1

4.5 Distributed Recovery Example

接下來我們分析一個例子: 一個新節點加入一個group的過程

4.5.1 Begin: Stable Group

一開始group有3個節點S1、S2、S3,整個group處於穩定狀態

gr_recovery_1

4.5.2 View Change: Member Joins

接下來新節點S4準備加入group,引起view changes(VC4)。所有的節點都會在快取佇列裡面快取view change event log到佇列。同時,新節點S4會選擇group裡面的某個節點作為donor。

所有的節點都要快取view change event log到佇列,因為這個event log之前有可能還存在著未apply的event log,這些event log是屬於old view的。

gr_recovery_2

4.5.3 State Transfer: Catching Up

當S4選擇好donor後,就會建立與donor的replication channel,基於async replication機制從donor上同步狀態進行recovery,直到S4遇到期望的view change marker為止。

gr_recovery_3

於此同時,S4也會不斷地接受group裡面下發的新提交事務,快取到佇列裡面。

gr_recovery_4

4.5.4 Finish: Caught Up

當S4遇到期望的view change marker(根據view change event log 判斷)以後,與donor之間的replication channel將會被關閉,這個時候,就會從之前的快取佇列裡面取新的事務(圖示中的T22)進行apply,直到快取佇列為空,然後就可以將S4的狀態標記為online,這就是階段2的主要動作。

注意,階段2的執行週期是不確定的,取決於系統的負載情況,因為在階段2期間,有可能系統不斷產生新的事務。系統的負載越高,產生的事務會越多,那麼階段2經歷的時間自然也就越長了。

gr_recovery_5