簡單來講MySQL的主從復(fù)制就是一個(gè)C/S架構(gòu)的應(yīng)用。master可以認(rèn)為是我們通常意義上所認(rèn)為的server,slave可以當(dāng)作是一臺client。slave上的I/O線程去請求master上數(shù)據(jù),而master驗(yàn)證通過slave的信息后就允許slave接入,然后進(jìn)行數(shù)據(jù)變化信息的發(fā)送。
一、MySQL主從復(fù)制原理
這里我以MySQL5.5為例來說一下MySQL的主從復(fù)制的原理:
首先由備節(jié)點(diǎn)的I/O線程負(fù)責(zé)向主節(jié)點(diǎn)請求數(shù)據(jù),主節(jié)點(diǎn)驗(yàn)證通過以后會(huì)由dump線程把數(shù)據(jù)發(fā)送給備用節(jié)點(diǎn)。備用節(jié)點(diǎn)的I/O線程收到資源后會(huì)把把這些數(shù)據(jù)寫入到中繼日志,備節(jié)點(diǎn)的SQL線程檢測到中繼日志變更后會(huì)立刻根據(jù)中繼日志的內(nèi)容跟新備庫的內(nèi)容。這樣就完成了同步的過程。
二、常見的復(fù)制模型
1、一主一從模型
這種架構(gòu)的優(yōu)點(diǎn)就是比較簡單,搭建和維護(hù)都比較容易,成本也比較低。對于一些負(fù)載量不是特別大、可靠性要求不是特別高的場合,完全可以采用這種模型。但是對于一些負(fù)載比較大站點(diǎn),和對可用性要求比較高的場合,這種架構(gòu)就不太適用了。因?yàn)槿绻L問量比較大,Master節(jié)點(diǎn)的壓力會(huì)比較的,另外如果Master崩潰,也會(huì)導(dǎo)致業(yè)務(wù)的終止。
2、一主多從模型
在絕大多數(shù)場景中,我們的應(yīng)用都是讀多寫。我們使用這種架構(gòu),通過讀寫分離的技術(shù),可以有效降低Master上讀的壓力。我們在后端的slave上可以做一些數(shù)據(jù)備份,數(shù)據(jù)挖掘等方面的工作。但是如果備庫比較多,同時(shí)主庫又要負(fù)責(zé)其他的請求時(shí),主庫的壓力會(huì)明顯增大,此時(shí)主庫會(huì)成為整個(gè)系統(tǒng)的性能瓶頸。
當(dāng)然,還有其他的復(fù)制模型,比如多級中繼,和環(huán)狀復(fù)制等,這些復(fù)制的基本原理都和上面的差不多,這里不再詳細(xì)的解釋了。
3、配置主從復(fù)制
(1)、異步復(fù)制
主從同步的條件:
Master:
a:啟用二進(jìn)制日志;
b:選擇一個(gè)server-id
c:創(chuàng)建具有復(fù)制權(quán)限的用戶
Slave:
a:啟用中繼日志
b:選擇一個(gè)唯一的server-id
c:連接主服務(wù)器,并開始復(fù)制數(shù)據(jù)
A、首先在主庫上建立用于復(fù)制的最小權(quán)限的用戶
1
|
mysql> grant replication slave,replication client on *.* to repl@ '10.12.%' |
1
2
|
-> identified by '123456'; Query OK, 0 rows affected (0.03 sec) |
B、在從庫上連接主庫
1
2
3
4
5
|
mysql> CHANGE MASTER TO MASTER_HOST= '10.12.128.19' ,MASTER_PORT=3306,MASTER_USER= 'repl' , MASTER_PASSWORD= '123456' ,MASTER_LOG_FILE= 'mysql-bin.000006' , MASTER_LOG_POS=451; #查看復(fù)制的狀態(tài) mysql> show slave status\G |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.12.128.19 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 1512 Relay_Log_File: relay_index.000002 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1512 Relay_Log_Space: 452 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 3306 Master_UUID: 97f33396-ed12-11e4-921a-000c29e8ee06 Master_Info_File: /mydata/data5.6/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 1 row in set (0.00 sec) |
C、然后再從庫上執(zhí)行:
1
2
|
#啟動(dòng)復(fù)制 mysql> start slave; |
也可以單獨(dú)啟動(dòng)IO線程和SQL線程。
(如果從庫的IO線程狀態(tài)一直是connecting的狀態(tài),可能是防火墻的原因,一般來說關(guān)閉防火墻或者配置防火墻規(guī)則就可以了)
(2)、半同步復(fù)制
半同步復(fù)制是基于Google為MySQL開發(fā)的半同步復(fù)制的插件。半同步復(fù)制的原理是,一個(gè)事務(wù)在主服務(wù)器上執(zhí)行完成后,必須至少確保至少在一臺從服務(wù)器上執(zhí)行完成后,事務(wù)才算提交成功。如果在一定時(shí)間內(nèi)從服務(wù)器沒有響應(yīng),則會(huì)自動(dòng)降級為異步復(fù)制。
這個(gè)半同步復(fù)制是建立在異步復(fù)制的基礎(chǔ)之上進(jìn)行的。
首先需要安裝Google的半同步插件:
master:
1
|
install plugin rpl_semi_sync_master soname 'semisync_master.so' ; |
slave:
1
|
install plugin rpl_semi_sync_slave soname 'semisync_slave.so' ; |
然后開啟半同步的功能
master:
1
2
|
set global rpl_semi_sync_master_enabled = 1; set global rpl_semi_sync_master_timeout = 100; // 以毫秒計(jì)算 |
slave:
1
|
set global rpl_semi_sync_slave_enabled = ON; |
在從庫上還需要重啟IO線程:
1
2
|
stop slave IO_thread; start slave IO_thread; |
分別在主庫和備庫上查看半同步插件運(yùn)行的狀態(tài):
1
|
mysql> show global status like 'rpl%' ; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
+--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | 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 | 1 | | Rpl_semi_sync_master_no_tx | 8 | | 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.04 sec) |
1
|
mysql> show global status like 'rpl%' ; |
1
2
3
4
5
6
|
+----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.04 sec) |
可以看到,主庫和備庫的半同步插件都已經(jīng)處于啟用狀態(tài)。
至此,異步主從配置結(jié)束。