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 #登入mysqlmysql> 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.cnfserver-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 -pmysql> 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/profileexport JAVA_HOME=/usr/local/jdk1.6export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/libexport PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATHexport AMOEBA_HOME=/usr/local/amoebaexport PATH=$PATH:$AMOEBA_HOME/bin
[root@amoeba local]# source /etc/profile[root@amoeba local]# java -version2.配置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打開主從複制
可以看到用戶端和主之前插入的資料了。
再次打開用戶端檢視,還是存在兩種表記錄的情況。
主伺服器上還是隻有用戶端與主插入的資料。