企業級高性能MYSQL的用法---------(二)----------半同步複製 和 全同步複製(組複製)

企業級高性能MYSQL的用法---------(二)----------半同步複製 和 全同步複製(組複製)

1.基於GDIT的半同步複製

  1. 爲什麼要實現mysqI的複製
    1.實現服務器負載均衡
    2.通過複製實現數據的異地備份
    3.提高數據庫系統的可用性

  2. 異步複製、全同步複製和半同步複製的對比
    1.異步複製( Asynchronous replication )
    MySQL默認的複製即是異步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果down掉了,此時主上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升爲主,可能導致新主上的數據不完整。
    2.全同步複製( Fully synchronous replication )
    指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因爲需要等待所有從庫執行完該事務才能返回,所以全同步複製的性能必然會收到嚴重的影響。
    3.半同步複製( Semisynchronous replication )
    介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步複製,半同步複製提高了數據的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網絡中使用。

在2010年MySQL 5.5版本之前,一直採用的是這種異步複製的方式。主庫的事務執行不會管備庫的同步進度,如果備庫落後,主庫不幸crash,那麼就會導致數據丟失。於是在MySQL在5.5中就順其自然地引入了半同步複製,主庫在應答客戶端提交的事務前需要保證至少一個從庫接收並寫到relay log中

  1. 基於GDIT的半同步複製
    第一步:主庫安裝服務插件,並且開啓半同步複製
[root@server1 ~]# mysql -uroot -pXiaoxu@junjun021129
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.28-log MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>  install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)

mysql> select plugin_name,plugin_status
    -> from information_schema.plugins
    -> where plugin_name like '%semi%';
+----------------------+---------------+
| plugin_name          | plugin_status |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.01 sec)

mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi%'; 
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)

mysql> show status like '%rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

mysql> 

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
第二步:在從端也安裝插件,開啓半同步複製

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)

mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.01 sec)

mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.03 sec)

mysql> 

在這裏插入圖片描述

注意:要重啓從端的IO線程,如果沒有重啓,則默認還是異步複製,重啓後,slave會在master上註冊爲半同步複製的slave角色

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

mysql> show status like '%rpl%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

mysql> show variables like '%rpl%';
+---------------------------------+----------+
| Variable_name                   | Value    |
+---------------------------------+----------+
| rpl_semi_sync_slave_enabled     | ON       |
| rpl_semi_sync_slave_trace_level | 32       |
| rpl_stop_slave_timeout          | 31536000 |
+---------------------------------+----------+
3 rows in set (0.00 sec)

mysql> 

在這裏插入圖片描述
在這裏插入圖片描述

測試:

情況一1:半同步失敗的情況

沒有通過半同步複製

1.從端關掉IO線程:

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)

2. 在主端表中插入數據,會等待10秒,10s後會變爲異步複製:

mysql> insert into userlist values ('user5','555');
Query OK, 1 row affected (10.01 sec)

此時在主端發現半同步失敗次數+1:

Rpl_semi_sync_master_no_tx表示沒有成功接收slave提交的次數,也就是使用半同步失敗的次數,10s後沒有得到反饋信息,會轉爲異步複製
Rpl_semi_sync_master_yes_tx使用半同步成功的次數,數據的一致性能提高

在這裏插入圖片描述

此時,從端會發現沒有同步過來,再次打開IO線程後,數據才能同步過來,此時複製過來的是異步複製的結果

mysql> select * from userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1    | 888      |
| user2    | 888      |
+----------+----------+
2 rows in set (0.00 sec)

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1    | 888      |
| user2    | 888      |
| user3    | 888      |
+----------+----------+
3 rows in set (0.00 sec)

mysql> 

在這裏插入圖片描述
情況二:半同步正常情況

第一步:從端打開IO:

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

第二步 主端插入新數據:

mysql> insert into userlist values ('user6','666');
Query OK, 1 row affected (0.01 sec)

mysql> select * from userlist;

