1. 程式人生 > 其它 >運維必懂的MySQL主從複製與讀寫分離解析和圖文詳細步驟

運維必懂的MySQL主從複製與讀寫分離解析和圖文詳細步驟

一、MySQL主從複製與讀寫分離

1.1 主從分離和讀寫分離的相關概述

1)主從複製與讀寫分離

在實質際的生產環境中,對資料庫的讀和寫都在同一個資料庫伺服器中,是不能滿足實院需求的。無論是在安全性、高可用性還是高併發等各個方面都是完全不能滿足實際需求的。因此,通過主從複製的方式來同步資料,再通過讀寫分離來提升資料庫的併發負載能力。有點類似於rsync,但是不同的是rsync是對磁碟檔案做備份,而mysql主從複製是對資料庫中的資料、語句做備份。

2)為什麼要讀寫分離

因為資料庫的"寫"(寫10000條資料可能要3分鐘)操作是比較耗時的。
但是資料庫的"讀" (讀10000條資料可能只要5秒鐘)
所以讀寫分離,解決的是,資料庫的寫入,景響了查詢的效率。

3)什麼時候要讀寫分離

資料庫不一定要讀寫分離,如果程式使用資料庫較多時,而更新少,查詢多的情況下會考慮使用。利用資料庫主從同步,再通過讀寫分離可以分擔資料庫壓力,提高效能。

4)讀寫分離的原理

讀寫分離基本的原理是讓主資料庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從資料庫處理SELECT香詢操作。資料庫複製被用來把事務性操作導致的變更同步到叢集中的從資料庫。

5)mysql支援的複製型別

1. STATEMENT∶基於語句的複製。在伺服器上執行sgl語句,在從伺服器上執行同樣的語句,mysgl預設採用基於語句的複製,執行效率高。
2. ROW∶ 基於行的複製。把改變的內容複製過去, 而不是把命令在從伺服器上執行一遍。


3. MIXED∶混合型別的複製。黑預設採用基於語句的複製,一旦發現基於語句無法精確複製時,就會採用基於行的複製。

6)主從複製的工作過程(主寫從複製)

1. 在每個事務更新資料完成之前,Master在二進位制日誌(Binary log)記錄這些改變。寫入二進位制日誌完成後,Master通知儲存引擎提交事務。

2. Slave將Master複製到其中繼日誌(Relay log) 。首先slave開始一個工作執行緒(I/O),I/0執行緒在Master上開啟一個普通的連線,然後開始Binlog dump process。Binlogdumpprocess從Master的二進位制日誌中讀取事件,如果已經跟上Master,它會睡眠並等待Master產生新的事件,I/O執行緒將這些事件寫入中繼日誌(快取中)。

3. SQL slave thread (SQL從執行緒)處理該過程的最後一步,SQL執行緒從中繼日誌讀取事件,並重放其中的事件而更新Slave資料,使其與Master 中的資料一致,只要該執行緒與I/O 執行緒保持一致,中繼日誌通常會位於OS(系統)快取中,所以中繼日誌的開銷很小。複製過程有一個很重要的限制,即複製在 Slave 上 是序列化的,也就是說Master 上的並行更新操作不能在Slave上並行操作。

7)MySOL主從複製延遲

1. master伺服器高併發,形成大量事務
2. 網路延遲
3. 主從硬體裝置導致 cpu主頻、記憶體io、硬碟io
4. 本來就不是同步複製、而是非同步複製
5. 從庫優化Mysql引數。比如增大innodb_buffer_pool_size,讓更多操作在Mysgl記憶體中完成,減少磁碟操作。從庫使用高效能主機。包 括cpu強悍、記憶體加大。避免使用虛擬雲主機,使用物理主機,這樣提升了i/o方面性。從庫使用SSD磁碟
網路優化,避免跨機房實現同步

8)MySQL 讀寫分離原理

讀寫分離就是隻在主伺服器上寫,只在從伺服器上讀。基本的原理是讓主資料庫處理事務性查詢,而從資料庫處理select查詢。資料庫複製被用來把主資料庫上事務性查詢導致的變更同步到叢集中的從資料庫。

9)目前較為常見的 MySQL

讀寫分離分為以下兩種∶
(1)基於程式程式碼內部實現
在程式碼中根據 select、insert,進行路由分類,這類方法也是目前生產環境應用最廣泛的。
優點是效能較好,因為在程式程式碼中實現,不需要增加額外的裝置為硬體開支;
缺點是需要開發人員來實現,運維人員無從下手。
但是並不是所有的應用都適合在程式程式碼中實現讀寫分離,像一些大型複雜的Java應用,如果在程式程式碼中實現讀寫分離對程式碼改動就較大。

(2)基於中間代理層實現
代理一般位於客戶端和伺服器之間, 代理伺服器接到客戶端請求後通過判斷後轉發到後端資料庫, 有以下代表性程式。

