1. 程式人生 > 實用技巧 >Mysql主從複製原理

Mysql主從複製原理

轉自微信

主從複製簡介

在實際的生產中,為了解決Mysql的單點故障已經提高MySQL的整體服務效能,一般都會採用「主從複製」

比如:在複雜的業務系統中,有一句sql執行後導致鎖表,並且這條sql的的執行時間有比較長,那麼此sql執行的期間導致服務不可用,這樣就會嚴重影響使用者的體驗度。

主從複製中分為「主伺服器(master)「和」從伺服器(slave)」「主伺服器負責寫,而從伺服器負責讀」,Mysql的主從複製的過程是一個「非同步的過程」

這樣讀寫分離的過程能夠是整體的服務效能提高,即使寫操作時間比較長,也不影響讀操作的進行。

主從複製的原理

首先放一張Mysql主從複製的原理圖,總的來說Mysql的主從複製原理還是比較好理解的,原理非常的簡單。

Mysql的主從複製中主要有三個執行緒:master(binlog dump thread)、slave(I/O thread 、SQL thread),Master一條執行緒和Slave中的兩條執行緒。

master(binlog dump thread)主要負責Master庫中有資料更新的時候,會按照binlog格式,將更新的事件型別寫入到主庫的binlog檔案中。

並且,Master會建立log dump執行緒通知Slave主庫中存在資料更新,這就是為什麼主庫的binlog日誌一定要開啟的原因。

I/O thread執行緒在Slave中建立,該執行緒用於請求Master,Master會返回binlog的名稱以及當前資料更新的位置、binlog檔案位置的副本。

然後,將binlog儲存在「relay log(中繼日誌)」中,中繼日誌也是記錄資料更新的資訊。

SQL執行緒也是在Slave中建立的,當Slave檢測到中繼日誌有更新,就會將更新的內容同步到Slave資料庫中,這樣就保證了主從的資料的同步。

以上就是主從複製的過程,當然,主從複製的過程有不同的策略方式進行資料的同步,主要包含以下幾種:

  1. 「同步策略」:Master會等待所有的Slave都回應後才會提交,這個主從的同步的效能會嚴重的影響。
  2. 「半同步策略」:Master至少會等待一個Slave迴應後提交。
  3. 「非同步策略」:Master不用等待Slave迴應就可以提交。
  4. 「延遲策略」:Slave要落後於Master指定的時間。

對於不同的業務需求,有不同的策略方案,但是一般都會採用最終一致性,不會要求強一致性,畢竟強一致性會嚴重影響效能。

主從搭建

下面我們就來實操搭建主從,使用的是兩臺centos7並且安裝的是Mysql 8來搭建主從,有一臺centos 7然後直接克隆就行了。

(1)首先檢查centos 7裡面的Mysql安裝包和依賴包:

rpm-qa|grepmysql

執行後,在我本機上的顯示如下:

(2)接著可以刪除上面的安裝包和依賴包:

sudoyumremovemysql*

(3)繼續檢查一下是否存在Mariadb,若是存在直接刪除Mariadb

//檢查是否存在Mariadb
rpm-qa|grepmariadb
//刪除Mariadb
sudorpm-e--nodepsmariadb-libs-5.5.56-2.el7.x86_64

(4)然後,就是刪除Mysql的配置檔案,可以使用下面的命令查詢Msqyl配置檔案的路徑:

sudofind/-namemysql

在我本機上的顯示的Mysql配置檔案的路徑如下:

(5)然後,通過下面的命令,將他們逐一刪除:

sudorm-rf/usr/lib64/mysql
......

(6)接著就開始安裝Mysql 8了,使用wget命令下載Mysql 8的repo源,並且執行安裝:

wgethttps://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm
sudoyum-yinstallmysql80-community-release-el7-3.noarch.rpm

安裝完後會在/etc/yum.repos.d/目錄下生成下面的兩個檔案,說明安裝成功了:

mysql-community.repo
mysql-community-source.repo

-

(7)安裝完Mysql8後,接著來更新一下yum源,並且檢視yum倉庫中的Mysql:

//更新yum源
yumcleanall
yummakecache
//檢視yum倉庫中的Mysql
yumlist|grepmysql

(8)可以檢視到倉庫中存在mysql-community-server.x86_64,直接安裝就行了:

sudoyum-yinstallmysql-community-server

(9)接著啟動Mysql,並檢查Mysql的狀態:

//啟動Mysql
systemctlstartmysqld.service
//檢查Mysql的狀態
systemctlstatusmysqld

確保檢視Mysql的狀態是active(running),表示正在執行,並且配置一下Mysql開機啟動:

systemctlenablemysqld

(10)因為Mysql是新安裝的,所以要修改一下初始密碼,先檢視一下初始密碼:

grep"password"/var/log/mysqld.log

你可能找出來有多個,可能是你之前安裝解除安裝後的檔案沒有刪乾淨,這裡你就直接看時間,時間對應你現在的時間,就是你的初始密碼:

(11)然後使用初始密碼,登陸資料庫,並且修改密碼:

mysql-uroot-p
ALTERUSER'root'@'localhost'IDENTIFIEDBY'LDCldc@123095;

(12)此時在建立一個可以用於給兩一臺centos連線的使用者,預設的root使用者只有本機才能連線:

//建立連線使用者
createuser'test'@'%'identifiedby'LDCldc-2020';
//並且把防火牆給關了,或者配置一下3306埠
systemctl stop firewalld.service;
//設定防火牆開機自動關閉
systemctldisablefirewalld.service;

(13)測試:到這裡就Mysql的安裝教程就就講完了,可以測試一下,兩臺centos是否可以ping通:

ping192.168.163.156

我這裡的兩臺機是可以互通的,Master:192.168.163.156,Slave:192.168.163.155,並且Slave使用下面的命令可以登陸到Master的Mysql:

mysql-u[user]-p[密碼]-h[遠端主機ip]

確保了這兩項測試成功後,就可以進行下面的主從搭建了。

(14)我這裡使用的使用兩臺centos 7的vmware的ip分別是192.168.163.155(Slave)192.168.163.156(Master)作為測試,首先在192.168.163.156(Master)中建立一個測試庫test:

//建立測試庫
createdatabasetestdefaultcharactersetutf8mb4collateutf8mb4_general_ci;
//並且授權
grantallprivilegesontest.*to'test'@'%';

(15)然後編輯Master中的my.cnf檔案,此檔案位於/etc/my.cnf,執行下面的sql,並新增下面的資訊:

sudovi/etc/my.cnf

==========以下是配置檔案中的資訊=============
#配置編碼為utf8
character_set_server=utf8mb4
init_connect='SETNAMESutf8mb4'

#配置要給Slave同步的資料庫
binlog-do-db=test
#不用給Slave同步的資料庫,一般是Mysql自帶的資料庫就不用給Slave同步了
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
binlog-ignore-db=sys
#自動清理30天前的log檔案
expire_logs_days=30
#啟用二進位制日誌
log-bin=mysql-bin
# Master的id,這個要唯一,唯一是值,在主從中唯一
server-id=3

(16)配置完後重啟Mysql服務,並檢視Mysql的log_bin日誌是否啟動成功:

systemctlrestartmysqld
#檢視log_bin日誌是否啟動成功
showvariableslike'%log_bin%';

(17)接著檢視Master的狀態:

showmasterstatus;

這兩個資料FilePosition要記住,後面配置Slave的時候要使用到這兩個資料。

(18)最後登陸Master的資料庫,並建立一個使用者用於同步資料:

createuser'backup'@'%'IDENTIFIEDBY'LDCldc-2020';
grantfileon*.*to'backup'@'%';
GRANTREPLICATIONSLAVE,REPLICATIONCLIENTON*.*to'backup'@'%';

