Mysql-主從複製與讀寫分離

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

Tags: