1 MySQL數據庫 Group Replication
MySQL Group Replication(下簡稱:MGR)是MySQL官方推出的一種基於Paxos協議的狀態機複製。在MGR出現之前,用戶常見的MySQL高可用方式,無論怎麼變化架構,本質就是Master-Slave架構。MySQL 5.7版本開始支持無損半同步複製(lossless semi-sync replication),從而進一步提示數據複製的強一致性
組複製是一種可用於實現容錯系統的技術。複製組是一個通過消息傳遞相互交互的Server集羣。複製組由多個Server成員組成,如下圖的Master1、Master2、Master3,所有成員獨立完成各自的事務。
當客戶端發起一個更新事務時,該事務先在本地執行,執行完成之後就要發起對事務的提交操作。在還沒有真正提交之前,需要將產生的複製寫集廣播出去,複製到其它成員。如果衝突檢測成功,組內決定該事務可以提交,其它成員可以應用,否則就回滾。
最終,所有組內成員以相同的順序接收同一組事務。因此組內成員以相同的順序應用相同的修改,保證組內數據強一致性。
2 MySQL Group Replication 要求
要用於組複製的服務器實例必須滿足以下要求。
2.1 基礎架構
2.1.1 InnoDB存儲引擎
數據必須存儲在 InnoDB
事務存儲引擎中。事務以樂觀方式執行,然後在提交時檢查衝突。如果存在衝突,爲了保持整個組的一致性,將回滾一些事務。這意味着需要事務存儲引擎。此外, InnoDB
還提供了一些附加功能,可以在與Group Replication一起操作時更好地管理和處理衝突。使用其他存儲引擎,包括臨時存儲引擎 MEMORY
存儲引擎,可能會導致組複製錯誤。您可以通過disabled_storage_engines
在組成員上設置系統變量來阻止使用其他存儲引擎 ,例如:
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
2.1.2 主鍵
要由組複製的每個表必須具有已定義的主鍵或等效的主鍵,其中等效項是非null唯一鍵。這些密鑰作爲表中每一行的唯一標識符是必需的,使系統能夠通過準確識別每個事務已修改的行來確定哪些事務衝突。
2.1.3 外鍵
不建議使用級聯外鍵,如果舊庫本身有外鍵,業務上無法去除並且使用的是多主模式,那麼,請配置 group_replication_enforce_update_everywhere_check ,強制檢查每個組成員的級聯檢查,避免多主模式下執行級聯操作造成的檢測不到的衝突。
2.1.4 隔離級別
官網建議使用READ COMMITTED級別,除非應用程序依賴於REPLEATABLE READ,RC模式下沒有GAP LOCK,比較好支持Innodb本身的衝突檢測機制何組複製的內部分佈式檢測機制一起協同工作。不支持SERIALIZABLE隔離級別。
2.1.5 ID自增&步長
這裏需要注意到,搭建group的時候,每個實例中的auto_increment_increment跟auto_increment_offset的配置情況。
- auto_increment_increment,在GROUP中範圍在1-9(因爲一個GROUP最多只能有9個組成員),GROUP中安裝的時候,默認爲7;
- auto_increment_offset,增長步長,GROUP安裝過程,是等於@@server_id的,但是注意有個規則是,當 auto_increment_offset > auto_increment_increment的時候,則是忽略 auto_increment_offset的設置,第一個insert的從1開始,組內其他成員的初始值按照插入順序 1+n*組員個數,若GROUP有3個成員,A,B,C,serverid分別爲2243310,2243320,3423340,A先insert,C再insert,B最後insert,則初始值 A是1,B是9,C是6
2.1.6 IPv4 協議
MySQL Group Replication使用的組通信引擎僅支持IPv4。因此,組複製需要IPv4網絡基礎結構。
2.2 數據庫實例
2.2.1 Binary Log Active
MySQL Group Replication複製二進制日誌內容,因此二進制日誌需要打開才能運行。默認情況下啓用此選項。
--- 配置my.cnf
log_bin = /app/mysql5.7/logs/ocean-bin
2.2.2 Slave Updates Logged
服務器需要記錄通過複製應用程序應用的二進制日誌。組中的服務器需要記錄他們收到的所有事務並從組中應用。這是必需的,因爲恢復是通過依賴組中的參與者的二進制日誌來進行的。因此,每個事務的副本都需要存在於每個服務器上,即使對於那些未在服務器本身上啓動的事務也是如此。
--- 配置my.cnf
log_slave_updates = 1
2.2.3 Binary Log Row Format
組複製依賴於基於行的複製格式,以在組中的服務器之間一致地傳播更改。它依賴於基於行的基礎結構來提取必要的信息,以檢測在組中的不同服務器中併發執行的事務之間的衝突。
--- 配置my.cnf
binlog_format = 'ROW'
2.2.4 Binary Log Checksums Off
由於複製事件校驗和的設計限制,組複製無法使用它們,因此必須禁用它們。
--- 配置my.cnf
binlog_checksum = NONE
2.2.5 Global Transaction Identifiers On
組複製使用全局事務標識符來準確跟蹤在每個服務器實例上已提交的事務,從而能夠推斷哪些服務器執行的事務可能與其他地方已提交的事務衝突。換句話說,顯式事務標識符是框架的基本部分,以便能夠確定哪些事務可能發生衝突。
--- 配置my.cnf
gtid_mode = ON
2.2.6 Replication Information Repositories
複製應用程序需要將主信息和中繼日誌元數據寫入 系統表mysql.slave_master_info
和 mysql.slave_relay_log_info
系統表。這可確保組複製插件具有一致的可複製性和複製元數據的事務管理。
--- 配置my.cnf
master_info_repository=TABLE
relay_log_info_repository=TABLE
2.2.7 Transaction Write Set Extraction
收集行以將其記錄到二進制日誌時,服務器也會收集寫入集。寫集基於每行的主鍵,是標記的簡化緊湊視圖,唯一標識已更改的行。然後,此標記用於檢測衝突。
--- 配置my.cnf
transaction_write_set_extraction=XXHASH64
2.2.8 Multithreaded Appliers
組複製成員可以配置爲多線程應用程序,從而可以並行應用事務。
--- 配置my.cnf
slave_parallel_workers = 3
slave_preserve_commit_order = 1
slave_parallel_type = [ LOGICAL_CLOCK | DATABASE ]
配置 --slave-parallel-workers=N
啓用成員上的多線程應用程序。組複製依賴於圍繞保證所有參與成員以相同順序接收和應用已提交事務的一致性機制,因此您還必須設置 --slave-preserve-commit-order=1
確保並行事務的最終提交與原始事務的順序相同。最後,爲了確定哪些事務可以並行執行,中繼日誌必須包含生成的事務父信息 --slave-parallel-type=LOGICAL_CLOCK
。嘗試在--slave-parallel-workers
不設置其他兩個選項的情況下添加set大於0 的成員會 生成錯誤,並且會阻止實例加入。
3 MySQL Group Replication 配置
3.1 基礎環境
實例名 | 主機名 | IP地址 | 實例ID | 實例端口 | 通訊端口 | 軟件版本 | my.cnf |
node1 | node1 | 10.11.12.1 | 1 | 3306 | 20001 | 5.7.24 | Y |
node2 | node2 | 10.11.12.2 | 2 | 3306 | 20002 | 5.7.24 | Y |
node3 | node3 | 10.11.12.3 | 3 | 3306 | 20003 | 5.7.24 | Y |
3.2 單主模式
組中的每個服務器實例都可以在獨立的物理機器上運行,也可以在同一臺機器上運行。本節介紹如何在一臺物理計算機上創建具有三個MySQL Server實例的複製組。這意味着需要三個數據目錄,每個服務器實例一個,並且您需要獨立配置每個實例。
3.2.1 部署MySQL實例
單實例部署請參考《MySQL數據庫安裝實踐 Part 1:單實例部署》。Group Replication是MySQL Server 5.7.17及更高版本提供的內置MySQL插件。
3.2.2 MySQL組複製配置(at all of nodes)
--- 配置my.cnf
#InnoDB engines
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
log_bin = /app/mysql5.7/logs/ocean-bin
binlog_format = ROW
#Group Replication parameter
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "10.11.12.1:20001"
loose-group_replication_group_seeds = "10.11.12.1:20001,10.11.12.2:20002,10.11.12.3:20003"
loose-group_replication_bootstrap_group = OFF
loose-binlog_gtid_simple_recovery = ON
loose-group_replication_enforce_update_everywhere_checks = OFF
關於MGR相關參數說明
- transaction_write_set_extraction --- 記錄事務的算法
- group_replication_start_on_boot --- 是否隨服務器啓動而自動啓動組複製
- group_replication_bootstrap_group --- 引導組成員的組,這個用於第一次搭建MGR跟重新搭建MGR的時候使用
- group_replication_group_name --- 此GROUP的名字,必須是一個有效的UUID,以此來區分整個內網裏邊的各個不的GROUP
- group_replication_local_address --- 本地的IP地址字符串,host:port
- group_replication_group_seeds --- 需要接受本實例的信息服務器IP地址字符串
- group_replication_single_primary_mode --- 是否啓動單主模式,如果啓動,則本實例是主庫,提供讀寫,其他實例僅提供讀
- group_replication_enforce_update_everywhere_checks --- 多主模式下,強制檢查每一個實例是否允許該操作
3.2.3 創建數據同步賬號(at all of nodes)
--- 禁止binlog
SET SQL_LOG_BIN=0;
--- 創建用戶
CREATE USER rep@'10.11.12.%' IDENTIFIED BY 'root1234';
GRANT REPLICATION SLAVE ON *.* TO rep@'10.11.12.%';
FLUSH PRIVILEGES;
--- 開啓binlog
SET SQL_LOG_BIN=1;
3.2.4 安裝Group Replication插件(at all of nodes)
--- 安裝Group Replication插件
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
--- 查看插件狀態
SHOW PLUGINS;
3.2.5 開啓Group Replication(at the node1)
--- 查看當前的group replication相關參數
show global variables like 'group%';
--- 啓動 group_replication_bootstrap_group
SET GLOBAL group_replication_bootstrap_group=ON;
--- 配置MGR
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
--- 啓動MGR
start group_replication;
--- 查看Error log
tail -50f /app/mysql5.7/logs/node1.err
--- 關閉 group_replication_bootstrap_group
SET GLOBAL group_replication_bootstrap_group=OFF;
--- 查看數據文件
ls -rtlh /app/mysql5.7/data | grep relay
-- *_apaplier.* 系列文件 提供 SQL_Thread 使用,存儲同個組內其他SERVER的binnary log,這個文件在第一個組成員加入組的時候,可以在Error Log看到其安裝信息。
-- *_recovery.* 系列文件 是做什麼使用的呢,在第一個成員啓動MGR的時候,並沒有看到其相關信息,稍後解疑!
3.2.6 添加node2
--- 查看當前的group replication相關參數
show global variables like 'group%';
--- 配置MGR
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
--- 啓動MGR
start group_replication;
--- 查看Error log
tail -50f /app/mysql5.7/logs/node2.err
--- 查看組複製成員
SELECT * FROM performance_schema.replication_group_members;
--- 查看組複製成員
SELECT * FROM performance_schema.replication_group_member_stats\G;
通過errrlog,可以詳細看到啓動過程的所有步驟信息,由於新增數據,導致node2需要使用到 group_replication_recovery 通道來恢復數據。
3.2.7 添加node3
--- 查看當前的group replication相關參數
show global variables like 'group%';
--- 配置MGR
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
--- 啓動MGR
start group_replication;
--- 查看Error log
tail -50f /app/mysql5.7/logs/node3.err
--- 查看組複製成員
SELECT * FROM performance_schema.replication_group_members;
--- 查看組複製成員
SELECT * FROM performance_schema.replication_group_member_stats\G;
通過errrlog,可以詳細看到啓動過程的所有步驟信息,由於新增數據,導致node3需要使用到 group_replication_recovery 通道來恢復數據,這跟node2是一模一樣的過程,但是,由於前期node1造了大量的數據,所以在整個recovery的過程中,可以查看到 *_recovery.* 系列文件 的變化情況。
通過error log大小的變化,是通過group_replication_recovery 通道來恢復數據,需要恢復的binary log是存放在 *_recovery.* 系列文件 ,通過本次recovery 文件查看,發現,在recovery過程中,通道內的IO_THREAD拉去日誌存儲在 *_recovery.* 系列文件 中,當通道內的 SQL_Thread 完成日誌應用後,則會刪除掉 *_recovery.* 系列文件 文件,新建空文件,代表已經沒有數據需要恢復。
至此,單主模式已搭建結束,node1可提供讀寫,但是node2和node3僅提供讀服務。
通道說明
- group_replication_applier 通道 提供組內成員向 MASTER 實時同步binlog日誌使用,這個通道內IO_thread拉取到的日誌存放在 *_apaplier.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上。
- group_replication_recovery 通道 提供 首次加入GROUP或者重新加入GROUP時恢復數據使用,這個通道內 IO_thread拉取到的日誌存放在 *_recovery.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上,應用結束後,刪除所有 *_recovery.* 系列文件 ,重新建立新的 *_recovery.* 系列文件。
3.3 多主模式
3.3.1 多主模式參數配置
my.cnf的配置參數中,把 group_replication_single_primary_mode 參數設置成‘OFF’狀態即可。
--- 動態修復方式
set global group_replication_single_primary_mode=OFF;
--- 配置文件修改方式
loose-group_replication_single_primary_mode = OFF
注:單主模式運行時,動態修改此參數會報錯
需先停止組複製, 操作流程:
- 業務端連接IP處理
- 組內成員依次主動退出
- 關閉 group_replication_single_primary_mode參數
- 依次啓動組內的實例
3.3.2 組內成員依次退出
node1實例退組
--- node1實例退組
stop group_replication;
--- 查看node2、node3的errorlog
tail -50f /app/mysql5.7/log/node2.err
tail -50f /app/mysql5.7/log/node3.err
errorlog如下
node1停止gr
node2實例被選舉爲 new primary member
node3實例被選舉爲 secondary member
這個時候,node1可讀寫,但是不在group中,其binlog內容不會在組內同步;node3自動升級爲主庫,可讀寫,binlog會同步到node2上。這裏的主庫升級,是看MEMBER_ID的升序排序情況,最小的升級爲主庫。
node2上通過查看 replication_group_members、global_status,可以查看現在的組成員以及主庫信息。
--- 查看組內成員信息
SELECT * FROM performance_schema.replication_group_members;
--- 查看global組信息
SELECT * FROM performance_schema.global_status WHERE variable_name LIKE '%group%';
node2實例退組
--- node2實例退組
stop group_replication;
--- 查看node2的errorlog
tail -50f /app/mysql5.7/logs/node3.err
node1,node2均可以讀寫,但是不在組中,業務目前在node1上運行,node3也可以讀寫,目前是主庫。
node3實例退組
--- node3實例退組
stop group_replication;
組內的所有成員都依次退出了GROUP。
3.3.3 配置group_replication_single_primary_mode參數(at all of nodes)
--- 動態修復方式
set global group_replication_single_primary_mode=OFF;
--- 配置文件修改方式
loose-group_replication_single_primary_mode = OFF
3.3.4 依次啓動組內的實例
首先啓動實例A,然後啓動實例B,緊接着啓動實例C。實例A啓動的時候,可以看到成了一個新的GROUP,B加入到時候,需要通過 group_replication_recovery 通道恢復數據,C加入到時候,也需要通過 group_replication_recovery 通道恢復數據,這部分的內容跟 3.2.5 配置Group 中的errorlog內容。
--- node1實例啓動
---- 需要啓動 group_replication_bootstrap_group 引導組,啓動後需要關閉,防止腦裂
set global group_replication_bootstrap_group=ON;
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
set global group_replication_bootstrap_group=OFF;
--- node2實例啓動
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
start group_replication;
--- node3實例啓動
CHANGE MASTER TO MASTER_USER='rep', MASTER_PASSWORD='root1234' FOR CHANNEL 'group_replication_recovery';
start group_replication;
3.3.5 監控GR狀態
目前GROUP中的各個成員都關閉了super_read_only選項,提供了讀寫服務,由於三個都爲主庫,屬於多主情況,所以 global_status中無法查看到主庫信息,因爲這個GROUP中,每個SERVER都是MASTER。
--- 查看組成員
select * from performance_schema.replication_group_members;
--- 查看組內master信息
select * from performance_schema.global_status where variable_name like '%group%';
--- 查看單主模式參數
show global variables like 'group_replication_single_primary_mode';
--- 查看只讀
show global variables like 'super%';
至此,多主模式已搭建結束,實例node1、node2、node3均可提供讀寫。
4 日常運維
4.1 運維用到的表
table_schema | table_name | type | description |
performance_schema | replication_group_members |
重要 常用 |
查看組成員 |
performance_schema | replication_group_member_stats |
重要 常用 |
當前實例在組中的同步情況, 查看applier通道的同步情況。 |
performance_schema | replication_connection_stats |
重要 常用 |
當前實例中各個通道的使用情況, applier通道是一定有顯示, recovery通道看是否使用過, 如果有則顯示,沒有則不顯示。 |
performance_schema | replication_applier_stats |
重要 常用 |
當前server中各個通道是否啓用。 |
performance_schema | global_status |
重要 常用 |
單主模式下,查看當前主庫信息。 |
performance_schema | replication_applier_configuration |
瞭解 不常用 |
|
performance_schema | replication_applier_status_by_coordinator |
瞭解 不常用 |
|
performance_schema | replication_applier_status_by_worker |
瞭解 不常用 |
|
performance_schema | replication_connection_configuration |
瞭解 不常用 |
|
mysql | slave_master_info |
重要 不常用 |
設置了master_info_repository=TABLE,所以master的相關信息會存儲在這個表格。 如果使用GROUP中的SERVER備份數據庫,恢復時,注意要清理這個表格。 |
mysql | slave_relay_log_info |
重要 不常用 |
設置了relay_log_info_repository=TABLE,所以master的相關信息會存儲在這個表格。 如果使用GROUP中的SERVER備份數據庫,恢復時,注意要清理這個表格。 |
4.2 運維用到的查詢語句
--- 查詢組成員信息
SELECT * FROM performance_schema.replication_group_members;
--- 單主模式,查詢master。(UUID一致的即爲master)
SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema.global_status;
--- 實例是否讀寫
show global variables like 'super%';
SELECT * FROM performance_schema.replication_group_members;
---- 如果super_read_only是啓動的,那麼該成員僅提供讀服務;
---- 如果super_read_only是關閉的,並且 replication_group_members 中正常的成員n 滿足 2n+1 > 整個GROUP成員個數,並且該成員的 member state是online,則該成員可提供讀寫服務。
--- 檢查組複製狀態
SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema.replication_group_member_stats;
SELECT * FROM performance_schema.replication_connection_stats;
SELECT * FROM performance_schema.replication_applier_stats;
tail -50f /app/mysql5.7/logs/node1.err
tail -50f /app/mysql5.7/logs/node2.err
tail -50f /app/mysql5.7/logs/node3.err
附件
單主模式my.cnf參數對比 | ||
node1 | node2 | node3 |
[mysqld]
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 1 log_bin_index = /app/mysql5.7/logs/node1-bin.index enforce_gtid_consistency = ON expire_logs_days = 7
#Group Replication parameter
transaction_write_set_extraction = XXHASH64 loose-group_replication_single_primary_mode = ON |
[mysqld]
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 2 log_bin_index = /app/mysql5.7/logs/node2-bin.index enforce_gtid_consistency = ON expire_logs_days = 7
#Group Replication parameter
transaction_write_set_extraction = XXHASH64 |
[mysqld]
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 3 log_bin_index = /app/mysql5.7/logs/node3-bin.index enforce_gtid_consistency = ON expire_logs_days = 7
#Group Replication parameter
transaction_write_set_extraction = XXHASH64 |
單主模式 & 多主模式,my.cnf參數對比 | |
單主模式 | 多主模式 |
[mysqld]
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 1 log_bin_index = /app/mysql5.7/logs/node1-bin.index enforce_gtid_consistency = ON expire_logs_days = 7
#Group Replication parameter
transaction_write_set_extraction = XXHASH64 loose-group_replication_single_primary_mode = ON |
[mysqld]
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#Replication infrastructure
server_id = 1 log_bin_index = /app/mysql5.7/logs/node1-bin.index enforce_gtid_consistency = ON expire_logs_days = 7
#Group Replication parameter
transaction_write_set_extraction = XXHASH64 loose-group_replication_single_primary_mode = OFF |
參考
MySQL 5.7 Reference Manual - Chapter 17 Group Replication
相關鏈接