串列埠應用:傳送資料
一、MySQL主從複製的理論
1、mysql支援的複製型別
STATEMENT∶基於語句的複製。在伺服器上執行sql語句,在從伺服器上執行同樣的語句,mysql預設採用基於語句的複製,執行效率高。
ROW∶ 基於行的複製。把改變的內容複製過去, 而不是把命令在從伺服器上執行一遍。
MIXED∶混合型別的複製。預設採用基於語句的複製,一旦發現基於語句無法精確複製時,就會採用基於行的複製。
2、主從複製的工作過程(主寫從複製)
主伺服器在更新資料前,會寫入二進位制日誌
從伺服器開啟I/O執行緒,Master節點為每個I/O執行緒啟動一個dump執行緒用於傳送二進位制事件到從伺服器的中繼日誌中
從伺服器的sql執行緒開啟,讀取中繼日誌,並且進行重放,從而實現與主伺服器的資料一致
- 首先client端(tomcat)將資料寫入到master節點的資料庫中,master節點會通知儲存引擎提交事務,同時會將資料以(基於行、基於sql、基於混合)的方式儲存在二進位制日誌中
- SLAVE節點會開啟I/O執行緒,用於監聽master的二進位制日誌的更新,一旦發生更新內容,則向master的dump執行緒發出同步請求
- master的dump執行緒在接收到SLAVE的I/O請求後,會讀取二進位制檔案中更新的資料,併發送給SLAVE的I/O執行緒
- SLAVE的I/O執行緒接收到資料後,會儲存在SLAVE節點的中繼日誌中
- 同時,SLAVE節點鐘的SQL執行緒,會讀取中繼日誌鐘的資料,更新在本地的mysql資料庫中
- 最終,完成slave——>複製master資料,達到主從同步的效果
核心重點
- 兩個日誌:二進位制和中繼日誌
- 三個執行緒:master的dump和alave的I/O、SQL
主要原理: master將資料儲存在二進位制檔案中,I/O向dump發出同步請求,dump把資料傳送給I/O執行緒,I/O寫入本地的中繼日誌,SQL執行緒讀取本地的中繼日誌資料,同步到自己的資料庫中,完成同步。
3、MySQL主從複製延遲
master伺服器高併發,形成大量事務
網路延遲
主從硬體裝置導致
cpu主頻、記憶體io、硬碟io
本來就不是同步複製、而是非同步複製
從庫優化Mysql引數。比如增大innodb_buffer_pool_size,讓更多操作在Mysql記憶體中完 成,減少磁碟操作。
從庫使用高效能主機。包括cpu強悍、記憶體加大。避免使用虛擬雲主機,使用物理主機,這樣提升了i/o方面性。
從庫使用SSD磁碟
網路優化,避免跨機房實現同步
4、MySOL主從複製模式
非同步複製(Asynchronous replication)
MySQL預設的複製即是非同步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果crash掉了,此時主上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升為主,可能導致新主上的資料不完整。
全同步複製(Fully synchronous replication)
指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因為需要等待所有從庫執行完該事務才能返回,所以全同步複製的效能必然會收到嚴重的影響。
半同步複製(Semisynchronous replication)
介於非同步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於非同步複製,半同步複製提高了資料的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網路中使用。
二、MySQL讀寫分離的理論
1、MySQL讀寫分離的概念和原理
讀寫分離基本的原理是讓主資料庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從資料庫處理SELECT查詢操作。資料庫複製被用來把事務性操作導致的變更同步到叢集中的從資料庫。
讀寫分離就是隻在主伺服器上寫,只在從伺服器上讀。基本的原理是讓主資料庫處理事務性查詢,而從資料庫處理select查詢。資料庫複製被用來把主資料庫上事務性查詢導致的變更同步到叢集中的從資料庫
2、進行讀寫分離的原因
因為資料庫的“寫”(寫10000條資料可能要3分鐘)操作是比較耗時的;
但是資料庫的“讀”(讀10000條資料可能只要5秒鐘);
所以讀寫分離,解決的是,資料庫的寫入,影響了查詢的效率
4、目前較為常見的MySQL讀寫分離
分為以下兩種:
1)基於程式程式碼內部實現.
在程式碼中根據select、 insert 進行路由分類,這類方法也是目前生產環境應用最廣泛的。
優點是效能較好,因為在程式程式碼中實現,不需要增加額外的裝置為硬體開支;缺點是需要開發人員來實現,運維人員無從下手
但是並不是所有的應用都適合在程式程式碼中實現讀寫分離,像一些大型複雜的Java應用,如果在程式程式碼中實現讀寫分離對程式碼改動就較大。
2)基於中間代理層實現
代理一般位於客戶端和伺服器之間,代理伺服器接到客戶端請求後通過判斷後轉發到後端資料庫,有以下代表性程式。
(1)MySQL-Proxy。 MySQL-Proxy 為MySQL開源專案,通過其自帶的lua指令碼進行SQL判斷。
(2) Atlas。是由奇虎360的Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的資料中間層專案。它是在mysql-proxy0.8.2版本的基礎上,對其進行了優化,增加了一些新的功能特性。
360內部使用Atlas執行的mysq1業務,每天承載的讀寫請求數達幾十億條。支援事物以及儲存過程。
(3) Amoeba。由陳思儒開發,作者曾就職於阿里巴巴。該程式由Java語言進行開發,阿里巴巴將其用於生產環境。但是它不支事務和儲存過程。
由於使用MySQL Proxy 需要寫大量的Lua腳木,這些Lua並不是現成的,而是需要自己去寫。這對於並不熟悉MySQL Proxy內建變數和MySQLProtocol的人來說是非常困難的
Amoeba是一個非常容易使用、可移植性非常強的軟體。因此它在生產環境中被廣泛應用於資料庫的代理層
三、MYSQL主從複製
1、NTP概述
NTP(Network Time Protocol)網路時間協議基於UDP,用於網路時間同步的協議,使網路中的計算機時鐘同步到UTC,再配合各個時區的偏移調整就能實現精準同步對時功能。
提供NTP對時的伺服器有很多,比如微軟的NTP對時伺服器,利用NTP伺服器提供的對時功能,可以使我們的裝置時鐘系統能夠正確執行。
2、搭建MYSQL主從複製的具體操作
2.1 環境準備
主伺服器:192.168.160.30
從伺服器1:192.168.160.40
從伺服器2:192.168.160.50
2.2 主伺服器設定
systemctl stop firewalld systemctl disable firewalld setenforce 0 #主從伺服器時間同步設定 yum -y install ntp ntpdate vim /etc/ntp.conf #末行新增 server 192.168.160.0 #設定本地是時鐘源,注意修改網段 fudge 192.168.160.0 stratum 8 #設定時間層級為8(限制在15內)
service ntpd start
server 190.168.160.0 #設定本地是時鐘源,注意修改網段 fudge 192.168.160.0 stratum 8 #設定時間層級為8(限制在15內)
vim /etc/my.cnf ##新增以下配置 server-id = 1 #修改伺服器id為1 log-bin=master-bin #新增,主伺服器開啟二進位制日誌 binlog_format = MIXED #新增,mysql支援的複製型別為MIXED log-slave-updates=true #新增,允許從伺服器更新二進位制日誌 systemctl restart mysqld.service #重啟伺服器 mysql -uroot -pabc123 GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.160.%' IDENTIFIED BY '123'; #新增授權,配置slave 訪問master的許可權,IP為slave伺服器IP,myslave為建立的mysql使用者名稱 FLUSH PRIVILEGES; #重新整理許可權 SHOW master status; #檢視主服務狀態,如下代表正確 +-------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+----------+--------------+------------------+-------------------+ | master-bin.000001 | 603 | | | | +-------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.01 sec) #File列顯示日誌名,Position 列顯示偏移量
2.3 從伺服器設定
vim /etc/my.cnf server-id = 2 #修改,注意id與Master的不同,兩個Slave的id也要不同 relay-log=relay-log-bin #新增,開啟中繼日誌,從主伺服器上同步日誌檔案記錄到本地 relay-log-index=slave-relay-bin.index #新增,定義中繼日誌檔案的位置和名稱
relay_log_recovery = 1 systemctl restart mysqld.servicemysql -u root -pabc123 ##配置同步,注意master_log_file和master_log_pos的值要與Master查詢的一致 change master to master_host='192.168.229.90' , master_user='myslave',master_password='12345',master_log_file='master-bin.000001',master_log_pos=604; start slave; #啟動同步,如有報錯執行reset slave; show slave status\G #檢視Slave狀態 #確保下面IO和SQL執行緒都是Yes,代表同步正常。 Slave_IO_Running: Yes #負責與主機的io通訊 Slave_SQL_Running: Yes #負責自己的slave mysql程序
一般Slave_IO_Running: No的可能性:
- 網路不通
- my. cnf配置有問題
- 密碼、file檔名、pos偏移量不對
- 防火牆沒有關閉
3、詳細步驟
3.1 主伺服器配置(192.168.160.30)
3.2 從伺服器配置1(192.168.160.40)
3.3 從伺服器2配置(192.168.160.50)
4、驗證
主伺服器
從伺服器1
從伺服器2
四、搭建MYSQL讀寫分離
1、搭建MySQL讀寫分離的操作步驟
1.1、環境準備
Master 伺服器: 192.168.160.30 mysql5.7
Slave1 伺服器: 192.168.160.40 mysql5.7
Slave2 伺服器: 192.168.160.50 mysql5.7
Amoeba 伺服器:192.168.160.60 JDK1.6、Amoeba
1.2 Amoeba伺服器設定
##安裝Java 環境#
因為Amoeba基於是jdk1.5 開發的,所以官方推薦使用jdk1.5 或1.6版本,高版本不建議使用。
cd /opt/ cp jdk-6u14-1inux-x64.bin /usr/local/ cd /usr/local/ chmod +x jdk-6u14-linux-x64 ./jdk-6u14-linux-x64.bin //按yes,按enter mv jdk1.6.0_14/ /usr/local/jdk1.6 vim /etc/profile.d/java.sh export JAVA_HOME=/usr/local/jdk1.6 export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin export AMOEBA_HOME=/usr/local/amoeba export PATH=$PATH:$AMOEBA_HOME/bin source /etc/profile.d/java.sh java -version
##安裝Amoeba軟體##
mkdir /usr/local/amoeba tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ chmod -R 755 /usr/local/amoeba/ /usr/local/amoeba/bin/amoeba / /如顯示amoeba start |stop說明安裝成功
##配置Amoeba讀寫分離,兩個Slave 讀負載均衡##
#先在Master、Slave1、 Slave2 的mysql上開放許可權給Amoeba 訪問
grant all on *.* to 'test'@'192.168.160.%' identified by '123';
cd /usr/local/amoeba/conf/ cp amoeba.xml amoeba.xml.bak vim amoeba.xml #修改amoeba配置檔案 --30行-- <property name="user">amoeba</property> --32行-- <property name="password">1234</property> --115行-- <property name="defaultPool">master</property> --117-去掉註釋- <property name= "writePool">master</property> <property name= "readPool">slaves</property> cp dbServers.xml dbServers.xml.bak vim dbServers.xml #修改資料庫配置檔案 --23行--註釋掉 作用:預設進入test庫 以防mysq1中沒有test庫時, 會報錯 <!-- <property name= "schema">test</property> --> --26--修改 <property name="user">test</property> --28-30--去掉註釋,然後再把28行註釋或刪除 <property name="password"> 123</property> --45--修改, 設定主伺服器的名Master <dbServer name="master" parent="abstractServer"> --48--修改,設定主伺服器的地址 <property name="ipAddress">192.168.160.30</property> --52--修改, 設定從伺服器的名slave1 <dbServer name="slave1" parent="abstractServer"> --55--修改,設定從伺服器1的地址 <property name="ipAddress">192.168.160.40</property> --58--複製.上面6行貼上,設定從伺服器2的名slave2和地址 <dbServer name="slave2" parent="abstractServer"> <property name="ipAddress">192.168.160.50</property> --65行--修改 <dbServer name="slaves" virtual="true"> --71行--修改 <property name="poolNames">slave1,slave2</property> /usr/local/amoeba/bin/amoeba start& #&表示交給後臺啟動 #啟動Amoeba軟體,按ctrl+c 返回 netstat -anpt | grep java #檢視8066埠是否開啟,預設埠為TCP 8066
1.3 測試讀寫分離
yum install -y mariadb-server mariadb systemctl start mariadb.service 在客戶端伺服器上測試: mysql -u amoeba -p1234 -h 192.168.160.60 -P8066 //通過amoeba伺服器代理訪問mysql,在通過客戶端連線mysql後寫入的資料只有主服務會記錄,然後同步給從--從伺服器
2、例項操作:搭建MySQL讀寫分離
1.1 Amoeba伺服器設定(192.168.160.60)
##安裝Java 環境#
##安裝Amoeba軟體##
##配置Amoeba讀寫分離,兩個Slave 讀負載均衡##
先在Master、Slave1、 Slave2 的mysql上開放許可權給Amoeba 訪問
grant all on *.* to 'test'@'192.168.160.%' identified by '1234';
#再回到amoeba伺服器配置amoeba服務
1.2 測試讀寫分離
在主服務上建立表並插入資料,並在客戶端以及從伺服器上查看錶
關閉slave1、slave2的同步,再分別插入資料,再次在客戶端檢視
再次在客戶端寫入資料,然後分別在主從伺服器上檢視