防偽碼:曾總想穿過那段最無暇的時光,去實現(xiàn)所有繽紛的夢想。
第八章 MYSQL主從復(fù)制與讀寫分離
前言:又快到雙十一網(wǎng)購狂歡節(jié)了,試想,當(dāng)天那么多的朋友上網(wǎng)購物,單單一臺或幾臺數(shù)據(jù)庫服務(wù)器肯定是不夠的。恰好今天使用的軟件amoeba也是阿里巴巴自己員工開發(fā)出來的,經(jīng)過淘寶這么多用戶的驗證,效果不用懷疑。在實際的生產(chǎn)環(huán)境中,對數(shù)據(jù)庫的讀和寫都在同一個數(shù)據(jù)庫服務(wù)器中,是不能滿足實際需求的。無論是在安全性、高可用性還是高并發(fā)等各個方面都是完全不能滿足實際需求的。因此,通過主從復(fù)制的方式來同步數(shù)據(jù),再通過讀寫分離來提升數(shù)據(jù)庫的并發(fā)負(fù)載能力。有點類似于前面我們學(xué)習(xí)過的rsync,但是不同的是rsync是對磁盤文件做備份,而mysql主從復(fù)制是對數(shù)據(jù)庫中的數(shù)據(jù)、語句做備份。
如圖所示:
一、 案例前置知識點
1、 mysq支持的復(fù)制類型
1) 基于語句的復(fù)制。在服務(wù)器上執(zhí)行sql語句,在從服務(wù)器上執(zhí)行同樣的語句,mysql默認(rèn)采用基于語句的復(fù)制,執(zhí)行效率高。
2) 基于行的復(fù)制。把改變的內(nèi)容復(fù)制過去,而不是把命令在從服務(wù)器上執(zhí)行一遍。
3) 混合類型的復(fù)制。默認(rèn)采用基于語句的復(fù)制,一旦發(fā)現(xiàn)基于語句無法精確復(fù)制時,就會采用基于行的復(fù)制。
2、 復(fù)制的工作過程
1) 在每個事務(wù)更新數(shù)據(jù)完成之前,master在二進(jìn)制日志記錄這些改變。寫入二進(jìn)制日志完成后,master通知存儲引擎提交事務(wù)。
2) Slave將master的binary log復(fù)制到其中繼日志。首先slave開始一個工作線程(I/O),I/O線程在master上打開一個普通的連接,然后開始binlog dump process。binlog dump process從master的二進(jìn)制日志中讀取事件,如果已經(jīng)跟上master,它會睡眠并等待master產(chǎn)生新的事件,I/O線程將這些事件寫入中繼日志。
3) Sql slave thread(sql從線程)處理該過程的最后一步,sql線程從中繼日志讀取事件,并重放其中的事件而更新slave數(shù)據(jù),使其與master中的數(shù)據(jù)一致,只要該線程與I/O線程保持一致,中繼日志通常會位于os緩存中,所以中繼日志的開銷很小。
如圖所示:
3、 mysql讀寫分離原理
讀寫分離就是在主服務(wù)器上修改,數(shù)據(jù)會同步到從服務(wù)器,從服務(wù)器只能提供讀取數(shù)據(jù),不能寫入,實現(xiàn)備份的同時也實現(xiàn)了數(shù)據(jù)庫性能的優(yōu)化,以及提升了服務(wù)器安全。
前較為常見的Mysql讀寫分離分為以下兩種:
1)基于程序代碼內(nèi)部實現(xiàn)
在代碼中根據(jù)select 、insert進(jìn)行路由分類,這類方法也是目前生產(chǎn)環(huán)境下應(yīng)用最廣泛的。優(yōu)點是性能較好,因為程序在代碼中實現(xiàn),不需要增加額外的硬件開支,缺點是需要開發(fā)人員來實現(xiàn),運(yùn)維人員無從下手。
2) 基于中間代理層實現(xiàn)
代理一般介于應(yīng)用服務(wù)器和數(shù)據(jù)庫服務(wù)器之間,代理數(shù)據(jù)庫服務(wù)器接收到應(yīng)用服務(wù)器的請求后根據(jù)判斷后轉(zhuǎn)發(fā)到,后端數(shù)據(jù)庫,有以下代表性的程序。
(1)mysql_proxy。mysql_proxy是Mysql的一個開源項目,通過其自帶的lua腳本進(jìn)行sql判斷。
(2)Atlas。是由 Qihoo 360, Web平臺部基礎(chǔ)架構(gòu)團(tuán)隊開發(fā)維護(hù)的一個基于MySQL協(xié)議的數(shù)據(jù)中間層項目。它是在mysql-proxy 0.8.2版本的基礎(chǔ)上,對其進(jìn)行了優(yōu)化,增加了一些新的功能特性。360內(nèi)部使用Atlas運(yùn)行的mysql業(yè)務(wù),每天承載的讀寫請求數(shù)達(dá)幾十億條。支持事物以及存儲過程。
(3)Amoeba。由阿里巴巴集團(tuán)在職員工陳思儒使用序java語言進(jìn)行開發(fā),阿里巴巴集團(tuán)將其用戶生產(chǎn)環(huán)境下,但是他并不支持事物以及存數(shù)過程。
經(jīng)過上述簡單的比較,不是所有的應(yīng)用都能夠在基于程序代碼中實現(xiàn)讀寫分離,像一些大型的java應(yīng)用,如果在程序代碼中實現(xiàn)讀寫分離對代碼的改動就較大,所以,像這種應(yīng)用一般會考慮使用代理層來實現(xiàn),那么今天就使用Amoeba為例,完成主從復(fù)制和讀寫分離。
二、 實驗案例:mysql主從復(fù)制和讀寫分離
1、 實驗拓?fù)?/span>
2、 實驗環(huán)境
在amoeba上安裝amoeba和jdk,在其它的機(jī)器上安裝mysql,ip地址如上圖所示
三、 主從復(fù)制的實驗步驟
1、搭建時間NTP服務(wù)器,同步時間
1) 建立時間同步環(huán)境,在主節(jié)點上搭建時間同步服務(wù)器
2) 配置NTP時間服務(wù)器
Vim /etc/ntp.conf
3) 重啟ntpd服務(wù)
4) 在防火墻上開啟指定端口
5) 在從節(jié)點上進(jìn)行時間同步
在另一臺從服務(wù)器上執(zhí)行相同操作
2、 在mysql主和兩臺從服務(wù)器上安裝mysql,我以其中一臺為例。
(1) 安裝mysql并創(chuàng)建程序用戶
[root@centos4 ~]# tar zxf cmake-2.8.6.tar.gz
[root@centos4 ~]# cd cmake-2.8.6
[root@centos4 cmake-2.8.12]# ./configure && gmake && gmake install
[root@centos4 ~]# tar zxf mysql-5.5.38.tar.gz
[root@centos4 ~]# cd mysql-5.5.38
[root@centos4 mysql-5.5.38]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DSYSCONFDIR=/etc/ -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all && make && make install
[root@centos4 mysql-5.5.38]# useradd -M -s /sbin/nologin mysql -g mysql
(2)優(yōu)化程序執(zhí)行路徑
[root@centos4 mysql-5.5.38]# echo "PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
(3)創(chuàng)建主配置文件
[root@centos4 mysql-5.5.38]# cp support-files/my-medium.cnf.sh /etc/my.cnf
cp:是否覆蓋"/etc/my.cnf"? y
[root@centos4 mysql-5.5.38]#
(4)創(chuàng)建服務(wù)腳本并添加為系統(tǒng)服務(wù)
[root@centos4 mysql-5.5.38]# cp support-files/mysql.server /etc/init.d/mysqld
[root@centos4 mysql-5.5.38]# chkconfig --add mysqld
[root@centos4 mysql-5.5.38]# chkconfig mysqld on
[root@centos4 mysql-5.5.38]# chmod +x /etc/init.d/mysqld
(5)初始化數(shù)據(jù)庫
[root@centos4 mysql-5.5.38]# /usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data
[root@centos4 mysql-5.5.38]#
(6)修改安裝目錄權(quán)限
[root@centos4 mysql-5.5.38]# chown -R mysql:mysql /usr/local/mysql/
(7)啟動服務(wù)
[root@centos4 mysql-5.5.38]# service mysqld start
(8)為用戶root設(shè)置密碼
[root@centos4 mysql-5.5.38]# mysqladmin -u root -p password '123-abc’
默認(rèn)沒有密碼,直接在確認(rèn)舊密碼處回車即可。
(9)登錄mysql數(shù)據(jù)庫
[root@centos4 mysql-5.5.38]# mysql -u root -p
3、 配置mysql主服務(wù)器(MASTER)
1)修改/etc/my.cnf配置文件
server-id = 11 //mysql數(shù)據(jù)的唯一標(biāo)示(不能重復(fù))
log-slave-updates=true //允許連級復(fù)制 (增加)
log-bin=master-bin //二進(jìn)制文件名(修改)
2) 重啟MySQL服務(wù)
3) 登錄mysql程序,給從服務(wù)器授權(quán)
mysql -u root -p
注:上圖中File列顯示日志名,Position列顯示偏移量,這兩個值在后面配置從服務(wù)器
的時候需要。
4、 配置從服務(wù)器
1) 在/etc/my.cnf中修改以下內(nèi)容
[root@centos3 ~]# vim /etc/my.cnf
server-id = 22 //不能與其他實例重復(fù)
log-bin=mysql-bin //二進(jìn)制日志文件名 修改
relay-log=relay-log-bin //復(fù)制過來的二進(jìn)制文件名,增加
relay-log-index=slave-relay-bin.index //中繼日志存放的文件名稱,增加
注意server-id不能與主服務(wù)器相同,但是從服務(wù)器要相同。
2) 重啟mysql服務(wù)
3) 登錄mysql,配置同步(按照主服務(wù)器結(jié)果更改下面命令中
master_file和master_log_pos參數(shù))
4)啟動同步
5) 查看slave狀態(tài),確保以下兩個值為YES
5、 驗證主從復(fù)制效果
1) 在主服務(wù)器上新建數(shù)據(jù)庫“IT”
2) 在從服務(wù)器上查看數(shù)據(jù)庫,如果和主服務(wù)器相同,說明主從復(fù)制成功。
四、 搭建MySQL讀寫分離
1、 安裝java環(huán)境(amoeba軟件基于java平臺運(yùn)行)
1)運(yùn)行jdk
安裝過程中提示(yes/no),我們要選擇yes安裝
2) 修改/etc/profile配置文件,增加以下配置
export JAVA_HOME=/usr/local/jdk1.6 //設(shè)置jdk的根目錄
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jir
e/lib //將jdk的程序文件賦予CLASSPATH變量
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin:$PATH:$HOME
/bin //將jdk的程序文件賦予PATH變量
export AMOEBA_HOME=/usr/local/amoeba //定義AMOEBA的根目錄
export PATH=$PATH:$AMOEBA_HOME/bin 將amoeba的程序文件復(fù)制給PATH變量
3) 執(zhí)行腳本
2、 安裝并配置Amoeba軟件
官方解釋:Amoeba(變形蟲),這個軟件致力于MySQL的分布式數(shù)據(jù)庫前端代理層,主要為應(yīng)用層訪問MySQL的時候
充當(dāng)SQL路由功能,并具有負(fù)載均衡、高可用性、SQL過濾、讀寫分離、可路由相關(guān)的到目的數(shù)據(jù)庫,可并發(fā)
請求多臺數(shù)據(jù)庫。
3、 配置amoeba讀寫分離,兩個slave讀負(fù)載均衡
1) 在主從服務(wù)器上開放權(quán)限給amoeba訪問(三臺服務(wù)器上都做相同設(shè)置,這里我就以其中一臺為例)
2) 修改amoeba.xml文件
注意:所有配置文件注釋都是以 <!-- 內(nèi)容 -->,再刪除注釋時請將內(nèi)容也一并刪除,最好是刪除正行,
但是有些時候只需要刪除頭和尾即可,里面的配置項是可以直接使用的。這個配置文件需要定義兩
個配置,第一是應(yīng)用程序使用什么用戶連接amoeba訪問到后端的mysql數(shù)據(jù)庫,第二個是定義默認(rèn)寫池以及讀池。
vi /usr/local/amoeba/conf/amoeba/amoaba.xml
接下來修改
3) 編輯dbServers.xml文件
vi /usr/local/amoeba/conf/dbServers.xml
接下圖
4) 啟動amoeba軟件(默認(rèn)端口為tcp 8066)
4、 測試讀寫分離
1) 打開一臺客戶端192.168.1.10,也需要安裝mysql,作為測試機(jī),可以使用yum -y install mysql安裝。
2)建立防火墻規(guī)則
[root@centos1 ~]# iptables -I INPUT -p tcp --dport 8066 -j ACCEPT
master、slave1、slave2都需要開放3306端口入站
[root@centos2 ~]# iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
[root@centos2 ~]# service iptables save
另外兩臺從服務(wù)器也是一樣的配置,或者直接將iptables stop掉
3)在客戶端登錄
4) 在主服務(wù)器master上創(chuàng)建一個數(shù)據(jù)庫YZZG(一盞燭光,嘿嘿),同步到各從服務(wù)器上,然后關(guān)掉從服務(wù)器的slave功能,再插入數(shù)據(jù)。
5) 查看在從服務(wù)器已經(jīng)同步
6) 然后在主服務(wù)器上寫入數(shù)據(jù)
7) 從服務(wù)器上也同步了表
8)在兩臺從服務(wù)器上執(zhí)行stop slave, 分別在從服務(wù)器上寫入不同的數(shù)據(jù)
9) 在客戶端上查詢
10) 在客戶機(jī)上寫入一條語句
11) 在客戶端上查不到剛寫入的數(shù)據(jù),最終只有在master主服務(wù)器上才能看到,因為寫操作只有master有,另外兩臺負(fù)責(zé)讀取數(shù)據(jù)。
總結(jié):到此為止主從復(fù)制和讀寫分離都已完成,寫操作都在主服務(wù)器上,實現(xiàn)數(shù)據(jù)的統(tǒng)一更新,從服務(wù)器只負(fù)責(zé)讀取,負(fù)載均衡分擔(dān)了數(shù)據(jù)庫壓力。其實在我們生活中有很多主從復(fù)制的應(yīng)用,例如有很多連鎖超市,總部負(fù)責(zé)產(chǎn)品的名稱和價格等信息的錄入,而所有的超市都會同步更新,做到了統(tǒng)一價格。而像淘寶的服務(wù)器,主要是為了分擔(dān)負(fù)載,提升查詢的性能,最后補(bǔ)充一句,Mysql主從復(fù)制與我們以前學(xué)習(xí)的sqlserver復(fù)制是一樣的作用。
謝謝觀看,真心的希望能幫到您。
本文出自 “一盞燭光” 博客,謝絕轉(zhuǎn)載!
更多建議: