MySQL Group Replication 介紹


2016-12-12,一個重要的日子,mysql5.7.17 GA版發布,正式推出Group Replication(組復制) 插件,通過這個插件增強了MySQL原有的高可用方案(原有的Replication方案),提供了重要的特性——多寫,保證組內高可用,確保數據最終一致性

1. 背景

在介紹組復制之前,我們先簡單介紹傳統的異步復制和半同步復制:

1.1 傳統復制

傳統mysql復制是完全異步化的復制。下圖描述了傳統復制的原理:

async_replication_diagram

master事務的提交不需要經過slave的確認,slave是否接收到master的binlog,master並不care。slave接收到master binlog后先寫relay log,最后異步地去執行relay log中的sql應用到自身。由於master的提交不需要確保slave relay log是否被正確接受,當slave接受master binlog失敗或者relay log應用失敗,master無法感知。

假設master發生宕機並且binlog還沒來得及被slave接收,而切換程序將slave提升為新的master,就會出現數據不一致的情況!另外,在高並發的情況下,傳統的主從復制,從節點可能會與主產生較大的延遲(當然mysql后續版本陸續做了優化,推出了並行復制,以此降低異步復制的延遲)。

1.2 半同步復制

基於傳統異步存在的缺陷,mysql在5.5版本推出半同步復制。可以說半同步復制是傳統異步復制的改進,在master事務的commit之前,必須確保一個slave收到relay log並且響應給master以后,才能進行事務的commit。但是slave對於relay log的應用仍然是異步進行的,原理如下圖所示:

semisync_replication_diagram

因為slave接受relay log之后有可能apply失敗。這個時候master其實不知道slave的失敗,照常提交了這個事務。並且,半同步復制只確保一個slave能夠收到relay log,多slave的場景下,不能保證其他節點正確收到relay log,由此,當發生master切換后,半同步復制一樣也會出現數據不一致的情況。

1.3 組復制

gr_replication_diagram

基於傳統異步復制和半同步復制的缺陷——數據的一致性問題無法保證,MySQL官方在5.7.17版本正式推出組復制(MySQL Group Replication,簡稱MGR)。

由若干個節點共同組成一個復制組,一個事務的提交,必須經過組內大多數節點(N / 2 + 1)決議並通過,才能得以提交。如上圖所示,由3個節點組成一個復制組,Consensus層為一致性協議層,在事務提交過程中,發生組間通訊,由2個節點決議(certify)通過這個事務,事務才能夠最終得以提交並響應。

引入組復制,主要是為了解決傳統異步復制和半同步復制可能產生數據不一致的問題。組復制依靠分布式一致性協議(Paxos協議的變體),實現了分布式下數據的最終一致性,提供了真正的數據高可用方案(是否真正高可用還有待商榷)。其提供的多寫方案,給我們實現多活方案帶來了希望。

一個復制組由若干個節點(數據庫實例)組成,組內各個節點維護各自的數據副本(Share Nothing),通過一致性協議實現原子消息和全局有序消息,來實現組內實例數據的一致。

2. 組復制介紹

一句話簡介:基於分布式一致性協議Paxos實現數據最終一致性的MySQL插件。上面的介紹也已經大概地描述了組復制的相關概念以及它的誕生背景,下面我們關注於它的一些特性:

2.1 數據一致性保證

對於只讀(RO)事務,組間實例無需進行通訊,就可以處理事務;但是對於讀寫(RW)事務,需要經過組內大多數節點決議,來決定該事務是否可以提交。

引用mysql官方博客對於讀寫事務提交過程的描述,解釋了如何保證了組內節點間數據的一致性的:

To be precise, when a transaction is ready to commit at the originating server, the server will atomically broadcasts the write values (rows changed) and the correspondent write set (unique identifiers of the rows that were updated). Then a global total order will be established for that transaction. Ultimately, this means that all servers receive the same set of transactions in the same order. As a consequence, all servers apply the same set of changes in the same order, therefore they remain consistent within the group.

2.2 事務並發沖突處理

在高並發的多寫模式(MGR的一種運行模式)下,節點間事務的提交可能會產生沖突,比如,兩個不同的事務在兩個節點上操作了同一行數據,這個時候就會產生沖突。首先,Group Replication(GR)能夠識別到這個沖突,然后對此的處理采用樂觀策略:依賴事務提交的時間先后順序,先發起提交的節點能夠正確提交,而后面的提交,會失敗。

2.3 節點故障自動檢測

GR自帶故障檢測機制,可以識別組內成員是否掛掉(組內節點心跳檢測)。當一個節點失效,將由其他節點決定是否將這個失效的節點從group里面剔除。當然,這是建立在滿足大多數節點存活並且可以進行決議的前提上的。

2.4 組成員自動管理

GR自動維護組內節點的狀態(在線?存活?掛掉?),對於失效的節點,由其他節點決定是否剔除。對於新加入的節點,GR會自動維護它的視圖與其他節點的視圖保持一致。關於集群內節點的狀態,可以通過performance_schema.replication_group_members表查看:

舉個例子:

mysql> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+---------------+-------------+--------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | +---------------------------+--------------------------------------+---------------+-------------+--------------+ | group_replication_applier | 748703ac-dbcc-11e6-a668-90e2bac5d924 | 10.202.44.215 | 24801 | ONLINE | | group_replication_applier | 8f8bc352-2566-11e7-aa5e-d4ae52ab91b3 | 10.202.44.214 | 24801 | ONLINE | | group_replication_applier | 9c09340a-e04c-11e6-9916-0024e869a606 | 10.202.44.213 | 24801 | ONLINE | +---------------------------+--------------------------------------+---------------+-------------+--------------+ 3 rows in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如上有3個節點組成一個GR組,然后狀態都是ONLINE(最正常的狀態)。可以在組內的3個節點上都看到這個統一的視圖。

有些同學可能會問,上面視圖中的MEMBER_HOST是怎么顯示成IP的,其實這個是通過my.cnf配置文件里面指定report_host而來的,若沒有配置report_host,則MEMBER_PORT將顯示為主機名

2.5 容錯能力

GR基於分布式一致性算法實現,一個組允許部分節點掛掉,只要保證大多數節點仍然存活並且之間的通訊是沒有問題的,那么這個組對外仍然能夠提供服務。

假設一個GR由2n + 1個節點,那么允許n個節點失效,這個GR仍然能夠對外提供服務。比如有3個節點組成的一個GR,可允許1個節點失效,這個GR仍然能夠提供服務。

GR組節點數 大多數 允許掛掉的節點數
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
6 4 2
7 4 3

【注意】若不滿足大多數,所有事務寫操作都會阻塞,直到集群滿足大多數節點存活為止。

GR一般由奇數個節點組成為佳,是從最節省機器的角度考慮,你用4台機器,一樣只能掛1台。

2.6 兩種模式

GR提供了single-primarymulti-primary兩種模式。single-primary模式下,組內只有一個節點負責寫入,讀可以從任意一個節點讀取,組內數據保持最終一致;而multi-primary模式即為多寫方案,即寫操作會下發到組內所有節點,組內所有節點同時可讀可寫,該模式也是能夠保證組內數據最終一致性。

注意,一個GR的所有節點必須配置使用同一種模式,不可混用。比如說A、B、C三個節點組成一個GR組,那么要么都運行在single-primary模式下,要么都運行在multi-primary模式下。

my.cnf里的配置項group_replication_single_primary_mode來配置節點到底是運行在single-primary模式還是multi-primary模式

2.6.1 Single-Primary Mode

這個模式下,group內只有一台節點可寫可讀,其他節點只可以讀。對於group的部署,需要先跑起primary節點(即那個可寫可讀的節點,read_only = 0)然后再跑起其他的節點,並把這些節點一一加進group。其他的節點就會自動同步primary節點上面的變化,然后將自己設置為只讀模式(read_only = 1)。

當primary節點意外宕機或者下線,在滿足大多數節點存活的情況下,group內部發起選舉,選出下一個可用的讀節點,提升為primary節點。

primary選舉根據group內剩下存活節點的server_uuid按字典序升序來選擇,即剩余存活的節點按server_uuid字典序排列,然后選擇排在最前的節點作為新的primary節點。

引用 MySQL 5.7 Reference Manual :

Upon primary member failure, an automatic leader election mechanism chooses the next primary member. The next primary is selected by ordering the remaining servers lexicographically (using their UUID) and picking the first member in the list.

single-primary-election

【特別重要】 在切換primary期間,mysql group不會處理應用重連接到新的主,這需要應用層自己或者由另外的中間件層(proxy or router)去保證。

如何查看group內哪個節點是作為primary節點,官方提供了一個方法:

mysql> SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member'; +--------------------------------------+ | VARIABLE_VALUE | +--------------------------------------+ | 69e1a3b8-8397-11e6-8e67-bf68cbc061a4 | +--------------------------------------+ 1 row in set (0,00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

得到的是實例節點的server_uuid。利用上面的SQL,加上performance_schema里的replication_group_members表,可以查出更細節的信息,包括hostname,port等,sql語句如下所示:

SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_ID = ( SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member' );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

另外,還可以通過以下SQL來直接判斷當前節點是否為主節點,得到1表示主節點,0表示不是主節點:

mysql> SELECT IF((SELECT @@server_uuid) = (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member'), 1, 0) as is_primary_node; +-----------------+ | is_primary_node | +-----------------+ | 1 | +-----------------+ 1 row in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

最后發現一個便捷的方式,可以通過直接查看read_only變量來判斷節點是否為主節點:

mysql> select @@read_only; +-------------+ | @@read_only | +-------------+ | 0 | +-------------+ 1 row in set (0.00 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.6.2 Multi-Primary Mode

多主模式,即多寫,沒有選擇新primary的概念(無需進行選舉),group內的所有機器都是primary節點,同時可以進行讀寫操作,並且數據是最終一致的。但是,這個模式下仍然存在一些使用限制,限制請看2.7.2小節介紹。

multi-primary

2.7 約束與限制

2.7.1 約束

部署GR有以下需求:

1) 架構

  • 存儲引擎必須為innodb
  • 每個表必須提供主鍵
  • 只支持ipv4,網絡帶寬要好
  • 一個group最多只能有9個節點

2) 配置上

針對my.cnf,需要指定如下配置:


# Binary Log must be active.
log-bin[=log_file_name]

# Binary Log Format must be set to ROW. binlog-format=row # Global Transaction Identifiers must be turned on. gtid-mode=ON # Replication applier needs to have replication metadata repositories stored in system tables. master-info-repository=TABLE relay-log-info-repository=TABLE # Transaction write set extraction must be enabled. transaction-write-set-extraction=XXHASH64 # Servers need to log binary logs that are applied through the replication applier. log-slave-updates # Replication event checksums are not supported. binlog-checksum=NONE
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.7.2 限制

以下是使用GR的限制:

  • 不支持Replication event checksums,需要在my.cnf里面配置,在上節已經提及
  • 不支持Savepoints
  • multi-primary mode部署方式不支持SERIALIZABLE事務隔離級別
  • multi-primary mode部署方式不能完全支持級聯外鍵約束
  • multi-primary mode部署方式不支持在不同節點上對同一個數據庫對象並發執行DDL(在不同節點上對同一行並發進行RW事務,后發起的事務會失敗)
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM