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