Mysql-主從複製與讀寫分離
Mysql-主從複製與讀寫分離
1.MySQL主從複製與讀寫分離
1.1主從複製與讀寫分離
mysql使用主從複製的原因大概由一下三點:
1、在業務複雜的系統中,有這麼一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那麼就很影響運行中的業務,使用主從複製,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。
2、做數據的熱備
3、架構的擴展。業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁碟I/O訪問的頻率,提高單個機器的I/O性能。
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,才會提交事務。
主庫的事務提交依賴於後面所有的從庫,這樣一來性能就會明顯得下降
除非是對所有從庫數據一致性要求非常高的場景,否則我們一般不採用這種策略
全同步複製的數據一致性最好,但是性能也是最差的
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打開主從複製

可以看到客戶端和主之前插入的數據了。

再次打開客戶端查看,還是存在兩種表記錄的情況。

主伺服器上還是只有客戶端與主插入的數據。


