詳解MySQL主從復制及讀寫分離
前言
在企業實際應用中,成熟的業務通常數據量都比較大,而單臺MySQL服務器在安全性、高可用性和高並發方面都無法滿足實際的需求,我們可以在多臺MySQL服務器(Master-Slave)部署 主從復制來實現同步數據,再通過 讀寫分離來提升數據庫的並發負載能力。有點類似於rsync,但是不同的是rsync是對磁盤文件做備份,而mysql主從復制是對數據庫中的數據、語句做備份。
一、相關概述
主從復制:主數據庫(Master)發送更新事件到從數據庫(Slave),從數據庫讀取更新記錄,並執行更新記錄,使得從數據庫的內容與主數據庫保持一致。
(一)MySQL 支持的復制類型
- 基於語句的復制(STATEMENT)。在主庫上執行的 SQL 語句,在從庫上執行同樣的語句。MySQL 默認采用基於語句的復制,效率比較高。
- 基於行的復制(ROW)。把改變的內容復制過去,而不是把命令在從庫上執行一遍。
- 混合類型的復制(MIXED)。默認采用基於語句的復制,一旦發現基於語句無法精確復制時,就會采用基於行的復制。
(二)MySQL主從復制的工作過程
1.Master 服務器保存記錄到二進制日志
- MySQL主庫上進行的增、刪、改的數據更新,都會按順序寫入到自己的二進制日志(Binary log)當中
2.Slave 服務器復制Master 服務器的日志
- 然後MySQL從庫開始一個I/O線程連接主庫,讀取主庫的二進制日志,備份到從服務器的==中繼日志(Relay log)==當中。如果已經跟上主庫,它會睡眠並等待Master 產生新的事件,I/O線程將這些事件寫入中繼日志
3.Slave 服務器重放復制過來的日志
- 然後從庫打開SQL線程,SQL線程讀取I/O線程寫入的中繼日志,並且根據中繼日志的內容更新從庫的數據,使其與主庫中的數據一致
重點:復制過程有一個很重要的限制,即復制在 Slave 上是串行化的,也就是說Master 上的並行更新操作不能在 Slave 上並行操作
二、讀寫分離
(1)讀寫分離的概念
讀寫分離:讀寫分離就是隻在主服務器上寫,隻在從服務器上讀。基本的原理是讓主數據庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從數據庫處理SELECT查詢操作。數據庫復制被用來把事務性操作導致的變更同步到集群中的從數據庫。
(2)讀寫分離的作用
- 因為數據庫的”寫”(寫10000條數據可能要3分鐘)操作是比較耗時的。但是數據庫的”讀”(讀10000條數據可能隻要5秒鐘)。
- 所以讀寫分離,解決的是,數據庫的寫入,影響瞭查詢的效率。註意:數據庫不一定要讀寫分離,如果程序使用數據庫較多時,而更新少,查詢多的情況下會考慮使用。利用數據庫主從同步,再通過讀寫分離可以分擔數據庫壓力,提高性能
(3)MySQL 讀寫分離原理
- 讀寫分離就是隻在主服務器上寫,隻在從服務器上讀
- 基本的原理是讓主數據庫處理事務性查詢,而從數據庫處理 select 查詢
- 數據庫復制被用來把主數據庫上事務性查詢導致的變更同步到集群中的從數據庫
(4)常見的 MySQL 讀寫分離
1)基於程序代碼內部實現
1.在代碼中根據 select、insert 進行路由分類,這類方法也是目前生產環境應用最廣泛的。
2.優缺點:
- 優點是性能較好,因為在程序代碼中實現,不需要增加額外的設備為硬件開支;
- 缺點是需要開發人員來實現,運維人員無從下手。
3.並不是所有的應用都適合在程序代碼中實現讀寫分離,像一些大型復雜的Java應用,如果在程序代碼中實現讀寫分離對代碼改動就較大。
2)基於中間代理層實現
1.代理一般位於客戶端和服務器之間,代理服務器接到客戶端請求後通過判斷後轉發到後端數據庫,有以下代表性程序:
- MySQL-Proxy:MySQL-Proxy 為 MySQL 開源項目,通過其自帶的 lua 腳本進行SQL 判斷。
- Atlas:是由奇虎360的Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的數據中間層項目。它是在mysql-proxy 0.8.2版本的基礎上,對其進行瞭優化,增加瞭一些新的功能特性。360內部使用Atlas運行的mysql業務,每天承載的讀寫請求數達幾十億條。支持事物以及存儲過程。
- Amoeba:由陳思儒開發,作者曾就職於阿裡巴巴。該程序由Java語言進行開發,阿裡巴巴將其用於生產環境。但是它不支持事務和存儲過程。
2.由於使用MySQL Proxy需要寫大量的Lua腳本,這些Lua腳本不是現成的,而需要自己編寫,這對於並不熟悉MySQL Proxy內置變量和MySQL Protocol的人來說是非常困難的。
3.Amoeba是一個非常容易使用,可移植性非常強的軟件,因此它在生產環境中被廣泛用於數據庫的代理層。
三、MySQL主從復制實驗部署
需要的相關軟降包
amoeba-mysql-binary-2.2.0.tar.gz
jdk-6u14-linux-x64.bin
mysql壓縮包
(1)主從復制實驗步驟及準備
實驗步驟
第一步:客戶端client訪問代理服務器amoeba
第二步:代理服務器讀寫判斷
寫操作:寫入到主服務器
第三步:主服務器將增刪改寫入自己二進制日志
第四步:從服務器將主服務器的二進制日志同步至自己中繼日志
第五步:從服務器重放中繼日志到數據庫中
讀操作:直接訪問從服務器
最終結果:降低負載,起到負載均衡作用
主機 操作系統 IP地址 所需工具/軟件/安裝包
Amoeba CentOS7 | 192.168.71.10 | jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz |
Master CentOS7 | 192.168.71.12 | ntp 、 mysql-boost-5.7.20.tar.gz |
Slave1 CentOS7 | 192.168.71.13 | ntp 、ntpdate 、 mysql-boost-5.7.20.tar.gz |
Slave2 CentOS7 | 192.168.71.14 | ntp 、ntpdate 、mysql-boost-5.7.20.tar.gz |
客戶端 CentOS7 | 192.168.71.15 |
1.關閉防火墻及安全機制
四臺服務器都要關閉
systemctl stop firewalld systemctl disable firewalld setenforce 0
2.安裝時間同步服務ntp
(1)主服務器
yum -y install ntp vim /etc/ntp.conf ##---------末尾添加--------- server 127.127.71.0 #設置本地是時鐘源,註意修改網段 fudge 127.127.71.0 stratum 8 #設置時間層級為8(限制在15內) service ntpd start
(2)兩個從服務器
yum -y install ntp ntpdate service ntpd start /usr/sbin/ntpdate 192.168.71.12 #進行時間同步,指向Master服務器IP crontab -e #設置計劃任務每個半個小時同步一次時間 */30 * * * * /usr/sbin/ntpdate 192.168.71.12
3.主服務器的mysql配置
vim /etc/my.cnf server-id = 1 log-bin=master-bin #添加,主服務器開啟二進制日志 log-slave-updates=true #添加,允許從服務器更新二進制日志 systemctl restart mysqld mysql -u root -p grant replication slave on *.* to 'myslave'@'192.168.71.%' identified by '123'; #對從服務器提權 #grant 授權 #replication 復制 #允許網段為192.168.71的使用密碼123對所有表庫都可以復制 flush privileges; show master status; #File 列顯示日志名,Fosition 列顯示偏移量
4.從服務器的mysql配置
Slave1服務器:192.168.163.13
Slave2服務器:192.168.163.14
1)修改配置文件
vim /etc/my.cnf #修改,註意id與Master的不同,兩個Slave的id也要不同 server-id = 2 #添加,開啟中繼日志,從主服務器上同步日志文件記錄到本地 relay-log=relay-log-bin #添加,定義中繼日志文件的位置和名稱 relay-log-index=slave-relay-bin.index systemctl restart mysqld
slave1
slave2
2)從服務器 對數據庫進行操作
mysql -u root - p123 change master to master_host='192.168.71.12',master_user='myslave',master_password='123',master_log_file='master-bin.000002',master_log_pos=306; #show master status;所輸出的二進制文件和位置點一樣 #配置同步,註意master_log_file 和master_log_pos的值要與Master查詢的一致 start slave; #啟動同步,如有報錯執行reset slave; show slave status\G; #查看Slave 狀態 //確保 IO 和 SQL 線程都是Yes,代表同步正常。 Slave_IO_Running:Yes #負責與主機的io通信 Slave_SQL_Running:Yes #負責自己的slave mysql進程
5.驗證結果
主服務器上創建一個庫驗,在從服務器上查看
四、MySQL讀寫分離實驗
Amoeba服務器(192.168.153.30)
安裝Java 環境
因為Amoeba 基於是jdk1.5 開發的,所以官方推薦使用jdk1.5或1.6版本,高版本不建議使用。
1)創建jdk java環境
cd /opt/ #將jdk-6u14-linux-x64.bin 和 amoeba-mysql-binary-2.2.0.tar.gz上傳到/opt目錄下 cp jdk-6u14-linux-x64.bin /usr/local/ cd /usr/local/ chmod +x jdk-6u14-linux-x64.bin ./jdk-6u14-linux-x64.bin //按yes,按enter mv jdk1.6.0_14/ /usr/1ocal/jdk1.6 vim /etc/profile export JAVA_HOME=/usr/local/jdk1.6 export CLASSPATH=SCLASSPATH:$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 java -version
2)安裝 Amoeba軟件
mkdir /usr/local/amoeba tar zxvf /opt/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 說明安裝成功
3)在主從服務器的mysql上授權
Master服務器:192.168.71.12
Slave1服務器:192.168.71.13
Slave2服務器:192.168.71.14
先在Master、Slave1、Slave2 的mysql上開放權限給 Amoeba 訪問
grant all on *.* to 'test'@'192.168.163.%' identified by 'abc123';
4)配置amoeba服務在阿米巴上配置
cd /usr/local/amoeba/conf/ cp amoeba.xml amoeba.xml.bak #對配置文件備份 vim amoeba.xml #修改amoeba配置文件 <property name="user">amoeba</property> #30行修改 <property name="password">abc123</property> #32行修改 客戶端連接amoeba服務器的密碼 <property.name="defaultPool">master</property> #115行修改 設置默認池 <property name="writePool">master</property> #117行去掉註釋 設置master為寫池 <property name="readPool">slaves</property> #slaves 為讀池
cp dbServers.xml dbServers.xml.bak vim dbServers.xml #修改數據庫配置文件 <!-- <property name="schema"> test</property> --> #23行,註釋掉 作用: 默認進入test庫以防mysql 中沒有test庫時,會報錯 <property name="user">test</property> #26行,修改主從服務器上提權的用戶和密碼 <property.name-"password">123</property> #28-30行,去掉註釋 <dbServer name= "master" parent="abstractServer"> #45行,修改,設置主服務器的名Master <property name= "ipAddress">192.168.71.12</property> #48行,修改,設置主服務器的地址 <dbServer name="slave1" parent="abstractServer"> #52行,修改,設置從服務器的名slave1 <property.name="ipAddress">192.168.71.13</property> #55行,修改,設置從服務器1的地址 <dbServer name="slave2 " parent="abstractserver"> #59行,復制上面6行粘貼,設置從服務器2的名slave2和地址 <property, name="ipAddress">192.168.71.14</property> <dbServer name="slaves" virtual="true"> #65行,修改 <property name="poolNames">slave1,slave2</property> #71行,修改 /usr/local/amoeba/bin/amoeba start& #啟動Amoeba軟件,按ctrl+c 返回 netstat -anpt | grep java #查看8066端口是否開啟,默認端口為TCP 8066
5)測試讀寫分離
在客戶端服務器上測試
yum install -y mysql mysql-server #快速安裝mysql,也可以選擇編譯安裝 mysql -u amoeba -pabc123 -h 192.168.71.20 -P8066
主從服務 v器上都可以看到該表
通過amoeba服務器代理訪問mysql ,在通過客戶端連接mysql後寫入的數據隻有主服務會記錄,然後同步給從服務器
stop slave; #關閉同步寫入數據 use school; //在slave1上: insert into test1 values('1','slave1'); //在slave2上: insert into test1 values('2','slave2');
在主服務器上插入數據
insert into test1 values('3','master');
在客戶端中向表插入數據
//在客戶端服務器上: use school; select * from test1; //客戶端會分別向slave1和s1ave2讀取數據,顯示的隻有在兩個從服務器上添加的數據,沒有在主服務器上添加的數據 insert into test1 values('4','climet'); //隻有主服務器上有此數據
在主服務器上查看數據
同時開啟兩個從服務器,查看表格記錄
到此這篇關於詳解MySQL主從復制及讀寫分離的文章就介紹到這瞭,更多相關MySQL主從復制及讀寫分離內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Mysql數據庫的主從復制與讀寫分離精講教程
- 從mysql讀寫分離著手提升服務器性能
- MySQL 搭建主從同步實現操作
- MySQL主從配置及haproxy和keepalived搭建過程解析
- ARM64架構下安裝mysql5.7.22的全過程