mysql> show status like '%rpl%';  #Rpl_semi_sync_master_yes_tx 變爲1,成功一次

在這裏插入圖片描述
從端驗證同步結果
在這裏插入圖片描述

2.MySQL的組複製

1.組複製模型

  1. 組複製模型
    MySQL組複製是MySQL 5.7.17開始引入的新功能,爲主從複製實現高可用功能。它支持單主模型和多主模型兩種工作方式(默認是單主模型)。
  2. 單主模型
    從複製組中衆多個MySQL節點中自動選舉一個master節點,只有master節點可以寫,其他節點自動設置爲read only。當master節點故障時,會自動選舉一個新的master節點,選舉成功後,它將設置爲可寫,其他slave將指向這個新的master。
  3. 多主模型
    複製組中的任何一個節點都可以寫,因此沒有master和slave的概念,只要突然故障的節點數量不太多,這個多主模型就能繼續可用。

2.組複製原理

複製組由多個 server成員構成,並且組中的每個 server 成員可以獨立地執行事務。但所有讀寫(RW)事務只有在衝突檢測成功後纔會提交。只讀(RO)事務不需要在衝突檢測,可以立即提交。

換句話說,對於任何 RW 事務,提交操作並不是由始發 server 單向決定的,而是由組來決定是否提交。準確地說,在始發 server 上,當事務準備好提交時,該 server 會廣播寫入值(已改變的行)和對應的寫入集(已更新的行的唯一標識符)。然後會爲該事務建立一個全局的順序。最終,這意味着所有 server 成員以相同的順序接收同一組事務。因此,所有 server 成員以相同的順序應用相同的更改,以確保組內一致。

組複製使您能夠根據在一組 server 中複製系統的狀態來創建具有冗餘的容錯系統。因此,只要它不是全部或多數 server 發生故障,即使有一些 server 故障,系統仍然可用,最多隻是性能和可伸縮性降低,但它仍然可用。server 故障是孤立並且獨立的。它們由組成員服務來監控,組成員服務依賴於分佈式故障檢測系統,其能夠在任何 server 自願地或由於意外停止而離開組時發出信號。

總之,MySQL 組複製提供了高可用性,高彈性,可靠的 MySQL 服務。

3.實現組複製

實驗環境:
server1 server2 server3三臺裝有mysql的虛擬機

第一步:還原之前做過的實驗(因爲server1 server2 之前做過實驗,server3 是新機)

在server1 和 server2 中:

systemctl stop mysqld
cd /var/lib/mysql
rm -fr *

注意:如果之前沒有做過其他的mysql實驗,就可不用做這一步驟

在這裏插入圖片描述
在這裏插入圖片描述
第二步:配置server1

1. 生成UUID:
uuidgen	#這一步生成的uuid要在後面用到

2. 編輯mysql配置文件:

vim /etc/my.cnf
寫入:
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=binlog
binlog_format=ROW
plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64	#指示Server必須爲每個事務收集寫集合,並使用XXHASH64哈希算法將其編碼爲散列
group_replication_group_name="d2c2069a-974c-11ea-8ffb-000c29050807"	#告知插件,正在加入或創建的組要命名,一般寫UUID
group_replication_start_on_boot=off	#指示插件在 server 啓動時不自動啓動組複製
group_replication_local_address= "192.168.43.71:33061"	#告訴插件使用 IP 地址 本地主機,端口33061用於接受來自組中其他成員的傳入連接。
group_replication_group_seeds= "192.168.43.71:33061,192.168.43.72:33061,192.168.43.73:33061"
group_replication_bootstrap_group=off	#配置是否自動引導組
loose-group_replication_ip_whitelist="127.0.0.1,192.168.43.0/24"	#用戶白名單
loose-group_replication_enforce_update_everywhere_checks=ON	#多主模式下爲多主更新啓用或禁用嚴格一致性檢查
loose-group_replication_single_primary_mode=OFF	#設置組自動選擇一個 server 來處理讀/寫工作

