Mysql-主從複製與讀寫分離

發表於2022-06-05

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服務相關配置
image
2.mysql配置檔案
image
[mysqld]下加入
image

mysql從節點配置:

1.ntp時間同步設定
image
2.mysql配置
image

主從複製效果驗證:

image
image
image

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環境
image
2.配置amoeba
image
先配置mysql一主兩從開放授權

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

讀寫分離測試

主機通過Navicat連線資料庫
image
主伺服器上建立表
image
從1從2關閉主從複製
image
在slave1插入資料
image
在slave2插入資料
image
在master插入資料
image
Navicat檢視錶資料
image
關閉表重新整理一次,在開啟表test
image
插入一條資料
image
主檢視資料
image
從1檢視資料
image
從2檢視資料
image
只有主能檢視到插入的資料。

從2開啟主從複製
image
可以看到客戶端和主之前插入的資料了。
image
再次開啟客戶端檢視,還是存在兩種表記錄的情況。
image
主伺服器上還是隻有客戶端與主插入的資料。
image

相關文章