Mysql-主從複製與讀寫分離

2022-06-06 06:01:25

Mysql-主從複製與讀寫分離

1.MySQL主從複製與讀寫分離

1.1主從複製與讀寫分離

mysql使用主從複製的原因大概由一下三點:

1、在業務複雜的系統中,有這麼一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那麼就很影響執行中的業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。

2、做資料的熱備

3、架構的擴充套件。業務量越來越大,I/O存取頻率過高,單機無法滿足,此時做多庫的儲存,降低磁碟I/O存取的頻率,提高單個機器的I/O效能。

mysql主從複製原理

1.2 主從複製的過程

在主從複製過程中涉及到總共3個執行緒,兩個紀錄檔

Master 二進位制紀錄檔

SLAVE I/O執行緒

Master dump執行緒

SLAVE 中繼紀錄檔

SLAVE SQL執行緒

(1) Master節點將資料的改變記錄成二進位制紀錄檔(bin log),當Master上的資料發生改變時,則將其改變寫入二進位制紀錄檔中。

(2)Slave節點會在一定時間間隔內對Master的二進位制紀錄檔進行探測其是否發生改變,如果發生改變,則開始一個I/o執行緒請求Master的二進位制事件。

(3)同時Master 節點為每個I/o執行緒啟動一個dump執行緒,用於向其傳送二進位制事件,並儲存至slave節點原生的中繼紀錄檔(Relay log)中,Slave節點將啟動SQL執行緒從中繼紀錄檔中讀取二進位制紀錄檔,在本地重放,即解析成sql語句逐一執行,使得其資料和Master節點的保持一致,最後I/0執行緒和SQL執行緒將進入睡眠狀態,等待下一次被喚醒。

半同步模式:注意:5.7版本主多了一個ACK_collection執行緒接受從的ack確認資訊

1.3主從複製的同步模式

1.3.1 非同步複製:

非同步複製是mysql 預設的同步方式
在master為slave開通賬號密碼、ip授權之後,slave 可以從master進行資料同步,主要依賴的是master的binlog紀錄檔

slave會啟動兩個執行緒,IO Thread 和 SQL Thread
IO Thread 負責從master拉取binlog 紀錄檔,並寫入relay中繼紀錄檔
SQL Thread 負責將relay中繼紀錄檔中的變更進行重放,更新資料來達到跟master保持資料一致的目的

這個過程中,slave通過IO執行緒拉取binlog,master無需關注是否有slave需要同步,只做自己的事情,整個複製過程都是非同步完成的,這個就是非同步複製

非同步複製的優勢是效能好,缺點是資料的安全性比較差
在某一刻主從之間的資料差異可能較大,主機掛掉之後從機接管,可能會丟失一部分資料。

1.3.2半同步複製

master更新操作寫入binlog之後會主動通知slave,slave接收到之後寫入relay log 即可應答,master只要收到至少一個ack應答,則會提交事務

可以發現,相比較於非同步複製,半同步複製需要依賴至少一個slave將binlog寫入relay log,在效能上有所降低,但是可以保證至少有一個從庫跟master的資料是一致的,資料的安全性提高。

對於資料一致性要求高的場景,可以採用半同步複製的同步策略,比如主庫掛掉時,準備接管的那一個從庫,對資料的一致性要求很比較高。

半同步複製的優點是資料的安全性好,缺點是效能比非同步複製稍低

1.3.3 全同步複製

全同步複製跟半同步複製的區別是,全同步複製必須收到所有從庫的ack,才會提交事務。
主庫的事務提交依賴於後面所有的從庫,這樣一來效能就會明顯得下降
除非是對所有從庫資料一致性要求非常高的場景,否則我們一般不採用這種策略

全同步複製的資料一致性最好,但是效能也是最差的

mysql主從同步的三種模式_吳小佳同學的部落格

2.實驗步驟

2.1主從複製設定

環境:centos7

mysql版本:5.7.37

​ mysql主節點:192.168.80.20

​ mysql從節點1:192.168.80.25

​ mysql從節點2:192.168.80.30

mysql主節點設定

1.ntp服務設定
[root@mysql_master ~]# yum install ntp -y
······
[root@mysql_master ~]# vim /etc/ntp.conf
--末尾新增--
server 127.0.0.1							#設定本地是時鐘源,注意修改網段,127.0.0.1是本地迴環地址(127.網段中所有ip實際上都是本地迴環地址)
fudge 127.0.0.1 stratum 8	                #設定時間層級為8(限制在15內)
--------------------------------------------------------------
2.mysql組態檔
[root@mysql_master ~]# vim /etc/my.cnf
[mysqld]
......
server-id = 1
log-bin=mysql-bin							#新增,主伺服器開啟二進位制紀錄檔
binlog_format = MIXED
log-slave-updates=true						#新增,允許slave從master複製資料時可以寫入到自己的二進位制紀錄檔
expire_logs_days = 7						#設定二進位制紀錄檔檔案過期時間,預設值為0,表示logs不過期
max_binlog_size = 500M						#設定二進位制紀錄檔限制大小,如果超出給定值,紀錄檔就會發生捲動,預設值是1GB

:wq
--------------------------------------------------------------
[root@mysql_master ~]# systemctl restart mysqld   #重啟msyql服務,使設定生效
[root@mysql_master ~]# mysql -uroot -p            #登入mysql

mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.80.%' IDENTIFIED BY '123456';  #從服務授權

mysql> FLUSH PRIVILEGES;

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      603 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)
#File 列顯示紀錄檔名,Position 列顯示偏移量



mysql從節點1設定

1.ntp設定
[root@mysql_slave1 ~]# yum install ntp ntpdate -y
[root@mysql_slave1 ~]# service ntpd start
[root@mysql_slave1 ~]# /usr/sbin/ntpdate 192.168.80.20         #與主節點進行時間同步

[root@mysql_slave1 ~]# crontab -e
*/30 * * * * /usr/sbin/ntpdate 192.168.80.20
--------------------------------------------------------------
2.mysql設定
[root@mysql_slave1 ~]# vim /etc/my.cnf
server-id = 25								#修改,注意id與Master的不同,兩個Slave的id也要不同
relay-log=relay-log-bin						#新增,開啟中繼紀錄檔,從主伺服器上同步紀錄檔檔案記錄到本地
relay-log-index=slave-relay-bin.index		#新增,定義中繼紀錄檔檔案的位置和名稱,一般和relay-log在同一目錄
relay_log_recovery = 1                      #選配項
#當 slave 從庫宕機後,假如 relay-log 損壞了,導致一部分中繼紀錄檔沒有處理,則自動放棄所有未執行的 relay-log,並且重新從 master 上獲取紀錄檔,這樣就保證了 relay-log 的完整性。預設情況下該功能是關閉的,將 relay_log_recovery 的值設定為 1 時, 可在 slave 從庫上開啟該功能,建議開啟。

:wq
--------------------------------------------------------------
[root@mysql_slave1 ~]# systemctl restart mysqld
[root@mysql_slave1 ~]# mysql -uroot -p

mysql> CHANGE master to master_host='192.168.80.20',master_user='myslave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=603;           #紀錄檔名稱與偏移點應該與主status中的相同
mysql> start slave;
mysql> show slave status\G                # 檢視從狀態
//確保 IO 和 SQL 執行緒都是 Yes,代表同步正常。
Slave_IO_Running: Yes				#負責與主機的io通訊
Slave_SQL_Running: Yes				#負責自己的slave mysql程序

#一般 Slave_IO_Running: No/CONNECTING 的可能性:
1、網路不通
2、my.cnf設定有問題
3、密碼、file檔名、pos偏移量不對
4、防火牆沒有關閉

mysql從節點2設定需要修改server-id

實驗截圖

