Categories
程式開發

MySQL-技術專題-主從復制原理


主從復制簡介

生產中,為了解決Mysql的單點故障已經提高MySQL的整體服務性能,一般都會採用「主從復制」。

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

主從復制中分為「主服務器(master)「和」從服務器(slave)」,「主服務器負責寫,而從服務器負責讀」,Mysql的主從復制的過程是一個「異步的過程」。

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

主從復制的原理

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

MySQL-技術專題-主從復制原理 1

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數據庫中,這樣就保證了主從的數據的同步。

以上就是主從復制的過程,當然,主從復制的過程有不同的策略方式進行數據的同步,主要包含以下幾種:

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

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

主從搭建

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

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

rpm -qa |grep mysql

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

MySQL-技術專題-主從復制原理 2

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

sudo yum remove mysql*

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

// 检查是否存在Mariadb
rpm -qa |grep mariadb
// 删除Mariadb
sudo rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_64

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

sudo find / -name mysql

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

MySQL-技術專題-主從復制原理 3

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

sudo rm -rf /usr/lib64/mysql
......

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

wget https://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm
sudo yum -y install mysql80-community-release-el7-3.noarch.rpm

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

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

MySQL-技術專題-主從復制原理 4

圖片

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

// 更新yum源
yum clean all
yum makecache
// 查看yum仓库中的Mysql
yum list | grep mysql

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

sudo yum -y install mysql-community-server

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

// 启动Mysql
systemctl start mysqld.service
// 检查Mysql的状态
systemctl status mysqld

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

systemctl enable mysqld

MySQL-技術專題-主從復制原理 5

圖片

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

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

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

MySQL-技術專題-主從復制原理 6

圖片

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

mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY '[email protected];

(12)此時在創建一個可以用於給兩一台centos連接的用戶,默認的root用戶只有本機才能連接:

// 创建连接用户
create user 'test'@'%' identified by 'LDCldc-2020';
// 并且把防火墙给关了,或者配置一下3306端口
systemctl stop firewalld.service;
// 设置防火墙开机自动关闭
systemctl disable firewalld.service;

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

ping 192.168.163.156

MySQL-技術專題-主從復制原理 7

圖片

我這裡的兩台機是可以互通的,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:

// 创建测试库
create database test default character set utf8mb4 collate utf8mb4_general_ci;
// 并且授权
grant all privileges on test.* to 'test'@'%';

(15)然後編輯Master中的my.cnf文件,此文件位於/etc/my.cnf,執行下面的sql,並添加下面的信息:

sudo vi /etc/my.cnf

==========以下是配置文件中的信息=============
# 配置编码为utf8
character_set_server=utf8mb4
init_connect="SET NAMES utf8mb4"

# 配置要给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日誌是否啟動成功:

systemctl restart mysqld
# 查看log_bin日志是否启动成功
show variables like '%log_bin%';

MySQL-技術專題-主從復制原理 8

(17)接著查看Master的狀態:

show master status;

MySQL-技術專題-主從復制原理 9

圖片

這兩個數據File和Position要記住,後面配置Slave的時候要使用到這兩個數據。

(18)最後登陸Master的數據庫,並創建一個用戶用於同步數據:

create user 'backup'@'%' IDENTIFIED BY 'LDCldc-2020';
grant file on *.* to 'backup'@'%';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'backup'@'%';

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

(19)在Slave中同樣要創建test數據庫,並且授權給test用戶:

# 创建同步数据的test数据库
create database test default character set utf8mb4 collate utf8mb4_general_ci;
# 授权
grant all privileges on test.* 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服務:

systemctl restart mysqld

(22)在Slave中添加Master的信息:

# master_host是Master的ip,master_log_file和master_log_pos就是配置之前查看Master状态时显示的File和Position信息
change master to master_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的狀態:

show slave statusG

MySQL-技術專題-主從復制原理 10

圖片

當看到Slave_IO_Running和Slave_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,然後執行:

stop slave;
start slave;

這樣就能夠使Slave_IO_Running和Slave_SQL_Running顯示都是yes了。

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

主從面試

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

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

❝若是主從復制,達到了寫性能的瓶頸,你是怎麼解決的呢?❞

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

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

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

❝主從復制的過程有數據延遲怎麼辦?導致Slave被讀取到的數據並不是最新數據。❞

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

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