一直都想自己動(dòng)手搭建一個(gè)Redis集群和MySQL的主從同步,當(dāng)然不是依靠Docker的一鍵部署(雖然現(xiàn)在企業(yè)開(kāi)發(fā)用的最多的是這種方式),所以本文就算是一個(gè)教程類文章吧,但在動(dòng)手搭建之前,會(huì)先聊聊理論的東西,以便于大家有一個(gè)集群和主從同步的概念。
什么是Redis集群
簡(jiǎn)介
Redis是一個(gè)快速高效的NoSQL型數(shù)據(jù)庫(kù),由于其基于內(nèi)存存儲(chǔ)、單線程、多路IO復(fù)用的特性,其QPS可以達(dá)到驚人的100000+(官方數(shù)據(jù)),但是即使有這么高的速度,在中國(guó)這么大的網(wǎng)民基數(shù)環(huán)境下,也存在著性能瓶頸。
首先拋開(kāi)服務(wù)器故障不談,Redis集群首先可以使Redis性能得到線性提高,這是毋庸置疑的,其次Redis集群除了解決了效率問(wèn)題,還可以解決服務(wù)器宕機(jī)造成的數(shù)據(jù)丟失問(wèn)題,當(dāng)某個(gè)Redis節(jié)點(diǎn)宕機(jī),剩下的節(jié)點(diǎn)會(huì)繼續(xù)工作,并不會(huì)影響整體集群的使用,從而實(shí)現(xiàn)高可用。
Redis單機(jī)模式有什么問(wèn)題
單機(jī)故障
在單機(jī)模式下的Redis,我們的應(yīng)用中所有需要緩存的數(shù)據(jù)都依賴一臺(tái)Redis服務(wù)器,應(yīng)用的流量小可能看不出什么問(wèn)題,但是隨著應(yīng)用越來(lái)越大,流量越來(lái)越大,如果出現(xiàn)服務(wù)器宕機(jī)或者斷電的狀況,那么我們的應(yīng)用整個(gè)一個(gè)緩存層在一段時(shí)間內(nèi)(重啟)都將不復(fù)存在。
先不談基于Redis的分布式Session可能造成的問(wèn)題,如果恰好遇上流量高峰,這些流量直接打在數(shù)據(jù)庫(kù)上,我們知道數(shù)據(jù)庫(kù)的IO效率遠(yuǎn)不及Redis,這將大大提高應(yīng)用負(fù)載,容易出現(xiàn)數(shù)據(jù)庫(kù)服務(wù)器的宕機(jī),從而造成應(yīng)用的宕機(jī)。
由此看來(lái),單機(jī)版Redis如果出現(xiàn)故障,將有可能引起一系列的連鎖反應(yīng),造成不可逆的損失。
容量瓶頸
我們知道Redis是基于內(nèi)存存儲(chǔ)的一個(gè)NoSQL數(shù)據(jù)庫(kù),基于內(nèi)存也是其高速高效的原因之一。雖然容量瓶頸在實(shí)際生產(chǎn)中并不常見(jiàn)(通常有意識(shí)地將搭載Redis的機(jī)器內(nèi)存容量加高),但是不排除在某些極端條件下Redis會(huì)將一臺(tái)機(jī)器的內(nèi)存耗盡,造成數(shù)據(jù)丟失,甚至服務(wù)器宕機(jī)。
性能瓶頸
簡(jiǎn)介中提到,雖然Redis在官方文檔中提到可以達(dá)到約100000+QPS,但是首先在日常環(huán)境的測(cè)試中,我們可能并達(dá)不到文檔中宣稱的QPS,換言之,這可能也就是一種理論值,就像是4G的理論網(wǎng)速在10-100Mbps,折合下載速度1.5M/s-10M/s。
但在日常生活中我們極少甚至從來(lái)沒(méi)有達(dá)到過(guò)這個(gè)速度過(guò),一樣的道理。其次,在中國(guó)巨大的網(wǎng)民基數(shù)下,單機(jī)Redis滿足日常需求尚且捉襟見(jiàn)肘,如果碰上像雙十一、雙十二、春運(yùn)這些特殊的環(huán)境,單臺(tái)Redis顯然會(huì)有性能不足的現(xiàn)象發(fā)生。
Redis集群的三種模式
主從模式
主從模式是最簡(jiǎn)單的一種Redis集群模式,首先其思想就是一臺(tái)Redis服務(wù)器作為主服務(wù)器(Master),一臺(tái)或多臺(tái)服務(wù)器作為從服務(wù)器(Slave)。當(dāng)以此種方式部署集群時(shí),集群有如下特點(diǎn):
Master可以進(jìn)行讀寫操作,當(dāng)寫操作導(dǎo)致數(shù)據(jù)發(fā)生變化時(shí),將自動(dòng)同步給Slave,Slave通常是只讀的,并且接受從Master同步過(guò)來(lái)的數(shù)據(jù)。
一臺(tái)Master可以有多臺(tái)Slave,但每臺(tái)Slave只能有一個(gè)Master。
某臺(tái)Slave宕機(jī)不影響其他Slave和Master的讀寫,重新啟動(dòng)后會(huì)將數(shù)據(jù)重新從Master同步過(guò)來(lái)。
Master宕機(jī)后不影響Slave的讀,但該集群不再提供對(duì)Redis的寫入功能。
Master宕機(jī)后不會(huì)從Slave中選舉主節(jié)點(diǎn)。
在此種模式下,我們可以對(duì)Redis集群做容災(zāi)備份和讀寫分離,但是要注意,容災(zāi)備份并不能拯救你的誤操作,因?yàn)闊o(wú)論增刪改,Redis都將其作為寫,同步到每個(gè)Slave節(jié)點(diǎn)上,所以容災(zāi),是指不可預(yù)知的錯(cuò)誤導(dǎo)致數(shù)據(jù)丟失,這種情況下可以從Slave節(jié)點(diǎn)中找到原數(shù)據(jù)的備份,從而進(jìn)行數(shù)據(jù)恢復(fù)。
而讀寫分離就比較好理解了,上文中提到,Master節(jié)點(diǎn)可以讀寫,而Slave節(jié)點(diǎn)通常只進(jìn)行讀操作,索性直接將所有的讀操作都轉(zhuǎn)移到Slave節(jié)點(diǎn)上,這樣可以減輕Master節(jié)點(diǎn)的IO壓力。
主從模式的工作原理(全量同步):
Redis全量同步一般發(fā)生在Slave初始化階段,但其實(shí)在任何時(shí)候Slave都可以向Master發(fā)起全量同步的請(qǐng)求,這時(shí)Slave需要將Master上的所有數(shù)據(jù)都復(fù)制一份。
Slave連接主服務(wù)器,發(fā)送SYNC命令。
Master接收到SYNC命令后,開(kāi)始執(zhí)行BGSAVE命令生成RDB文件并使用緩沖區(qū)記錄此后執(zhí)行的所有寫命令。
Master執(zhí)行完BGSAVE后,向所有從服務(wù)器發(fā)送RDB文件,并在發(fā)送期間繼續(xù)記錄被執(zhí)行的寫命令。
Slave收到RDB文件后丟棄所有舊數(shù)據(jù),載入收到的RDB。
Master快照發(fā)送完畢后開(kāi)始向Slave發(fā)送緩沖區(qū)中的寫命令。
Slave完成對(duì)RDB的載入,開(kāi)始接收命令請(qǐng)求,并執(zhí)行來(lái)自Master緩沖區(qū)的寫命令。
主從模式的工作原理(增量同步):
Redis增量同步一般發(fā)生在Slave已經(jīng)初始化完成,開(kāi)始正常連接Master的階段
Master接收到寫請(qǐng)求,將寫命令發(fā)送到Slave。
Slave執(zhí)行接收到的些命令。
注:如果多個(gè)Slave同時(shí)宕機(jī)重啟,那么就會(huì)同時(shí)向Master發(fā)送SYNC命令,那么有可能會(huì)造成Master節(jié)點(diǎn)的IO劇增,有可能會(huì)引起宕機(jī)。
哨兵(Sentinel)模式
上文中介紹了Redis主從復(fù)制模式下的集群策略,當(dāng)Master宕機(jī)后,不會(huì)從Slave節(jié)點(diǎn)中選舉出Master,所以該集群?jiǎn)适Я藢懙哪芰?,我們只能人工去將Slave節(jié)點(diǎn)晉升為Master節(jié)點(diǎn),同時(shí)要通知應(yīng)用方更新Master節(jié)點(diǎn)的IP地址,對(duì)于這種故障處理的方式在現(xiàn)在的環(huán)境下通常是不可接受的。所以從Redis2.8開(kāi)始,Redis正式提供了哨兵模式的架構(gòu)(故障轉(zhuǎn)移),來(lái)解決這個(gè)問(wèn)題。
哨兵模式的工作特點(diǎn):
哨兵模式是建立在主從模式的基礎(chǔ)上,當(dāng)Master節(jié)點(diǎn)宕機(jī)之后,哨兵會(huì)從Slave節(jié)點(diǎn)中選擇一個(gè)節(jié)點(diǎn)作為Master,并修改它們的配置文件,使其他的Slave指向新的Master。
當(dāng)原先宕機(jī)的Master節(jié)點(diǎn)重新啟動(dòng)時(shí),他將不再是Master,而是作為新Master的一個(gè)Slave節(jié)點(diǎn)存在。
哨兵節(jié)點(diǎn)是一個(gè)特殊的Redis節(jié)點(diǎn)(不存儲(chǔ)數(shù)據(jù)),本質(zhì)上也是一個(gè)進(jìn)程,所以也有掛掉的可能,所以哨兵也存在集群模式。
哨兵模式工作原理:
每隔10秒,每個(gè)哨兵節(jié)點(diǎn)會(huì)向Master和Slave節(jié)點(diǎn)發(fā)送info命令獲取最新的拓?fù)浣Y(jié)構(gòu)。
每隔1秒,每個(gè)哨兵節(jié)點(diǎn)會(huì)向Master和Slave節(jié)點(diǎn)還有其它哨兵節(jié)點(diǎn)發(fā)送ping命令做心跳檢測(cè),看看是否存在不可達(dá)的節(jié)點(diǎn)。
主觀下線,如果某個(gè)哨兵向一個(gè)節(jié)點(diǎn)發(fā)出的心跳檢測(cè)沒(méi)有得到響應(yīng),那么該哨兵認(rèn)為該節(jié)點(diǎn)已經(jīng)下線。
客觀下線,當(dāng)哨兵主觀下線的節(jié)點(diǎn)是主節(jié)點(diǎn)時(shí),哨兵會(huì)向其他的哨兵詢問(wèn)對(duì)主節(jié)點(diǎn)的判斷,當(dāng)下線判斷超過(guò)一定個(gè)數(shù)時(shí),那么哨兵會(huì)認(rèn)為主節(jié)點(diǎn)確實(shí)已經(jīng)下線,那么會(huì)對(duì)主節(jié)點(diǎn)進(jìn)行客觀下線的判定。
故障轉(zhuǎn)移,當(dāng)Master節(jié)點(diǎn)客觀下線時(shí),哨兵會(huì)從Slave節(jié)點(diǎn)中選擇一個(gè)節(jié)點(diǎn)作為Master節(jié)點(diǎn),選擇規(guī)則是選擇與主節(jié)點(diǎn)復(fù)制相似度最高的節(jié)點(diǎn),選擇完成后會(huì)將其余的Slave節(jié)點(diǎn)指向新的Master節(jié)點(diǎn),并監(jiān)控原來(lái)的Master節(jié)點(diǎn),當(dāng)它回復(fù)后作為新Master節(jié)點(diǎn)的Slave存在,并且同步新Master節(jié)點(diǎn)的數(shù)據(jù)。
選舉領(lǐng)導(dǎo)者哨兵節(jié)點(diǎn):當(dāng)主節(jié)點(diǎn)被判斷客觀下線以后,各個(gè)哨兵節(jié)點(diǎn)會(huì)進(jìn)行協(xié)商,選舉出一個(gè)領(lǐng)導(dǎo)者哨兵節(jié)點(diǎn),并由該領(lǐng)導(dǎo)者節(jié)點(diǎn)對(duì)其進(jìn)行故障轉(zhuǎn)移操作。
當(dāng)使用sentinel模式的時(shí)候,客戶端不用直接連接Redis,而是連接哨兵的ip和port,由哨兵來(lái)提供具體的可提供服務(wù)的Redis實(shí)現(xiàn),這樣當(dāng)master節(jié)點(diǎn)掛掉以后,哨兵就會(huì)感知并將新的master節(jié)點(diǎn)提供給使用者。
Cluster模式
在上文的哨兵模式中,哨兵引入了主節(jié)點(diǎn)的自動(dòng)故障轉(zhuǎn)移,進(jìn)一步提高了Redis的高可用性。但是哨兵的缺陷同樣很明顯:哨兵無(wú)法對(duì)Slave進(jìn)行自動(dòng)故障轉(zhuǎn)移,在讀寫分離場(chǎng)景下,Slave故障會(huì)導(dǎo)致讀服務(wù)不可用,需要我們對(duì)Slave做額外的監(jiān)控、切換操作。
此外,哨兵仍然沒(méi)有解決寫操作無(wú)法負(fù)載均衡、及存儲(chǔ)能力受到單機(jī)限制的問(wèn)題。
Redis Cluster模式是Redis3.0之后推薦的一種解決方案,其是由多個(gè)主節(jié)點(diǎn)群組成的分布式服務(wù)器群,它具有復(fù)制、高可用和分片的特性。另外,Redis Cluster集群不需要哨兵也能完成節(jié)點(diǎn)移除和故障轉(zhuǎn)移的功能。需要將每個(gè)節(jié)點(diǎn)設(shè)置為集群模式,這種集群模式?jīng)]有中心節(jié)點(diǎn),可水平擴(kuò)展,且集群配置非常簡(jiǎn)單。
Cluster集群模式工作特點(diǎn):
多個(gè)Redis節(jié)點(diǎn)互聯(lián),數(shù)據(jù)共享。
所有的節(jié)點(diǎn)都是主從模式,其中Slave不提供服務(wù),只提供備用。
不支持同時(shí)處理多個(gè)Key,因?yàn)樾枰职l(fā)到多個(gè)節(jié)點(diǎn)上。
支持在線增加、刪除節(jié)點(diǎn)。
客戶端可以連接任何一個(gè)Master節(jié)點(diǎn)進(jìn)行讀寫。
Cluster集群模式工作原理:
Redis Cluster有固定的16384個(gè)hash slot(槽),對(duì)每個(gè)key計(jì)算CRC16值,然后對(duì)16384取模,可以獲取key對(duì)應(yīng)的hash slot。每個(gè)master都會(huì)持有部分slot,比如有3個(gè)master,那么可能每個(gè)master持有5000多個(gè)hash slot,在redis cluster寫入數(shù)據(jù)的時(shí)候。
其實(shí)是你可以將請(qǐng)求發(fā)送到任意一個(gè)master上去執(zhí)行。但是,每個(gè)master都會(huì)計(jì)算這個(gè)key對(duì)應(yīng)的CRC16值,然后對(duì)16384個(gè)hashslot取模,找到key對(duì)應(yīng)的hashslot,找到hashslot對(duì)應(yīng)的master。
主觀下線(pfail):集群中的每個(gè)節(jié)點(diǎn)都會(huì)定期向其他節(jié)點(diǎn)發(fā)送ping消息,如果在一段時(shí)間內(nèi)一直通信失敗,則發(fā)送節(jié)點(diǎn)方認(rèn)為接收節(jié)點(diǎn)存在故障,把接收節(jié)點(diǎn)標(biāo)為主觀下線(pfail)狀態(tài)。
客觀下線(fail):當(dāng)某個(gè)節(jié)點(diǎn)判斷另一個(gè)節(jié)點(diǎn)主觀下線后,相應(yīng)的節(jié)點(diǎn)狀態(tài)就會(huì)在集群中進(jìn)行傳播,如果集群中所有節(jié)點(diǎn)都將它標(biāo)為主觀下線,那么該節(jié)點(diǎn)為客觀下線,并通知該節(jié)點(diǎn)的Slave進(jìn)行故障轉(zhuǎn)移操作。
故障轉(zhuǎn)移:在某個(gè)節(jié)點(diǎn)客觀下線后,該節(jié)點(diǎn)的從節(jié)點(diǎn)開(kāi)始故障轉(zhuǎn)移流程,首先進(jìn)行資格檢查,每個(gè)從節(jié)點(diǎn)檢查與主節(jié)點(diǎn)的斷開(kāi)時(shí)間,超過(guò)一定時(shí)間的取消選舉資格,然后同樣在所有從節(jié)點(diǎn)中尋找復(fù)制偏移量最大的節(jié)點(diǎn)先開(kāi)始進(jìn)行選舉,只有持有槽的主節(jié)點(diǎn)才有投票權(quán),當(dāng)從節(jié)點(diǎn)收集到過(guò)半的票數(shù)時(shí),即晉升為Master,隨即通知Slave當(dāng)前Master變?yōu)樽约骸?/p>
搭建Redis集群
上文中說(shuō)了三種Redis搭建的模式,分別是主從模式、哨兵模式、Cluster模式,關(guān)于前兩種網(wǎng)上有著非常多的教程,這里就不再重新演示了,這里著重演示一下如何去搭建一個(gè)Redis Cluster集群。
環(huán)境準(zhǔn)備
CentOS 7,Redis5.0.4
場(chǎng)景描述
本次會(huì)啟動(dòng)三臺(tái)CentOS 7服務(wù)器,每臺(tái)服務(wù)器上搭載三個(gè)Redis實(shí)例,一主二從,一共三個(gè)Master實(shí)例,六個(gè)Slave實(shí)例。
清單如下:
修改配置文件
熟悉Redis的應(yīng)該明白,所謂Redis實(shí)例,實(shí)際上就是一個(gè)又一個(gè)的配置文件。要在服務(wù)器上啟動(dòng)多臺(tái)不同Redis,實(shí)際上就是使用不同的配置文件來(lái)啟動(dòng)Redis,所以第一步我們要先對(duì)集群中的每一個(gè)Redis實(shí)例配置不一樣的配置文件。
綁定Redis地址
下列三臺(tái)主機(jī)上的配置文件均為Master節(jié)點(diǎn)配置文件(修改bind屬性)
修改端口號(hào)
將端口號(hào)修改為自定義的端口號(hào),默認(rèn)為6379,修改為我們自定義的端口號(hào)。
將cluster-enabled 設(shè)置為yes,并將cluster-config-file設(shè)置為自定義的文件。
這里定義為nodes-端口號(hào).conf
修改集群RDB快照和AOF文件的存放位置
修改dir屬性,這里定義為/home/redis-cluster/redis-master/
修改集群密碼
修改masterauth屬性為Redis(RequirePass)密碼。
開(kāi)啟AOF持久化
修改appendonly屬性
對(duì)六臺(tái)Slave節(jié)點(diǎn)進(jìn)行同樣的修改配置操作
注意:上述指定的文件夾和文件名原則上對(duì)于每個(gè)redis實(shí)例都應(yīng)該是唯一的,便于區(qū)分。
啟動(dòng)Redis實(shí)例
運(yùn)行命令:
查看進(jìn)程 ps -ef | grep redis:
可以看到現(xiàn)在啟動(dòng)的redis實(shí)例已經(jīng)是集群模式的了。
搭建集群
輸入命令:
其中 --cluster-replicas 2代表每個(gè)Master攜帶2個(gè)Slave,那么就是三個(gè)Master,每個(gè)Master攜帶兩個(gè)Slave。
示意圖如下:
我們可以看到,Redis將三臺(tái)機(jī)器連成了一個(gè)整體,Master7001的Slave指向了其它兩臺(tái)服務(wù)器上的Slave,而其它兩臺(tái)服務(wù)器的Master也同樣跨服務(wù)器指向了,這就是RedisCluster高可用的策略,假設(shè)有一臺(tái)服務(wù)器完整地宕機(jī)了,由于自己的Slave節(jié)點(diǎn)存在于別的服務(wù)器上,數(shù)據(jù)也能重新通過(guò)選舉選舉的方式恢復(fù),不易引起數(shù)據(jù)的丟失。
另外我們可以看到,我們?cè)谏衔恼f(shuō)過(guò),Cluster集群模式將集群分為16384個(gè)槽,這里體現(xiàn)為0-16383,分布到了每一個(gè)Master節(jié)點(diǎn)上,這對(duì)我們之前的理論部分做了驗(yàn)證。
測(cè)試
測(cè)試環(huán)節(jié)通過(guò)客戶端測(cè)試和Java程序測(cè)試,來(lái)模擬集群模式下Redis的存儲(chǔ)策略。
客戶端測(cè)試
開(kāi)啟客戶端,隨意連接一個(gè)master節(jié)點(diǎn)
我們可以看到,當(dāng)我們set一個(gè)鍵值對(duì)的時(shí)候,Redis會(huì)自動(dòng)為我們的key計(jì)算CRC16值,然后對(duì)16384取模,獲取key對(duì)應(yīng)的hash slot,然后通過(guò)判斷該槽被那個(gè)Master所占用,幫我們重定向到那個(gè)Master節(jié)點(diǎn),將鍵值對(duì)存入。
程序測(cè)試
在測(cè)試之前先把Redis中的數(shù)據(jù)清空,對(duì)三個(gè)Master節(jié)點(diǎn)分別執(zhí)行flushall命令。
啟動(dòng)程序:
1.正常存入數(shù)據(jù)時(shí)關(guān)閉某Master節(jié)點(diǎn)(模擬宕機(jī)):
程序打印正在選舉…
2.選舉結(jié)束后繼續(xù)IO
代碼:
注意事項(xiàng)
在搭建集群的過(guò)程中有可能會(huì)遇到一直等待連接,但是集群無(wú)法連接成功的狀況,這是因?yàn)槲覀冊(cè)诖罱旱臅r(shí)候防火墻沒(méi)有開(kāi)啟對(duì)應(yīng)的端口號(hào)導(dǎo)致的,我們不光要開(kāi)啟我們對(duì)外連接的端口號(hào),如7001、7002、7003,還要開(kāi)啟對(duì)外連接端口號(hào)+10000的端口,用于集群內(nèi)部相互通信,如節(jié)點(diǎn)端口為7001、7002、7003,那么我們還應(yīng)該開(kāi)啟17001、17002、17003這些端口。
如果遇到搭建失敗的情況,重新搭建的時(shí)候一定要到dir指向的文件夾中將快照和AOF還有node.conf文件刪干凈,否則無(wú)法重新搭建。
搭建完畢
至此我們已經(jīng)完成了Redis集群的搭建,在私下實(shí)踐的時(shí)候可以試試使用Redis客戶端直接操作集群時(shí)手動(dòng)關(guān)閉某個(gè)Master,會(huì)出現(xiàn)什么樣的狀況,這個(gè)是文章中沒(méi)有提到的內(nèi)容。
什么是MySQL主從同步
數(shù)據(jù)是一個(gè)應(yīng)用至關(guān)重要的一部分。從目的出發(fā),主從同步有那么點(diǎn)備份的意思,主庫(kù)(Master)將自己庫(kù)中的寫入同時(shí)同步給自己的從庫(kù)(Slave),當(dāng)主庫(kù)發(fā)生某些不可預(yù)知的狀況,導(dǎo)致整個(gè)服務(wù)器無(wú)法使用時(shí),由于從庫(kù)中也有一份數(shù)據(jù),所以數(shù)據(jù)可以做到快速恢復(fù),不造成或者減少造成數(shù)據(jù)的損失。
當(dāng)然,這只是第一個(gè)層面,如果主從庫(kù)的作用僅限于此,那么我個(gè)人認(rèn)為沒(méi)有必要分為兩個(gè)數(shù)據(jù)庫(kù),只需要定期將數(shù)據(jù)庫(kù)內(nèi)容作為快照發(fā)送到另一臺(tái)服務(wù)器,或者每次寫入時(shí)將寫入內(nèi)容實(shí)時(shí)發(fā)送到另一臺(tái)服務(wù)器不就好了嗎,這樣不但可以節(jié)約資源,也可以起到容災(zāi)備份的目的。
當(dāng)然主從同步的作用絕不可能僅限于此,一旦我們配置了主從結(jié)構(gòu),我們通常不會(huì)讓從節(jié)點(diǎn)僅僅只作為備份數(shù)據(jù)庫(kù),我們應(yīng)該還會(huì)相應(yīng)地配置上讀寫分離(可以使用MyCat或者其它中間件,可以自己了解一下,關(guān)于MyCat我在下一篇博客中會(huì)說(shuō)這個(gè),篇幅可能會(huì)有點(diǎn)長(zhǎng),所以就再寫一篇吧)。
在實(shí)際環(huán)境下,對(duì)于數(shù)據(jù)庫(kù)的讀操作數(shù)目遠(yuǎn)大于對(duì)數(shù)據(jù)庫(kù)的寫操作,所以我們可以讓Master只提供寫的功能,然后將所有的讀操作都移到從庫(kù),這就是我們平時(shí)常說(shuō)的讀寫分離,這樣不但可以減輕Master的壓力,還可以做容災(zāi)備份,一舉兩得。
MySQL主從同步的原理
說(shuō)完了主從同步的概念,下面來(lái)說(shuō)說(shuō)主從同步的原理,其實(shí)原理也非常簡(jiǎn)單,沒(méi)有Redis集群那么多的概念。
實(shí)際上當(dāng)我們?cè)贛ySQL中配置了主從之后,只要我們對(duì)Master節(jié)點(diǎn)進(jìn)行了寫操作,這個(gè)操作將會(huì)被保存到MySQL的binary-log(bin-log)日志當(dāng)中,當(dāng)slave連接到master的時(shí)候,master機(jī)器會(huì)為slave開(kāi)啟binlog dump線程。當(dāng)master 的 binlog發(fā)生變化的時(shí)候,Master的dump線程會(huì)通知slave,并將相應(yīng)的binlog內(nèi)容發(fā)送給Slave。而Slave節(jié)點(diǎn)在主從同步開(kāi)啟的時(shí)候,會(huì)創(chuàng)建兩個(gè)線程,一個(gè)I/O線程,一個(gè)SQL線程,這在我們后面的搭建中可以親眼看到。
I/0線程:該線程鏈接到master機(jī)器,master機(jī)器的binlog發(fā)送到slave的時(shí)候,IO線程會(huì)將該日志內(nèi)容寫在本地的中繼日志(Relay log)中。
SQL線程:該線程讀取中繼日志中的內(nèi)容,并且根據(jù)中繼日志中的內(nèi)容對(duì)Slave數(shù)據(jù)庫(kù)做相應(yīng)的操作。
可能造成的問(wèn)題:在寫請(qǐng)求相當(dāng)多的情況下,可能會(huì)造成Slave數(shù)據(jù)和Master數(shù)據(jù)不一致的情況,這是因?yàn)槿罩緜鬏斶^(guò)程中的短暫延遲、或者寫命令較多,系統(tǒng)速度不匹配造成的。
這大致就是MySQL主從同步的原理,真正在其中起到作用的實(shí)際上就是這兩個(gè)日志文件,binlog和中繼日志。
手動(dòng)搭建MySQL主從同步
環(huán)境準(zhǔn)備
本次搭建主從同步的環(huán)境:CentOS 7 ,MySQL 8.0.18(使用二進(jìn)制包安裝)。
場(chǎng)景介紹
本次將會(huì)搭建MySQL的主從同步,其中一臺(tái)Master,兩臺(tái)Slave。
開(kāi)始搭建
修改配置文件
當(dāng)我們安裝好MySQL之后,在/etc/目錄下會(huì)有一個(gè)my.cnf文件,打開(kāi)文件,加入如下內(nèi)容(別忘了修改之前做好備份):
x
y
新增Slave用戶
打開(kāi)Master節(jié)點(diǎn)的客戶端 ,mysql -u root -p 密碼
創(chuàng)建用戶 create user 'Slave'@'%' identified by '123456';
給新創(chuàng)建的用戶賦權(quán):grant replication slave on '*.*' to 'Slave'@'%';
查看Master節(jié)點(diǎn)狀態(tài)
以上操作都沒(méi)有問(wèn)題后,我們?cè)诳蛻舳酥休斎雜how master status查看master的binlog日志。
配置兩個(gè)Slave節(jié)點(diǎn)
打開(kāi)兩個(gè)Slave節(jié)點(diǎn)客戶端,在我們的另外兩個(gè)Slave節(jié)點(diǎn)中輸入如下命令:
配置完成后,輸入start slave;開(kāi)啟從節(jié)點(diǎn),然后輸入show slave status\G;查看從節(jié)點(diǎn)狀態(tài)
可以看到,在兩臺(tái)Slave的狀態(tài)中,我們能親眼看到IO線程和SQL線程的運(yùn)行狀態(tài),這兩個(gè)線程必須都是yes,才算配置搭建完成。
搭建完成
通過(guò)上述步驟,就完成了MySQL主從同步的搭建,相對(duì)Redis而言MySQL配置相當(dāng)簡(jiǎn)單。下面我們可以進(jìn)行測(cè)試。
先看看三個(gè)MySQL的數(shù)據(jù)庫(kù)狀態(tài):SHOW DATABASES;
可以看到現(xiàn)在數(shù)據(jù)庫(kù)都是初始默認(rèn)狀態(tài),沒(méi)有任何額外的庫(kù)。
在Master節(jié)點(diǎn)中創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),庫(kù)名可以自己設(shè)置。
CREATE DATABASE testcluster;
可以看到,在Slave中也出現(xiàn)了Master中創(chuàng)建的數(shù)據(jù)庫(kù),說(shuō)明我們的配置沒(méi)有問(wèn)題,主從搭建成功。這里就不再創(chuàng)建表了,大家可以自己試試,創(chuàng)建表再往表中插入數(shù)據(jù),也是沒(méi)有任何問(wèn)題的。
注意事項(xiàng)
如果出現(xiàn)IO線程一直在Connecting狀態(tài),可以看看是不是三臺(tái)機(jī)器無(wú)法相互連接,如果可以相互連接,那么有可能是Slave賬號(hào)密碼寫錯(cuò)了,重新關(guān)閉Slave然后輸入上面的配置命令再打開(kāi)Slave即可。
如果出現(xiàn)SQL線程為NO狀態(tài),那么有可能是從數(shù)據(jù)庫(kù)和主數(shù)據(jù)庫(kù)的數(shù)據(jù)不一致造成的,或者事務(wù)回滾,如果是后者,先關(guān)閉Slave,然后先查看master的binlog和position,然后輸入配置命令,再輸入set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;,再重新start slave;即可,如通過(guò)是前者,那么就排查一下是不是存在哪張表沒(méi)有被同步,是否存在主庫(kù)存在而從庫(kù)不存在的表,自己同步一下再重新配置一遍即可。
結(jié)語(yǔ)
在寫這篇文章之前自己也被一些計(jì)算機(jī)領(lǐng)域的“名詞”嚇到過(guò),相信有不少朋友都有一樣的體會(huì),碰上某些高大上的名詞總是先被嚇到,例如像“分布式”、“集群”等等等等,甚至在沒(méi)接觸過(guò)nginx之前,連”負(fù)載均衡“、”反向代理“這樣的詞都讓人覺(jué)得,這么高達(dá)上的詞,肯定很難吧,但其實(shí)自己了解了nginx、ribbon等之后才發(fā)現(xiàn),其實(shí)也就那么回事吧,沒(méi)有想象中的那么難。
所以寫這篇文章的初衷是想讓大家對(duì)集群化或者分布式或者其他的一些技術(shù)或者解決方案不要有一種望而卻步的感覺(jué)(感覺(jué)計(jì)算機(jī)領(lǐng)域的詞都有這么一種特點(diǎn),詞匯高大上,但是其實(shí)思想是比較好理解的),其實(shí)自己手動(dòng)配置出一個(gè)簡(jiǎn)單的集群并沒(méi)有那么難。
如果學(xué)會(huì)docker之后再來(lái)配置就更加簡(jiǎn)單了,但是更希望不要只局限于會(huì)配置,配置出來(lái)的東西只能說(shuō)你會(huì)配置了,但是在這層配置底下是前人做了相當(dāng)多的工作,才能使我們通過(guò)簡(jiǎn)單配置就能實(shí)現(xiàn)一些功能,應(yīng)該要深入底層,了解配置下面的工作原理,這個(gè)才是最重要的,也是體現(xiàn)一個(gè)程序員水平的地方。
聯(lián)系客服