目錄
前言
一、主從復制原理
1.1 MySQL的復制類型
1.2?mysql主從復制的工作原理
1.3 MySQL主從復制延遲
1.4?MySQL四種同步方式
1.5 MySQL支持的復制類型
二、 MySQL應用場景
三、主從復制實驗
3.1?MySQL主從服務器時間同步
3.1.1 安裝ntp、修改配置文件
3.1.2 兩臺SLAVE服務器配置
3.2 配置主從同步
3.2.1 master服務器修改配置文件
?3.2.2?從服務器配置
3.3 測試數(shù)據(jù)同步
四、MySQL 讀寫分離
4.1 MySQL讀寫分離原理
4.2?讀寫分離存在意義
4.3 常見的兩種 MySQL 讀寫分離分
4.3.1 基于程序代碼內部實現(xiàn)
4.3.2 基于中間代理層實現(xiàn)?
4.3.3?Amoeba
4.4 MySQL讀寫分離原理
五、MySQL四種同步方式
5.1 異步復制(Async Replication)
5.2 同步復制(Sync Replication)
5.3 半同步復制(Semi-Sync Replication)
5.4 增強半同步復制(lossless Semi-Sync Replication、無損復制)
六、搭建 MySQL 讀寫分離??
6.1??Amoeba服務器配置
6.2?配置 Amoeba讀寫分離,兩個 Slave 讀負載均衡
?6.3 回到amoeba服務器配置amoeba服務
6.4 修改數(shù)據(jù)庫配置文件?
6.5?測試讀寫分離?
前言
在企業(yè)應用中,成熟的業(yè)務通常數(shù)據(jù)量都比較大 單臺MySQL在安全性、 高可用性和高并發(fā)方面都無法滿足實際的需求 配置多臺主從數(shù)據(jù)庫服務器以實現(xiàn)讀寫分離
一、主從復制原理
1.1 MySQL的復制類型
- ?基于SQL語句的復制(STATEMENT默認)
- ?基于行的復制(ROW)
- ?混合類型的復制(MIXED)
1.2?mysql主從復制的工作原理
【兩個日志,三個線程】
兩個日志:Binary log:二進制日志;relay log:中繼日志
三個線程:從服務器的I/O線程、SQL線程、主服務器的dump線程
Binary log:二進制日志;relay log:中繼日志
主服務器會把數(shù)據(jù)寫進二進制文件里面---》
然后從服務器的i/o線程向dump發(fā)出同步請求,dump把數(shù)據(jù)發(fā)送給i/o線程,然后i/o寫入到本地的中繼日志---》
然后通過mysql從服務器的sql線程來讀取中繼日志,實現(xiàn)`重放`的功能,同步到自己的數(shù)據(jù)庫中
最終實現(xiàn)mysql主從復制同步
- 主服務器 master 記錄數(shù)據(jù)庫通過 dump 線程將操作記錄到 Binary log。
- 從服務器開啟 I/O 線程向主服務器發(fā)送同步日志請求。
- 主服務器把二進制日志內容發(fā)送給從服務器。
- 從服務器將二進制日志記錄的操作同步到relay log (中繼日志) (存在從服務器的緩存中)。
- 從服務器中的sql線程將relay log日志記錄的操作在從服務器執(zhí)行后寫入從服務器數(shù)據(jù)庫。
- 首先client端(tomcat)將數(shù)據(jù)寫入到master節(jié)點的數(shù)據(jù)庫中,master節(jié)點會通知存儲引擎提交事務,同時會將數(shù)據(jù)以(基于行、基于sql、基于混合)的方式保存在二進制日志中
- SLAVE節(jié)點會開啟I/O線程,用于監(jiān)聽master的二進制日志的更新,一旦發(fā)生更新內容,則向master的dump線程發(fā)出同步請求
- master的dump線程在接收到SLAVE的I/O請求后,會讀取二進制文件中更新的數(shù)據(jù),并發(fā)送給SLAVE的I/O線程
- SLAVE的I/O線程接收到數(shù)據(jù)后,會保存在SLAVE節(jié)點的中繼日志中
- 同時,SLAVE節(jié)點中的SQL線程,會讀取中繼日志中的數(shù)據(jù),更新在本地的mysql數(shù)據(jù)庫中
- 最終,完成slave——>復制master數(shù)據(jù),達到主從同步的效果?
1.3 MySQL主從復制延遲
- master服務器高并發(fā),形成大量事務
- 網(wǎng)絡延遲
- 主從硬件設備導致 cpu主頻、內存io、硬盤io
- 本來就不是同步復制、而是異步復制 從庫優(yōu)化Mysql參數(shù)。比如增大innodb_buffer_pool_size,讓更多操作在Mysql內存中完成,減少磁盤操作。
- 從庫使用高性能主機。包括cpu強悍、內存加大。避免使用虛擬云主機,使用物理主機,這樣提升了i/o方面性。 從庫使用SSD磁盤 網(wǎng)絡優(yōu)化,避免跨機房實現(xiàn)同步
問題解決方法
- 半同步復制- 解決數(shù)據(jù)丟失的問題
- 并行復制---解決從庫復制延遲的問題
1.4?MySQL四種同步方式
異步復制(asynchronous)
- 搭建簡單,使用非常廣泛,從mysql誕生之初,就產(chǎn)生了這種架構,性能非常好,可為非常成熟。但是這種架構數(shù)據(jù)是異步的,所以有丟書數(shù)據(jù)庫的風險。
主服務器不需要等待從服務器是否把二進制文件拷入到中繼日志中,就開始讀取新的請求了。
同步復制(sync replication)
- 同步復制提供了最佳安全性,保證數(shù)據(jù)安全,不丟數(shù)據(jù),損失性能
主服務器需要等待從服務器把二進制文件拷入到中繼日志中,并且還要從庫中執(zhí)行完成,主服務器才能開始讀取新的請求了。
半同步復制(Semi synchronous)
- 性能、功能都介于異步和全同步之間。從mysql5.5開始誕生,目的是為了折中上述兩種架構性能已優(yōu)缺點。
主服務器需要等待從服務器是否把二進制文件拷入到中繼日志中,不管你是否在從庫中執(zhí)行完成,就開始讀取新的請求了。
增強版的半同步復制(lossless replication)
數(shù)據(jù)零丟失,無損復制,性能好,mysql5.7誕生
1.5 MySQL支持的復制類型
- STATEMENT:基于語句的復制在服務器上執(zhí)行sql語句,在從服務器上執(zhí)行同樣的語句,mysql默認采用基于語句的復制。
- ROW:基于行的復制,把改變的內容復制過去,而不是把命令在從服務器上執(zhí)行一遍。
- MIXED:混合類型的復制,默認采用基于語句的復制,一旦發(fā)現(xiàn)基于語句無法精確復制時,就會采用基于行復制。
二、 MySQL應用場景
- mysql 數(shù)據(jù)庫 主要的性能是讀和寫,一般場景來說讀請求更多。
- 根據(jù)主從復制可以演變成讀寫分離,因為讀寫分離基于主從復制,使用讀寫分離從而解決高并發(fā)的問題。
mysql架構演變的方向:
- 單臺mysql有單點故障 集群---》
- 主從復制
- 主從復制渡河寫的壓力不均衡
- 讀寫分離
- 讀寫分離的基礎是主從復制
- mysql的高可用架構MHA(master HA高可用) MGR MMM
三、主從復制實驗
主機 | 操作系統(tǒng) | IP地址 | 所需工具/軟件/安裝包 |
Master | CentOS7 | 192.168.19.3 | ntp 、 mysql-boost-5.7.20.tar.gz |
Slave1 | CentOS7 | 192.168.19.6 | ntp 、ntpdate 、mysql-boost-5.7.20.tar.gz |
Slave2 | CentOS7 | 192.168.19.7 | ntp 、ntpdate 、 mysql-boost-5.7.20.tar.gz |
Amoeba | CentOS7 | 192.168.19.4 | jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz |
客戶端 | CentOS7 | 192.168.19.5 |
3.1?MySQL主從服務器時間同步
3.1.1 安裝ntp、修改配置文件
yum -y install ntp
vim /etc/ntp.conf
末尾添加
server 127.127.19.0 #設置本地是時鐘源,注意修改網(wǎng)段
fudge 127.127.19.0 stratum 10 #設置時間層級為10(限制在15內)
?
3.1.2 兩臺SLAVE服務器配置
yum install ntp ntpdate -y
ntpdate 192.168.19.3
crontable -e
*/10 * * * * /usr/sbin/ntpdate 192.168.19.3
兩臺從服務器配置相同
?
?文章來源地址http://www.zghlxwxcb.cn/news/detail-603362.html
3.2 配置主從同步
3.2.1 master服務器修改配置文件
vim /etc/my.cnf
#在mysqld模塊下修改一下內容
#開啟二進制日志文件(之后生成的日志名為master-bin)
log_bin=master-bin
#開啟從服務器日志同步
log_slave-updates=true
#主服務器id為1(不可重復)
server_id = 1
--------》wq
重啟服務
?
配置規(guī)則
mysql -uroot -p
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.19.%' IDENTIFIED BY '123456';
刷新權限表
flush privileges;
查看master數(shù)據(jù)庫狀態(tài)
show master status;
?文章來源:http://www.zghlxwxcb.cn/news/detail-603362.html
3.2.2?從服務器配置
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 #選配項
#當 slave 從庫宕機后,假如 relay-log 損壞了,導致一部分中繼日志沒有處理,則自動放棄所有未執(zhí)行的 relay-log,并且重新從 master 上獲取日志,這樣就保證了relay-log 的完整性。默認情況下該功能是關閉的,將 relay_log_recovery 的值設置為 1 時, 可在 slave 從庫上開啟該功能,建議開啟。
systemctl restart mysqld
mysql -u root -p
change master to master_host='192.168.19.3' , master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=1311;
#配置同步,注意 master_log_file 和 master_log_pos 的值要與Master查詢的一致,這里的是例子,每個人的都不一樣
start slave; #啟動同步,如有報錯執(zhí)行 reset slave;
show slave status\G #查看 Slave 狀態(tài)
//確保 IO 和 SQL 線程都是 Yes,代表同步正常。
Slave_IO_Running: Yes #負責與主機的io通信
Slave_SQL_Running: Yes #負責自己的slave mysql進程
?
?
3.3 測試數(shù)據(jù)同步
在主服務器上創(chuàng)建一個數(shù)據(jù)庫
在兩臺從服務器上直接查看數(shù)據(jù)庫列表
?
?
四、MySQL 讀寫分離
4.1 MySQL讀寫分離原理
- 讀寫分離基本的原理是讓主數(shù)據(jù)庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從數(shù)據(jù)庫處理SELECT查詢操作。數(shù)據(jù)庫復制被用來把事務性操作導致的變更同步到集群中的從數(shù)據(jù)庫。
4.2?讀寫分離存在意義
- 因為數(shù)據(jù)庫的“寫”(寫10000條數(shù)據(jù)可能要3分鐘)操作是比較耗時的。
- 但是數(shù)據(jù)庫的“讀”(讀10000條數(shù)據(jù)可能只要5秒鐘)。
- 所以讀寫分離,解決的是,數(shù)據(jù)庫的寫入,影響了查詢的效率
4.3 常見的兩種 MySQL 讀寫分離分
4.3.1 基于程序代碼內部實現(xiàn)
- 在代碼中根據(jù) select、insert 進行路由分類,這類方法也是目前生產(chǎn)環(huán)境應用最廣泛的。
- 優(yōu)點是性能較好,因為在程序代碼中實現(xiàn),不需要增加額外的設備為硬件開支;缺點是需要開發(fā)人員來實現(xiàn),運維人員無從下手。
- 但是并不是所有的應用都適合在程序代碼中實現(xiàn)讀寫分離,像一些大型復雜的Java應用,如果在程序代碼中實現(xiàn)讀寫分離對代碼改動就較大。
4.3.2 基于中間代理層實現(xiàn)?
- 代理一般位于客戶端和服務器之間,代理服務器接到客戶端請求后通過判斷后轉發(fā)到后端數(shù)據(jù)庫,有以下代表性程序:
- MySQL-Proxy。MySQL-Proxy 為 MySQL 開源項目,通過其自帶的 lua 腳本進行SQL 判斷。
- Atlas。是由奇虎360的Web平臺部基礎架構團隊開發(fā)維護的一個基于MySQL協(xié)議的數(shù)據(jù)中間層項目。它是在mysql-proxy 0.8.2版本的基礎上,對其進行了優(yōu)化,增加了一些新的功能特性。360內部使用Atlas運行的mysql業(yè)務,每天承載的讀寫請求數(shù)達幾十億條。支持事物以及存儲過程。
4.3.3?Amoeba
- 讀取請求發(fā)送給從服務器是,采用輪詢調度算法
- amoeba使用的java語言編寫,配置文件為xml
- amoeba主要負責對外的一個代理IP
- 訪問這個IP時,發(fā)送的請求為“寫”請求,則會轉給主服務器
- 當發(fā)送的請求為讀時,會通過調度轉發(fā)給從服務器,使用輪詢算法,輪流分配給兩臺從服務器
- amoeba可以視為調度器,如果主服務器掛掉(單點故障),則會有MHA解決這個問題
- 由于使用MySQL Proxy需要寫大量的Lua腳本,這些Lua腳本不是現(xiàn)成的,而需要自己編寫,這對于并不熟悉MySQL Proxy內置變量和MySQL Protocol的人來說是非常困難的。Amoeba是一個非常容易使用,可移植性非常強的軟件,因此它在生產(chǎn)環(huán)境中被廣泛用于數(shù)據(jù)庫的代理層。
4.4 MySQL讀寫分離原理
- 讀寫分離就是只在主服務器上寫,只在從服務器上讀。
- 基本的原理是讓主數(shù)據(jù)庫處理事務性查詢,而從數(shù)據(jù)庫處理 select 查詢。
- 數(shù)據(jù)庫復制被用來把主數(shù)據(jù)庫上事務性查詢導致的變更同步到集群中的從數(shù)據(jù)庫。
- 數(shù)據(jù)庫不一定要讀寫分離,如果程序使用數(shù)據(jù)庫較多時,而更新少,查詢(select)多的情況下會考慮使用。利用數(shù)據(jù)庫主從同步,再通過讀寫分離可以分擔數(shù)據(jù)庫壓力,提高性能。
五、MySQL四種同步方式
5.1 異步復制(Async Replication)
- 默認同步方式是異步復制。主庫將更新寫入Binlog日志文件后,不需要等待數(shù)據(jù)更新是否已經(jīng)復制到從庫中,就可以繼續(xù)處理更多的請求。Master將事件寫入binlog,但并不知道Slave是否或何時已經(jīng)接收且已處理。在異步復制的機制的情況下,如果Master宕機,事務在Master上已提交,但很可能這些事務沒有傳到任何的Slave上。假設有Master->Salve故障轉移的機制,此時Slave也可能會丟失事務。MySQL復制默認是異步復制,異步復制提供了最佳性能。
5.2 同步復制(Sync Replication)
- 主庫將更新寫入Binlog日志文件后,需要等待數(shù)據(jù)更新已經(jīng)復制到從庫中,并且已經(jīng)在從庫執(zhí)行成功,然后才能返回繼續(xù)處理其它的請求。同步復制提供了最佳安全性,保證數(shù)據(jù)安全,數(shù)據(jù)不會丟失,但對性能有一定的影響。
5.3 半同步復制(Semi-Sync Replication)
- 主庫提交更新寫入二進制日志文件后,等待數(shù)據(jù)更新寫入了從服務器中繼日志中,然后才能再繼續(xù)處理其它請求。該功能確保至少有1個從庫接收完主庫傳遞過來的binlog內容已經(jīng)寫入到自己的relay log里面了,才會通知主庫上面的等待線程,該操作完畢。
- 半同步復制,是最佳安全性與最佳性能之間的一個折中。
- MySQL 5.5版本之后引入了半同步復制功能,主從服務器必須安裝半同步復制插件,才能開啟該復制功能。如果等待超時,超過rpl_semi_sync_master_timeout參數(shù)設置時間(默認值為10000,表示10秒),則關閉半同步復制,并自動轉換為異步復制模式。當master dump線程發(fā)送完一個事務的所有事件之后,如果在rpl_semi_sync_master_timeout內,收到了從庫的響應,則主從又重新恢復為增強半同步復制。
- ACK (Acknowledge character)即是確認字符。
5.4 增強半同步復制(lossless Semi-Sync Replication、無損復制)
- 增強半同步是在MySQL 5.7引入,其實半同步可以看成是一個過渡功能,因為默認的配置就是增強半同步,所以,大家一般說的半同步復制其實就是增強的半同步復制,也就是無損復制。
- 增強半同步和半同步不同的是,等待ACK時間不同
- rpl_semi_sync_master_wait_point = AFTER_SYNC(默認)
- 半同步的問題是因為等待ACK的點是Commit之后,此時Master已經(jīng)完成數(shù)據(jù)變更,用戶已經(jīng)可以看到最新數(shù)據(jù),當Binlog還未同步到Slave時,發(fā)生主從切換,那么此時從庫是沒有這個最新數(shù)據(jù)的,用戶看到的是老數(shù)據(jù)。
- 增強半同步將等待ACK的點放在提交Commit之前,此時數(shù)據(jù)還未被提交,外界看不到數(shù)據(jù)變更,此時如果發(fā)送主從切換,新庫依然還是老數(shù)據(jù),不存在數(shù)據(jù)不一致的問題。
六、搭建 MySQL 讀寫分離??
6.1??Amoeba服務器配置
Amoeba(192.168.19.4)
因為 Amoeba 基于是 jdk1.5 開發(fā)的,所以官方推薦使用 jdk1.5 或 1.6 版本,高版本不建議使用。
將jdk-6u14-linux-x64.bin 和 amoeba-mysql-binary-2.2.0.tar.gz.0 上傳到/opt目錄下。
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
##安裝 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 說明安裝成功
?
???
?
?
?
6.2?配置 Amoeba讀寫分離,兩個 Slave 讀負載均衡
?
?
6.3 回到amoeba服務器配置amoeba服務
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">123456</property>
115修改
<property name="defaultPool">master</property>
117去掉注釋–
<property name="writePool">master</property>
<property name="readPool">slaves</property>
?
?
6.4 修改數(shù)據(jù)庫配置文件?
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml #修改數(shù)據(jù)庫配置文件
23注釋掉
作用:默認進入test庫 以防m(xù)ysql中沒有test庫時,會報錯
<!-- mysql schema
<property name="schema">test</property>
-->
26修改
<!-- mysql user -->
<property name="user">test</property>
28-30去掉注釋
<property name="password">123456</property>
45修改,設置主服務器的名Master
<dbServer name="master" parent="abstractServer">
48修改,設置主服務器的地址
<property name="ipAddress">192.168.223.10</property>
52修改,設置從服務器的名slave1
<dbServer name="slave1" parent="abstractServer">
55修改,設置從服務器1的地址
<property name="ipAddress">192.168.223.9</property>
58復制上面6行粘貼,設置從服務器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.223.11</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
?
?
?
?
?
6.5?測試讀寫分離?
在客戶端服務器上進行測試:
使用yum快速安裝MySQL虛擬客戶端
通過amoeba服務器代理訪問mysql ,在通過客戶端連接mysql后寫入的數(shù)據(jù)只有主服務會記錄,然后同步給從服務器
在主服務器上:
use db_test;
create table test (id int(10),name varchar(10),address varchar(20));
?
在兩臺從服務器上:
stop slave; #關閉同步
use db_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','wangwu','this_is_master');
//在客戶端服務器上:
use db_test;
select * from test; //客戶端會分別向slave1和slave2讀取數(shù)據(jù),顯示的只有在兩個從服務器上添加的數(shù)據(jù),沒有在主服務器上添加的數(shù)據(jù)
insert into test values('4','qianqi','this_is_client'); //只有主服務器上有此數(shù)據(jù)
//在兩個從服務器上執(zhí)行 start slave; 即可實現(xiàn)同步在主服務器上添加的數(shù)據(jù)
start slave;
?
?
?
?
?
?
?
?
到了這里,關于Mysql 主從復制、讀寫分離的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!