組複製MySQL Group Replication(簡稱MGR)是MySQL官方在已有的Binlog複製架構之上,基於Paxos協議實現的一種分布式複製形態。RDS MySQL叢集系列執行個體支援組複製。本文介紹組複製的優勢、技術實現原理、AliSQL對組複製穩定性的最佳化。
組複製的優勢
組複製、半同步複製、非同步複製的資料可靠性、資料一致性、全域事務一致性情況如下表所示。
特性 | 組複製 | 半同步複製 | 非同步複製 |
資料可靠性 | ★★★★★ | ★★★ | ★ |
資料一致性 | 保證主備資料一致性 | 不保證 | 不保證 |
全域事務一致性 | 支援 | 不支援 | 不支援 |
資料強可靠性
組複製的資料強可靠性來源於Paxos協議的多數派原則,即當多數派收到事務的Binlog後,事務才能在各節點提交。這保證了在多數派可用的情況下,任何節點故障都不會導致資料丟失。
例如,5個節點的叢集,3個節點收到Binlog,2個節點未收到Binlog,此時有2個節點故障:
如果故障的2個節點是收到Binlog的節點,那至少還有1個節點上有資料。
如果故障的2個節點是沒收到Binlog的節點,那至少還有3個節點上有資料。
多數派指叢集中超過半數的節點。
少數派指叢集中少於半數的節點。
資料強一致性
在組複製中,事務總是先傳輸到叢集中其他節點,然後寫入Binlog檔案,這保證無論主節點在什麼時刻發生故障,重新啟動後資料都不會比叢集選出的新主節點多。舊主節點故障重啟後,能夠自動加回叢集,拉取它缺失的Binlog,就能夠獲得最新的資料,不會導致主備節點資料不一致。
而在傳統主備複製模式中,事務是先寫入Binlog檔案,然後傳輸到備節點。這樣,如果主節點在寫入Binlog後,傳輸資料到備節點之前發生故障,重新啟動後資料就會多於備節點。如果此時備節點已經被切換成新主節點,就會出現主節點資料少於備節點,主備節點資料不一致的情況。
全域事務強一致性
組複製具備叢集的節點間的資料全域強一致讀和全域強一致寫能力,並且可根據業務需要修改group_replication_consistency參數來調整讀寫的一致性等級:
設定備節點的強一致讀能力:可以在備節點上設定Session層級的group_replication_consistency參數為BEFORE,然後執行查詢語句。此時,備節點會等到主節點上所有先於此查詢語句的事務應用完成後,再執行這條查詢語句。這樣在備節點和主節點上就會讀到一致的資料。
設定主節點的強同步寫能力:可以在主節點上設定Session層級的group_replication_consistency參數為AFTER,然後執行寫事務,這個事務會等到所有節點應用成功後,再在主節點上返回提交成功的訊息到用戶端。
組複製的部署模式
如上圖所示,組複製支援單主和多主兩種部署模式:
多主模式(Multiple Leader):
叢集中所有節點均可讀可寫。多主模式的組複製主要用於擴充執行個體的寫能力。它依賴Paxos協議的多點寫入能力,輔以行層級的衝突檢測,能夠保證所有節點收到資料的順序一致,實現多寫。
但它的嚴重缺陷是,在多數派可用的情況下,任何節點的故障都會導致叢集的抖動(短時間不可用)。
單主模式(Single Leader):
叢集中只有一個節點可以寫入資料,其他節點只能讀不能寫。單主模式的組複製依賴Paxos Single Leader實現,在擴充讀能力、提高資料可靠性的同時,保持了高可用性:
當備節點故障時,只要多數派可用,就不會影響叢集的可用性。
當主節點故障時,叢集能夠根據Paxos協議,在保證資料強一致性的情況下自主進行主備切換。
RDS MySQL提供了單主模式的組複製執行個體,並對唯讀節點做了最佳化,在保證資料的高可靠和強一致的同時,提供了更平滑的效能。
組複製的架構
如上圖所示,在MySQL的Server層和Replica層之下,組複製的架構分為三層:
組複製層(Group Replication Logic Layer):在單機MySQL的Server層之下,組複製增加了組複製層,該層通過鉤子(HOOK)與Server層相連,負責向組通訊層發送、接收並回放事務。
組通訊層(Group Communication System Layer):與XCom層共同實現組複製層與叢集的通訊。該層除了負責訊息的傳遞,還負責故障檢測和叢集成員的管理。
XCom層(Paxos Layer):基於Paxos協議實現,與組通訊層共同實現組複製層與叢集的通訊,以及訊息傳遞的全域有序性和叢集成員的角色切換。它能夠保證所有節點收到資料的順序一致,同時保證只要多數派可用,資料就不會丟失。
XCom層
Paxos協議
Paxos協議在組複製中的作用主要有以下兩點:
確保叢集中各節點收到資料的順序一致,這是多主模式實現的基礎。
確保多數派收到資料後,事務才能提交。這對資料可靠性很重要,可以保證只要多數派可用,資料就不會丟失。
在Paxos協議中,使用鎖的方式來實現節點間順序一致性,這種方式存在一定的效率問題,並且還存在著負載不均衡的問題。在工程實現過程中,MySQL的XCom層基於Paxos的變種協議,Mencius協議。這是一種使用輪詢的方法實現的Leaderless Paxos協議,能夠有效提升節點間的負載平衡。
多主模式實現原理
多主模式基於Mencius協議。如上圖所示,在Mencius協議中,叢集中每個節點都會主動和其他節點建立串連,領導一個單主的Paxos組。對於n個節點的叢集,會形成n個互不干預的Paxos組。每個組中只允許Leader節點發送資料,當多數派收到資料後,視為資料發送成功。當一個節點的用戶端收到資料時,會使用自己領導的Paxos組發出資料,這個發送動作是串列的,因此單個組內的資料順序是一致的。
多個組在發出資料時,為了保證順序性,使用輪詢處理機制。也就是說,XCom層在接收到多個Paxos組的資料後,必須按一個預先約定好的順序傳給組複製層。如上圖所示,資料必須按照 (1,1)、(1,2)、(1,3) 這樣的順序發送給組複製層。
當一個節點發現比自己的順序號靠後的資料已經完成了Paxos過程,並且自己的這個位置上沒有資料要發送時,就會廣播一個Noop,通知其他節點自己的這個順序號可以跳過。每一個節點必須等順序在自己前面的一個節點發出資料或發出Noop後才能發出資料。當某個節點故障或抖動時,它既不能發出資料又不能發出Noop,在故障恢複或節點抖動期間,就會導致後續節點的資料無法發出,叢集將完全不可用。這是多主模式的一個嚴重缺陷。
圖中(m,n)表示第n個組發出的第m條資料。例如,(2,1)表示第1個組發出的第2條資料。
單主模式實現原理
上文中提到的多主模式的缺陷可以最佳化,但無法從根源上避免。為此MySQL推出了組複製的單主模式,來解決少數派故障對叢集可用性的影響。
上圖是單主模式的XCom架構,由於只有一個節點可寫,只需啟用一個Paxos組。接收方的XCom在輪詢資料時,會自動忽略其他Paxos組。這樣,只要多數派可用,Paxos就能正常發送資料,叢集的可用性不受影響。
在單主模式下,備節點不會發送交易資料,但有時需要發送一些叢集管理資訊。備節點在發送資料時,必須向主節點請求一個發送資訊的位置,如上圖中的 <3, 1>,並使用這個位置向全叢集發送自己的資料。這種發送方式效率低、時延高,但由於叢集管理資訊發送的頻率很低,並不會對效能造成影響。
組複製層
組複製層的主要工作是向叢集發送、接收並回放事務,其在主節點和備節點上的工作原理如下:
在主節點上:當一個事務在主節點進入提交階段時,事務的Binlog會先被傳到XCom層中,發送給其他節點。當確認多數派收到事務後,會對事務進行衝突檢測,如果成功則寫入Binlog檔案並提交,如果失敗則復原事務。
在備節點上:當一個事務被多數派接收後,會由XCom層傳給組複製層,進行衝突檢測。如果成功則事務會被寫入Relay Log,隨後被Applier線程應用,如果失敗則此事務的資料會被直接丟棄。
衝突檢測
情境
組複製在以下兩種情境中,都需要將不同節點的事務在同一個節點上執行,因此需要對不同節點間的事務進行衝突檢測,以確保它們的修改沒有衝突:
多主模式下,所有寫操作都需要衝突檢測。
單主模式下,如果發生切主,並且新主節點在應用完舊主的Relay log前,就執行寫事務,也需要衝突檢測。
原理
在組複製中,使用資料行的主鍵雜湊值來進行行層級的衝突檢測。每個節點都會維護一個事務認證資訊數組,這是一個雜湊數組,它的key是資料行的雜湊值,它的value是最近修改這一行的事務的GTID與此事務在源節點提交時的gtid_executed(源節點上所有提交過的事務的gtid集合)的並集。
一個事務在源節點準備提交時,除了發送自己修改的資料到其他節點外,還會發送一個gtid 集合,這個集合是該事務提交時,源節點上的gtid executed(源節點上所有提交過的事務的gtid集合)。這個集合標識了當前事務提交前,源節點上哪些事務已經完成提交,這裡將其稱為提交集合。
同時,叢集內的所有節點(包括源節點),都會使用當前事務修改的所有資料行(下文簡稱為相關行)的雜湊值作為key,到認證資訊數組中讀取value,並將讀到的這些value合并為一個gtid集合。這個集合標識了當前事務提交前,哪些事務必須完成提交,這裡將其稱為依賴集合。
在當前事務提交或寫入Relay Log前,需要將上述兩個集合進行比較:
如果提交集合包含了依賴集合,則說明所有之前修改過相關行的事務均已提交。此時衝突檢測成功,源節點上需要將當前事務寫入Binlog 並提交,其他節點上需要將當前事務寫入Relay Log。
如果提交集合沒有包含依賴集合,則說明有之前修改過相關行的事務未提交。此時衝突檢測失敗,源節點上需要復原當前事務,其他節點上需要丟棄Relay Log。
認證資訊數組還必須及時清理無用資料,以節省記憶體空間。當一個事務在所有節點上都被執行之後,任何其他事務都不會跟它衝突了,此事務修改的所有行都可以從認證資訊數組中清理掉。在組複製中每60秒會清理一次已執行的事務的資料。
AliSQL對組複製穩定性的最佳化
組複製的穩定性在引入單主模式後有了較大的改善,但是在一些情境下,仍存在穩定性問題。當備節點的延遲較大時,會有大量的事務無法及時應用,這會導致認證資訊大量積累,會有以下兩方面影響:
大量的認證資訊會佔用很多記憶體,導致執行個體記憶體溢出(OOM)。
認證資訊堆積可能導致清理的代價變高,影響執行個體的穩定性。
AliSQL對認證資訊的清理做了兩點最佳化:
在主節點上:無論何種情況,認證資訊數組都不會被使用,因此主節點上不再保留認證資訊數組,可以消除認證資訊對主節點的資源和穩定性的影響。
在備節點上:只有當group_replication_consistency參數設定為EVENTUAL時需要保留認證資訊。因為在這個配置下,備節點在切為主節點後會立刻對外提供服務,不會等待Relay Log回放完成,有可能產生資料操作的衝突。這種不等新主節點應用完成,就對外提供服務的方式在日常生產中並不常用。在禁止這種行為後,可以減少備節點的認證資訊保留量,節省備節點的記憶體開銷,提升叢集的穩定性。