主節點設定

1.ntp服務相關設定

2.mysql組態檔

[mysqld]下加入

mysql從節點設定:

1.ntp時間同步設定

2.mysql設定

主從複製效果驗證:



2.2 讀寫分離設定

環境:centos7

mysql版本:5.7.37

​ mysql主節點:192.168.80.20

​ mysql從節點1:192.168.80.25

​ mysql從節點2:192.168.80.30

​ Amoeba 伺服器:192.168.80.35 jdk1.6、Amoeba

Amoeba伺服器設定

實現準備jdk和amoeba包至opt目錄
1.設定java環境
[root@amoeba opt]# cd /opt
[root@amoeba opt]# cp jdk-6u14-linux-x64.bin  /usr/local/
[root@amoeba opt]# cd /usr/local/
[root@amoeba opt]# chmod +x jdk-6u14-linux-x64
[root@amoeba opt]# ./jdk-6u14-linux-x64.bin
//按yes,按enter
[root@amoeba local]# mv jdk1.6.0_14/ /usr/local/jdk1.6

[root@amoeba local]# vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

[root@amoeba local]# source /etc/profile
[root@amoeba local]# java -version

2.設定Amoeba
[root@amoeba local]# cd /opt
[root@amoeba opt]# mkdir /usr/local/amoeba
[root@amoeba opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba opt]# chmod -R 755 /usr/local/amoeba/
[root@amoeba opt]# /usr/local/amoeba/bin/amoeba
##設定 Amoeba讀寫分離,兩個 Slave 讀負載均衡##
先將一主兩從開放授權
grant all on *.* to test@'192.168.80.%' identified by '123.com';
#再回到amoeba伺服器設定amoeba服務:
[root@amoeba opt]# cd /usr/local/amoeba/conf/
[root@amoeba opt]# cp amoeba.xml amoeba.xml.bak
[root@amoeba opt]# vim amoeba.xml		
--30行--
<property name="user">amoeba</property>
--32行-- 
<property name="password">123456</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉註釋-
<property name="writePool">master</property>
<property name="readPool">slaves</property>

:wq
--------------------------------------------------------------
[root@amoeba opt]# cp dbServers.xml dbServers.xml.bak
[root@amoeba opt]# vim dbServers.xml
--23行--註釋掉  作用:預設進入test庫 以防mysql中沒有test庫時,會報錯
<!-- <property name="schema">test</property> -->
--26--修改
<property name="user">test</property>
--28-30--去掉註釋
<property name="password">123.com</property>
--45--修改,設定主伺服器的名Master
<dbServer name="master"  parent="abstractServer">
--48--修改,設定主伺服器的地址
<property name="ipAddress">192.168.80.10</property>
--52--修改,設定從伺服器的名slave1
<dbServer name="slave1"  parent="abstractServer">
--55--修改,設定從伺服器1的地址
<property name="ipAddress">192.168.80.11</property>
--58--複製上面6行貼上,設定從伺服器2的名slave2和地址
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.80.12</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>

[root@amoeba opt]# /usr/local/amoeba/bin/amoeba start&    後臺啟動amoeba	
[root@amoeba opt]# netstat -anpt | grep java

實驗截圖

1.設定java環境

2.設定amoeba

先設定mysql一主兩從開放授權

grant all on *.* to test@'192.168.80.%' identified by '123.com';



讀寫分離測試

主機通過Navicat連線資料庫

主伺服器上建立表

從1從2關閉主從複製

在slave1插入資料

在slave2插入資料

在master插入資料

Navicat檢視表資料

關閉表重新整理一次,在開啟表test

插入一條資料

主檢視資料

從1檢視資料

從2檢視資料

只有主能檢視到插入的資料。

從2開啟主從複製

可以看到使用者端和主之前插入的資料了。

再次開啟使用者端檢視,還是存在兩種表記錄的情況。

主伺服器上還是隻有使用者端與主插入的資料。