在這裏插入圖片描述

3. 打開服務、過濾密碼、安全初始化:

systemctl start mysqld
cat /var/log/mysqld.log | grep password
mysql_secure_installation 
4. 啓動組複製:

mysql> SET SQL_LOG_BIN=0;	#禁用二進制日誌
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Xiaoxu@junjun021129';	#創建用戶
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';	#加用戶權限
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;	#刷新數據
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;	#啓用二進制日誌
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Redhat.123' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.04 sec)

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';	#安裝組複製插件(因爲配置文件已經寫過此參數,所以報錯)
ERROR 1125 (HY000): Function 'group_replication' already exists
mysql> SHOW PLUGINS;


mysql> SET GLOBAL group_replication_bootstrap_group=ON;	#先打開,等打開組複製之後再開啓
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;	#打開組複製
Query OK, 0 rows affected (2.30 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;	#查看狀態,顯示ONLINE則開啓成功

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
第三步:配置server2

1 還原之前做過的實驗:
注意:如果之前沒有做過其他的mysql實驗,就可不用做這一步驟
systemctl stop mysqld
cd /var/lib/mysql
rm -fr *

step2 編輯mysql配置文件:
vim /etc/my.cnf
修改兩處:
server_id=2	#修改id
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=binlog
binlog_format=ROW
plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64	
group_replication_group_name="d2c2069a-974c-11ea-8ffb-000c29050807"	
group_replication_start_on_boot=off	
group_replication_local_address= "192.168.43.72:33061"	#修改本機ip
group_replication_group_seeds= "192.168.43.71:33061,192.168.43.72:33061,192.168.43.73:33061"
group_replication_bootstrap_group=off
loose-group_replication_ip_whitelist="127.0.0.1,192.168.43.0/24"	
loose-group_replication_enforce_update_everywhere_checks=ON	
loose-group_replication_single_primary_mode=OFF	


3 打開服務、過濾密碼、安全初始化:

systemctl start mysqld
cat /var/log/mysqld.log | grep password
mysql_secure_installation

4 配置組複製:
mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Xiaoxu@junjun021129';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Xiaoxu@junjun021129' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (3.11 sec)

mysql> 

配置完成之後,在server1上查看狀態:

在這裏插入圖片描述

第四步:配置server3

1 還原之前做過的實驗:
注意:如果之前沒有做過其他的mysql實驗,就可不用做這一步驟
systemctl stop mysqld
cd /var/lib/mysql
rm -fr *

step2 編輯mysql配置文件:
vim /etc/my.cnf
修改兩處:
server_id=3	#修改id
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=binlog
binlog_format=ROW
plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64	
group_replication_group_name="d2c2069a-974c-11ea-8ffb-000c29050807"	
group_replication_start_on_boot=off	
group_replication_local_address= "192.168.43.73:33061"	#修改本機ip
group_replication_group_seeds= "192.168.43.71:33061,192.168.43.72:33061,192.168.43.73:33061"
group_replication_bootstrap_group=off
loose-group_replication_ip_whitelist="127.0.0.1,192.168.43.0/24"	
loose-group_replication_enforce_update_everywhere_checks=ON	
loose-group_replication_single_primary_mode=OFF


3.打開服務、過濾密碼、安全初始化:
systemctl start mysqld
cat /var/log/mysqld.log | grep password
mysql_secure_installation

4.配置組複製:
mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Xiaoxu@junjun021129';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Xiaoxu@junjun021129' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.06 sec)

mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (3.09 sec)

mysql> 

配置完成之後,在server1上查看狀態:

在這裏插入圖片描述

測試:

在其中一臺服務器中創建新表,在其他兩臺都能看見插入的信息

這裏我們在server3中插入數據,在server1 和server2 中都可以看到數據

server3 中

在這裏插入圖片描述
server1 和 server2
在這裏插入圖片描述

同理:在其中一臺服務器中創建新表,在其他兩臺都能看見插入的信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章