到這裡Master的配置就配置完了,後面就進行Slave的配置。

(19)在Slave中同樣要建立test資料庫,並且授權給test使用者:

#建立同步資料的test資料庫
createdatabasetestdefaultcharactersetutf8mb4collateutf8mb4_general_ci;
#授權
grantallprivilegesontest.*to'test'@'%';

(20)接著編輯Slave中my.cnf檔案,同樣是在/etc/my.cnf路徑下,加入如下配置:

#配置從伺服器的ID,唯一的
server-id=4
#加上以下引數可以避免更新不及時,SLAVE 重啟後導致的主從複製出錯。
read_only=1
master_info_repository=TABLE
relay_log_info_repository=TABLE

(21)並且重啟Slave中的Mysql服務:

systemctlrestartmysqld

(22)在Slave中新增Master的資訊:

#master_host是Master的ip,master_log_file和master_log_pos就是配置之前檢視Master狀態時顯示的File和Position資訊
changemastertomaster_host='192.168.163.156',master_port=3306,master_user='backup',master_password='LDCldc-2020',master_log_file='mysql-bin.000001',master_log_pos=1513;

(23)最後檢視Slave的狀態:

showslavestatus\G

當看到Slave_IO_RunningSlave_SQL_Running都是yes的時候,這表示主從配置成功。

「Slave_IO_Running也就是Slave中的IO執行緒用於請求Master,Slave_SQL_Running時sql執行緒將中繼日誌中更新日誌同步到Slave資料庫中。」

但是,有時候Slave_IO_Running會為no,而Slave_SQL_Running為yes,這時候需要檢查一下原因,因為我自己初次搭建的時候,也是出現這個問題。

首先看重啟一下Slave的MySQL服務:systemctl restart mysqld,然後執行:

stopslave;
startslave;

這樣就能夠使Slave_IO_RunningSlave_SQL_Running顯示都是yes了。

(24)最後就是測試了,測試使用的是之前建立的test庫,Master是用來寫的,在Master的test庫中隨機建立一個表,你會發現Slave也會有這個表,插入資料也一樣,都會被同步到Slave中。

主從面試

Mysql主從有什麼優點?為什麼要選擇主從?

  1. 高效能方面:主從複製通過水平擴充套件的方式,解決了原來單點故障的問題,並且原來的併發都集中到了一臺Mysql伺服器中,現在將單點負載分散到了多臺機器上,實現讀寫分離,不會因為寫操作過長鎖表而導致讀服務不能進行的問題,提高了伺服器的整體效能。
  2. 可靠性方面:主從在對外提供服務的時候,若是主庫掛了,會有通過主從切換,選擇其中的一臺Slave作為Master;若是Slave掛了,還有其它的Slave提供讀服務,提高了系統的可靠性和穩定性。

若是主從複製,達到了寫效能的瓶頸,你是怎麼解決的呢?

主從模式對於寫少讀多的場景確實非常大的優勢,但是總會寫操作達到瓶頸的時候,導致效能提不上去。

這時候可以在設計上進行解決採用分庫分表的形式,對於業務資料比較大的資料庫可以採用分表,使得資料表的儲存的資料量達到一個合理的狀態。

也可以採用分庫,按照業務進行劃分,這樣對於單點的寫,就會分成多點的寫,效能方面也就會大大提高。

主從複製的過程有資料延遲怎麼辦?導致Slave被讀取到的資料並不是最新資料。

主從複製有不同的複製策略,對於不同的場景的適應性也不同,對於資料的實時性要求很高,要求強一致性,可以採用同步複製策略,但是這樣就會效能就會大打折扣。

若是主從複製採用非同步複製,要求資料最終一致性,效能方面也會好很多。只能說,對於資料延遲的解決方案沒有最好的方案,就看你的業務場景中哪種方案使比較適合的。