①MySQL-Proxy。 MySQL-Proxy 為 MySOL開源專案, 通過其自帶的 lua 指令碼進行SOL 判斷。
②Atlas。是由奇虎360的Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的資料中間層專案。它是在mysql-proxy0.8.2版本的基礎上,對其進行了優化, 增加了一些新的功能特性。360內部使用Atlas執行的mysql業務,每天承載的讀寫請求數達幾十億條。支援事物以 及儲存過程。
③Amoeba。 由陳思儒開發,作者曾就職於阿里巴巴。該程式由Jaya語言進行開發,阿里巴巴將其用於生產環境。但是它不支援事務和儲存過程。

二、MySQL主從複製與讀寫分離

2.1 主從複製的步驟(理論)

-----主伺服器設定--------

systemctl stop firewalld
systemctl disable firewalld
setenforce 0

##主從伺服器時間同步設定##
vim /etc/ntp.conf

##末行新增
server 127.127.80.0 #設定本地是時鐘源,注意修改網段
fudge 127.127.80.0 stratum 8 #設定時間層級為8(限制在15內)

-----從伺服器設定--------

systemctl stop firewalld
systemctl disable firewalld
setenforce 0

##從伺服器設定時間同步
yum install -y ntp ntpdate

service ntpd start

crontab -e #建立定時任務如下
*/30 * * * * /usr/sbin/ntpdate 192.168.80.10

-----主伺服器MySQL設定--------

vim /etc/my.cnf
##新增以下配置
server-id = 11 #修改伺服器id為11
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.80.%' IDENTIFIED BY '123456'; #新增授權
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 列顯示偏移量

-----從伺服器MySQL設定--------

vim /etc/my.cnf
server-id = 22 #修改,注意id與Master的不同,兩個Slave的id也要不同
relay-log=relay-log-bin #新增,開啟中繼日誌,從主伺服器上同步日誌檔案記錄到本地
relay-log-index=slave-relay-bin.index #新增,定義中繼日誌檔案的位置和名稱

##配置同步,注意master_log_file和master_log_pos的值要與Master查詢的一致
change master to master_host='192.168.80.10' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;

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的可能性:
1、網路不通
2、my. cnf配置有問題
3、密碼、file檔名、pos偏移量不對
4、防火牆沒有關閉

2.3 讀寫分離的步驟(理論)

#實驗環境
Master CentOS7 192.168.80.10
Amoeba CentOS7 192.168.80.20
Slave1 CentOS7 192.168.80.30
Slave2 CentOS7 192.168.80.40
客戶端 CentOS7 192.168.80.50

-----Amoeba伺服器設定--------

cd /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/local/jdk1.6

vim /etc/profile
## 末行新增下列配置
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
java -version
顯示:java version "1.6.0_14" 代表成功

## 安裝 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 說明安裝成功

---- 配置 Amoeba讀寫分離,兩個 Slave 讀負載均衡----

## 在Master、Slave1、Slave2 的mysql上開放許可權給 Amoeba 訪問
mysql -uroot -pabc123
grant all on *.* to test@'192.168.80.%' identified by '123456';

---- amoeba伺服器配置amoeba服務 -----
cd /usr/local/amoeba/conf/

cp amoeba.xml amoeba.xml.bak #備份配置檔案
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>


cp dbServers.xml dbServers.xml.bak

vim dbServers.xml #修改資料庫配置檔案
## 23行註釋掉 ##
<!-- mysql schema
<property name="schema">test</property>
-->
## 26行修改 ##
<!-- mysql user -->
<property name="user">test</property>
## 28 - 30 行取消註釋 ##
<property name="password">123456</property>
## 45行修改 ##
<dbServer name="master" parent="abstractServer">
## 48行修改主伺服器id ##
<property name="ipAddress">192.168.80.10</property>
## 52行修改從伺服器名slave1 ##
<dbServer name="slave1" parent="abstractServer">
## 55行修改為從伺服器slave1的ip ##
<property name="ipAddress">192.168.80.20</property>
## 複製58行上面6行貼上,設定從伺服器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.80.30</property>
## 65行修改 ##
<dbServer name="slaves" virtual="true">
## 71行修改 ##
<property name="poolNames">slave1,slave2</property>

/usr/local/amoeba/bin/amoeba start& #執行此程式,按Ctrl + c 返回
netstat -anpt | grep java #檢視是否開啟了8066埠

---- 測試階段 -----

systemctl stop firewalld
systemctl disable firewalld
setenforce 0

yum install -y mariadb-server mariadb
mysql -u amoeba -p123123 -h 192.168.80.40 -P8066 #通過amoeba伺服器代理訪問mysql ,在通過客戶端連線mysql後寫入的資料只有主服務會記錄,然後同步給從伺服器

## 主伺服器 ##
use TEST;
create table test(id int(10),name varchar(10),address varchar(20));

## 兩臺從伺服器 ##
stop slave; #關閉同步
USE TEST;

## slave1 上
insert into test values('1','zhangsan','this_is_slave1');

## slave2 上
insert into test values('2','lisi','this_is_slave2');

## 主伺服器 上
insert into test values('3','wanger','this_is_master');

## 客戶端 上
use TEST;
select * from test; #客戶端會分別向slave1和slave2讀取資料,顯示的只有在兩個從伺服器上新增的資料,沒有在主伺服器上新增的資料
insert into test values('4','趙六','this_is_client'); ##只有主伺服器上有此資料