鏡 | 5 個(gè)維度深度剖析「主從架構(gòu)」原理
前言
玩過(guò)王者榮耀的同學(xué),應(yīng)該都知道里面有個(gè)英雄叫做鏡,她釋放技能時(shí),會(huì)出現(xiàn)一個(gè)長(zhǎng)相一模一樣的分身,而且動(dòng)作也是一樣的。
那么我們今天要討論的主從架構(gòu)原理其實(shí)就是多個(gè)節(jié)點(diǎn)中有一個(gè)作為本體,其他節(jié)點(diǎn)作為分身存在,但是本體和分身的數(shù)據(jù)都是一樣的,數(shù)據(jù)總是保持一致,是不是和鏡很相似呢?
為了保證緩存的高可用,我們經(jīng)常聽(tīng)到采用主從架構(gòu)來(lái)保證高可用,那如何去理解主從架構(gòu)核心原理呢?
這次我們還是用最熟悉的 Redis 緩存來(lái)理解主從架構(gòu),只要理解了一個(gè)主從架構(gòu),其他技術(shù)的主從架構(gòu)都是一通百通。
Redis 的主從架構(gòu),其實(shí)就是利用多副本,將一份數(shù)據(jù)同時(shí)保存在多個(gè)實(shí)例上。單個(gè)實(shí)例出現(xiàn)故障后,一般都會(huì)過(guò)一段時(shí)間才能恢復(fù),那么其他節(jié)點(diǎn)還是可以提供服務(wù)的。
本篇我會(huì)帶著大家一起探討緩存的主從架構(gòu)幾個(gè)問(wèn)題:
Why:為什么需要主從架構(gòu)? What:主從架構(gòu)原理? Who:誰(shuí)需要關(guān)心主從架構(gòu)? When:什么時(shí)候用主從架構(gòu)? Question:主從架構(gòu)會(huì)帶來(lái)哪些問(wèn)題?
Why:為什么需要主從架構(gòu)?
Redis 單機(jī)我們都玩得很溜了,那單點(diǎn)架構(gòu)會(huì)帶來(lái)什么問(wèn)題?
造成服務(wù)雪崩:高并發(fā)場(chǎng)景下,Redis 單點(diǎn)故障了,導(dǎo)致請(qǐng)求到 Redis 后都返回錯(cuò)誤,或者請(qǐng)求都到數(shù)據(jù)庫(kù)了,造成服務(wù)雪崩,這是不能接受的。 不能進(jìn)行快速轉(zhuǎn)移:線上系統(tǒng),Redis 單點(diǎn)故障了,沒(méi)有其他的備份節(jié)點(diǎn)可用。如何做到故障快速轉(zhuǎn)移? 不能快速恢復(fù)數(shù)據(jù):Redis 是內(nèi)存數(shù)據(jù)庫(kù),內(nèi)存數(shù)據(jù)會(huì)自動(dòng)備份到 RDB 和 AOF 文件(開(kāi)啟了兩種持久化的情況下),當(dāng)某個(gè)節(jié)點(diǎn)出現(xiàn)故障時(shí),能將這些備份文件快速恢復(fù)到節(jié)點(diǎn),將故障造成的影響降到最低。
服務(wù)的快速轉(zhuǎn)移和恢復(fù)數(shù)據(jù),其實(shí)是高可用的范疇,我們就可以通過(guò)主從架構(gòu)來(lái)做到了。
What:主從架構(gòu)原理
文中最開(kāi)始也提到過(guò)這么一段話,劃重點(diǎn):
Redis 的主從架構(gòu),其實(shí)就是利用多副本,將一份數(shù)據(jù)同時(shí)保存在多個(gè)實(shí)例上。單個(gè)實(shí)例出現(xiàn)故障后,一般都會(huì)過(guò)一段時(shí)間才能恢復(fù),那么其他節(jié)點(diǎn)還是可以提供服務(wù)的。
主從架構(gòu)拓?fù)鋱D
Redis 主從架構(gòu)其實(shí)就是主從庫(kù)模式,而主從庫(kù)的模式可以分為三種拓?fù)浣Y(jié)構(gòu):一主一從結(jié)構(gòu)、一主多從結(jié)構(gòu)、樹(shù)狀主從結(jié)構(gòu)。而如何去構(gòu)建這種結(jié)構(gòu)其實(shí)也很簡(jiǎn)單,就是配置下多個(gè)節(jié)點(diǎn)上 Redis 的配置文件就可以了。如下所示:
slaveof <Master IP> <Master Port>
當(dāng)然還有一些其他參數(shù)配置,就不在本篇講解,下篇主從的部署教程其實(shí)已經(jīng)寫(xiě)好了,后續(xù)發(fā)出來(lái)。
下面我們接著來(lái)看這幾種主從架構(gòu):
一主一從結(jié)構(gòu):一個(gè)主節(jié)點(diǎn),一個(gè)從節(jié)點(diǎn),主節(jié)點(diǎn)可讀可寫(xiě),從節(jié)點(diǎn)只接收讀請(qǐng)求。常用于主節(jié)點(diǎn)出現(xiàn)故障時(shí),從節(jié)點(diǎn)能夠快速頂上。
一主多從結(jié)構(gòu):一個(gè)主節(jié)點(diǎn),多個(gè)從節(jié)點(diǎn),對(duì)于讀命令較大的場(chǎng)景,可以把讀命令分?jǐn)偟蕉鄠€(gè)從節(jié)點(diǎn)。
而對(duì)于一主多從結(jié)構(gòu),還可以再擴(kuò)展一點(diǎn):當(dāng)日常開(kāi)發(fā)中需要執(zhí)行一些比較耗時(shí)的讀命令時(shí),比如 keys、sort等,可以用其中一個(gè)從節(jié)點(diǎn)專(zhuān)門(mén)作為耗時(shí)查詢(xún)用的從節(jié)點(diǎn),避免慢查詢(xún)對(duì)主節(jié)點(diǎn)造成阻塞,而影響服務(wù)的穩(wěn)定性。我們也可以用圖來(lái)進(jìn)行說(shuō)明:
樹(shù)狀主從結(jié)構(gòu):一個(gè)主節(jié)點(diǎn),多個(gè)從節(jié)點(diǎn),其中一個(gè)從節(jié)點(diǎn)作為中間層,既可以復(fù)制主節(jié)點(diǎn),又可以當(dāng)做其他從節(jié)點(diǎn)復(fù)制的主節(jié)點(diǎn)。有效降低主節(jié)點(diǎn)負(fù)載和需要傳送給從節(jié)點(diǎn)的數(shù)據(jù)量。
主從復(fù)制的方式
從節(jié)點(diǎn)復(fù)制主節(jié)點(diǎn)的數(shù)據(jù)后,就相當(dāng)于給主從節(jié)點(diǎn)備份了,所謂的有備無(wú)患就是這個(gè)意思。那么主從復(fù)制的原理是怎么樣的?其實(shí)主要就是三種復(fù)制方式:持續(xù)復(fù)制、全量復(fù)制、部分復(fù)制。
持續(xù)復(fù)制
當(dāng)有客戶(hù)端的寫(xiě)命令請(qǐng)求到主節(jié)點(diǎn)后,主節(jié)點(diǎn)會(huì)做兩件事:命令傳播和將寫(xiě)命令寫(xiě)入到復(fù)制積壓緩沖區(qū)。
原理圖如下:
命令傳播:將寫(xiě)命令持續(xù)發(fā)送給所有從服務(wù)器,保持主從數(shù)據(jù)一致。這個(gè)就可以理解為持續(xù)復(fù)制了。 復(fù)制積壓緩沖區(qū):其實(shí)就是一個(gè)有界隊(duì)列,保存著最近傳播的寫(xiě)命令,而隊(duì)列里面的每個(gè)字節(jié)都有一個(gè)偏移量標(biāo)識(shí)。復(fù)制積壓緩沖區(qū)的作用和原理在部分復(fù)制的時(shí)候再細(xì)講。
全量復(fù)制
用于主從節(jié)點(diǎn)第一次復(fù)制的場(chǎng)景。這在我們的軟件開(kāi)發(fā)中也很常見(jiàn),比如你要把第三方的用戶(hù)數(shù)據(jù)同步到自己的系統(tǒng)中,一開(kāi)始肯定是把存量用戶(hù)一次性給復(fù)制過(guò)來(lái),后續(xù)有新增或更新的用戶(hù)就采用增量更新就可以了。
當(dāng)然全量復(fù)制的時(shí)候,數(shù)據(jù)量很大時(shí),就會(huì)對(duì)主從節(jié)點(diǎn)和網(wǎng)絡(luò)造成很大的開(kāi)銷(xiāo),也就是常說(shuō)的復(fù)制風(fēng)暴,所以要避免不必要的全量復(fù)制,這個(gè)后面再講怎么避免。
我們先來(lái)看下全量復(fù)制的原理圖,然后我再來(lái)詳細(xì)解釋每一步怎么做的。
全量復(fù)制總共可以分為 9 步:
(1)從節(jié)點(diǎn)發(fā)送 psync 命令進(jìn)行數(shù)據(jù)同步,會(huì)發(fā)送 psync 命令,來(lái)告訴主節(jié)點(diǎn)我想干啥。
psync 命令格式如下:
psync {runId} {offset}
runId 是 每個(gè) Redis 實(shí)例啟動(dòng)時(shí)隨機(jī)生成的一個(gè) ID,用來(lái)唯一標(biāo)記這臺(tái) Redis 實(shí)例。由于第一次復(fù)制時(shí),剛啟動(dòng)時(shí)會(huì)隨機(jī)生成 runId,只有自己知道,外人是不知道的,所以從節(jié)點(diǎn)是不知道主節(jié)點(diǎn)的 runId 的,這個(gè)時(shí)候發(fā)送 psync 命令時(shí) runId 就是一個(gè)問(wèn)號(hào)。第一次復(fù)制時(shí),offset 默認(rèn)為 -1。
(2)主節(jié)點(diǎn)響應(yīng)從節(jié)點(diǎn),要開(kāi)始全量復(fù)制了哦。
主節(jié)點(diǎn)響應(yīng)從節(jié)點(diǎn)時(shí)分三種情況:全量復(fù)制、部分復(fù)制、舊版全量復(fù)制流程,這三種的區(qū)別后面會(huì)專(zhuān)門(mén)講到。
而這個(gè)階段就是全量復(fù)制:主節(jié)點(diǎn)告訴從節(jié)點(diǎn),要開(kāi)始全量復(fù)制了哦。響應(yīng)如下命令:
FULLRESYNC <runId> <offset>
runId 就是主節(jié)點(diǎn) id,offset 為復(fù)制偏移量。
(3)從節(jié)點(diǎn)收到主節(jié)點(diǎn)響應(yīng)的 runId 和 offset,將其保存到從節(jié)點(diǎn)本地,這兩個(gè)參數(shù)以后會(huì)用到。
(4)主節(jié)點(diǎn)在后臺(tái)執(zhí)行 bgsave 命令保存 RDB 文件到主節(jié)點(diǎn)的本地。
(5)主節(jié)點(diǎn)將第四步生成的 RDB 文件發(fā)送給從節(jié)點(diǎn),子節(jié)點(diǎn)收到 RDB 文件后,保存到本地,后面會(huì)用到。這個(gè)發(fā)送的過(guò)程也可能直接超時(shí)。比如一個(gè) 6 GB 的 RDB 文件,100 MB 帶寬下,至少需要 60 秒的傳輸時(shí)間,很容易超出默認(rèn)配置的超時(shí)時(shí)間。那么從節(jié)點(diǎn)將放棄接收 RDB 文件,并清理已經(jīng)下載的臨時(shí)文件,導(dǎo)致全量復(fù)制失敗。所以推薦不要超過(guò) 6 GB,如果 RDB 文件實(shí)在太大了,可以調(diào)大 repl-timeout 超時(shí)參數(shù)。
(6)在第五步的時(shí)候,主節(jié)點(diǎn)也沒(méi)有閑著,會(huì)往另外一個(gè)緩沖區(qū)寫(xiě)東西,就是來(lái)自客戶(hù)端的寫(xiě)命令數(shù)據(jù)。這個(gè)緩沖區(qū)叫做:復(fù)制客戶(hù)端緩沖區(qū)。等第五步完成后,主節(jié)點(diǎn)就把這個(gè)緩沖區(qū)的數(shù)據(jù)發(fā)送給從節(jié)點(diǎn)。注意:對(duì)于高流量寫(xiě)入的場(chǎng)景,很容易就把復(fù)制客戶(hù)端緩沖區(qū)給占滿(mǎn)了,如果 60 秒內(nèi)緩沖區(qū)消耗持續(xù)大于 64 MB 或者直接超過(guò) 256 MB 時(shí),主節(jié)點(diǎn)將直接關(guān)閉復(fù)制客戶(hù)端連接,造成全量不同失敗。
(7)從節(jié)點(diǎn)在第五步保存完 RDB 文件后,就會(huì)把自身的舊數(shù)據(jù)清空。
(8)歷經(jīng)磨難,從節(jié)點(diǎn)終于可以開(kāi)始加載 RDB 文件了,但是對(duì)于較大的 RDB 文件,加載 RDB 文件,進(jìn)行數(shù)據(jù)恢復(fù),還是非常耗時(shí)的,如果從節(jié)點(diǎn)負(fù)責(zé)響應(yīng)讀命令,則可能拿到過(guò)期或錯(cuò)誤的數(shù)據(jù)。
(9)從節(jié)點(diǎn)加載完 RDB 后,如果當(dāng)前節(jié)點(diǎn)開(kāi)啟了 AOF 持久化功能,從節(jié)點(diǎn)會(huì)執(zhí)行 bgrewriteof 操作,保證 AOF 持久化文件可以立刻使用。
“總結(jié)下全量復(fù)制的步驟:
”
從節(jié)點(diǎn)給主節(jié)點(diǎn)發(fā)送命令;
主節(jié)點(diǎn)回復(fù)從節(jié)點(diǎn),要開(kāi)始全量復(fù)制了;
從節(jié)點(diǎn)保存主節(jié)點(diǎn)信息;
主節(jié)點(diǎn)開(kāi)始生成 RDB 快照文件;
RDB 文件發(fā)給從節(jié)點(diǎn),主節(jié)點(diǎn)發(fā)送 RDB 文件;
主節(jié)點(diǎn)發(fā)送緩存的客戶(hù)端命令;
從節(jié)點(diǎn)清空舊數(shù)據(jù);
從節(jié)點(diǎn)加載 RDB 文件;
從節(jié)點(diǎn)執(zhí)行 AOF 操作。
由上面的幾個(gè)步驟可以看出,全量復(fù)制是非常耗時(shí)的,可能比較大的時(shí)間開(kāi)銷(xiāo)如下:
第四步,主節(jié)點(diǎn) fork 出子進(jìn)程執(zhí)行 bgsave 時(shí),fork 操作耗時(shí)。 第五步,RDB 文件的網(wǎng)絡(luò)傳輸時(shí)間。 第七步,從節(jié)點(diǎn)清空數(shù)據(jù)花時(shí)間。 第八步,從節(jié)點(diǎn)加載 RDB 的時(shí)間。 第九步,AOF 的重寫(xiě)時(shí)間。
所以除了第一次需要采用全量復(fù)制外,其他場(chǎng)景應(yīng)該避免全量復(fù)制的發(fā)生。下面介紹另外一種復(fù)制方式,可以極大提高復(fù)制的效率。
部分復(fù)制
這個(gè)可以理解為增量更新,比如和第三方系統(tǒng)對(duì)接時(shí),如果第三方有數(shù)據(jù)更新,定期進(jìn)行增量更新就可以了。
而 Redis 主從的部分復(fù)制就是指當(dāng)主從之間的網(wǎng)絡(luò)故障等原因造成持續(xù)復(fù)制中斷了,當(dāng)從節(jié)點(diǎn)再次連上主節(jié)點(diǎn)后,主節(jié)點(diǎn)就補(bǔ)發(fā)數(shù)據(jù)給從節(jié)點(diǎn),避免了全量復(fù)制的過(guò)高開(kāi)銷(xiāo)。補(bǔ)發(fā)數(shù)據(jù)的來(lái)源就是復(fù)制積壓緩沖的數(shù)據(jù)。
原理圖如下所示:
部分復(fù)制總共分為六步:
(1)當(dāng)主節(jié)點(diǎn)之間失聯(lián)后,如果時(shí)間超過(guò)了 repl-timeout 時(shí)間,主節(jié)點(diǎn)就認(rèn)為從節(jié)點(diǎn)發(fā)生故障了,中斷連接。
(2)主節(jié)點(diǎn)其實(shí)一直都在把客戶(hù)端寫(xiě)命令放入復(fù)制積壓緩沖區(qū),所以即使斷連了,主節(jié)點(diǎn)還是會(huì)保留斷連期間的命令,但因?yàn)殛?duì)列是固定的,當(dāng)寫(xiě)命令太多時(shí),就會(huì)導(dǎo)致部分命令被覆蓋了。
(3)主從節(jié)點(diǎn)恢復(fù)連接。
(4)從節(jié)點(diǎn)發(fā)送 psync 命令給主節(jié)點(diǎn),帶有 runId 和 offset 參數(shù),runId 是上一次復(fù)制時(shí)保存的主節(jié)點(diǎn)的 runId值,offset 是從節(jié)點(diǎn)的復(fù)制偏移量。
(5)主節(jié)點(diǎn)接收到從節(jié)點(diǎn)的命令后,先判斷傳過(guò)來(lái)的 runId 是否和自己匹配,如果不匹配,則進(jìn)行全量復(fù)制;如果 runId 匹配,則響應(yīng) CONTINUE,告訴從節(jié)點(diǎn),可以進(jìn)行部分復(fù)制了。我要把復(fù)制積壓緩沖區(qū)的數(shù)據(jù)發(fā)給你了哦,請(qǐng)準(zhǔn)備好接收。
(6)主節(jié)點(diǎn)根據(jù)子節(jié)點(diǎn)發(fā)送的偏移量,將復(fù)制積壓緩沖區(qū)的數(shù)據(jù)發(fā)送給子節(jié)點(diǎn)。
那復(fù)制積壓緩沖區(qū)到底是怎么來(lái)根據(jù)偏移量來(lái)計(jì)算要發(fā)送哪些緩存數(shù)據(jù)的呢?我們接著往下看。
復(fù)制積壓緩沖區(qū)
復(fù)制積壓緩沖區(qū)有幾個(gè)特點(diǎn):
固定長(zhǎng)度的隊(duì)列。 最近傳播的寫(xiě)命令,默認(rèn)為 1 MB 大小,可調(diào)節(jié)大小。 隊(duì)列中的每個(gè)字節(jié)都有對(duì)應(yīng)的復(fù)制偏移量進(jìn)行標(biāo)識(shí)。如下圖所示,每一個(gè)字節(jié)對(duì)應(yīng)一個(gè)偏移量。
從節(jié)點(diǎn)重新連上主節(jié)點(diǎn)后,會(huì)發(fā)送 psync 命令,攜帶著偏移量 offset。比如 offset = 125,然后主節(jié)點(diǎn)拿著這個(gè) 125 去復(fù)制積壓緩沖區(qū)找,125 正好在里面,然后就會(huì)執(zhí)行部分復(fù)制的操作,將 125 以后的緩沖數(shù)據(jù)發(fā)送給從節(jié)點(diǎn)。
如果 offset =10,主節(jié)點(diǎn)拿著這個(gè) 10 去復(fù)制積壓緩沖區(qū)找,發(fā)現(xiàn)隊(duì)列中最早的 offset 是 100,所以 100 之前的字節(jié)都被覆蓋了,那么子節(jié)點(diǎn)就不能通過(guò)復(fù)制積壓緩沖區(qū)拿到完整數(shù)據(jù),所以只能通過(guò)全量復(fù)制的方式來(lái)同步。這個(gè)時(shí)候主節(jié)點(diǎn)就會(huì)發(fā)送一個(gè) +FULLRESYNC
所以為了合理設(shè)置復(fù)制積壓緩沖區(qū)的大小,有個(gè)計(jì)算公式推薦給大家:
2 * 恢復(fù)連接的時(shí)間(s) * 主節(jié)點(diǎn)寫(xiě)緩沖區(qū)的速度(MB/s)。
比如從節(jié)點(diǎn)需要 10 s 才能連上主節(jié)點(diǎn),而主節(jié)點(diǎn)在這期間每秒產(chǎn)生 5 MB 的寫(xiě)數(shù)據(jù),那么復(fù)制積壓緩沖區(qū)的大小可以設(shè)置為 100 MB。(2 * 10 s * 5 MB/s = 100 MB)
主節(jié)點(diǎn)響應(yīng)從節(jié)點(diǎn) psync 命令
在上面提到從節(jié)點(diǎn)不管是全量復(fù)制還是部分復(fù)制,最開(kāi)始都會(huì)發(fā)送一個(gè) psync 命令給主節(jié)點(diǎn),那么主節(jié)點(diǎn)會(huì)根據(jù)這個(gè)命令攜帶的參數(shù) runId 和 offset,來(lái)決定如何響應(yīng)。
原理圖如下所示:
全量復(fù)制,響應(yīng) +FULLRESYNC 。 部分復(fù)制,響應(yīng) +CONTINUE。根據(jù)從節(jié)點(diǎn)發(fā)送 runId 是否和主節(jié)點(diǎn)相同,offset 偏移量是否在復(fù)制積壓緩沖區(qū)來(lái)判斷是響應(yīng)全能量復(fù)制還是部分復(fù)制。 使用舊版全量復(fù)制,響應(yīng) -ERR。說(shuō)明主服務(wù)器的版本低于 Redis 2.8,識(shí)別不了 PSYNC 命令。
復(fù)制時(shí)如何保持連接
說(shuō)完上面主從節(jié)點(diǎn)的連接的結(jié)構(gòu),接下來(lái)的問(wèn)題是這些節(jié)點(diǎn)如何在復(fù)制時(shí)保持連接呢?
也就是說(shuō)主節(jié)點(diǎn)和從節(jié)點(diǎn)如何知道對(duì)方還存活著?其實(shí)就是通過(guò)心跳檢測(cè),這個(gè)在服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)里面經(jīng)常提到。而主節(jié)點(diǎn)和從節(jié)點(diǎn)都會(huì)向?qū)Ψ桨l(fā)送心跳檢測(cè)的命令。
主節(jié)點(diǎn)發(fā)送命令:
主節(jié)點(diǎn)會(huì)每隔 10 秒對(duì)從節(jié)點(diǎn)發(fā)送 ping 命令(也就是 10 秒一次心跳),從節(jié)點(diǎn)接收到 ping 命令后,會(huì)進(jìn)行響應(yīng),所以這個(gè) ping 命令可以用來(lái)判斷從節(jié)點(diǎn)的存活性和連接狀態(tài)。10 秒檢測(cè)一次是可以調(diào)整的,用參數(shù) repl-ping-slave-period 控制發(fā)送頻率。
從節(jié)點(diǎn)發(fā)送命令:
而從節(jié)點(diǎn)也會(huì)每隔 1 秒發(fā)送一個(gè)命令給主節(jié)點(diǎn)。這個(gè)命令還挺拗口,叫做 REPLCONF ACK {offset} ,作用就是給主節(jié)點(diǎn)上報(bào)自身當(dāng)前的復(fù)制偏移量的,這個(gè)偏移量用來(lái)檢查復(fù)制數(shù)據(jù)是否丟失,如果丟失,主節(jié)點(diǎn)將補(bǔ)發(fā)丟失的數(shù)據(jù)。
補(bǔ)發(fā)丟失數(shù)據(jù)的操作和部分復(fù)制操作的區(qū)別:
補(bǔ)發(fā)丟失數(shù)據(jù)操作在主從服務(wù)器沒(méi)有斷線的情況下執(zhí)行。
而部分復(fù)制操作是在主從服務(wù)器斷線后重連之后執(zhí)行。
從節(jié)點(diǎn)發(fā)送這個(gè)命令還可以實(shí)時(shí)檢測(cè)主從節(jié)點(diǎn)的網(wǎng)絡(luò)狀態(tài),類(lèi)似于我們?cè)诿钚写翱?ping 服務(wù)器 ip,如果 ping 不通,則表示雙方的網(wǎng)絡(luò)連接有問(wèn)題。
另外從節(jié)點(diǎn)的命令還可以用來(lái)計(jì)算主從的通信延遲,正常的延遲在 0~1 秒之間,如果超過(guò)了默認(rèn)的 60 秒,則判定從節(jié)點(diǎn)下線,斷開(kāi)復(fù)制,等重新上線后,復(fù)制繼續(xù)。而斷開(kāi)期間丟失的數(shù)據(jù),則可能需要全量復(fù)制或部分復(fù)制,取決于從節(jié)點(diǎn)的 offset 偏移量在不在復(fù)制積壓緩沖區(qū)。
Who:誰(shuí)需要關(guān)心主從架構(gòu)?
運(yùn)維人員肯定是要關(guān)注,然后就是架構(gòu)師和技術(shù)專(zhuān)家,他們對(duì)這些技術(shù)是需要有深入了解的。當(dāng)然掌握了主從復(fù)制原理,其他技術(shù)棧的復(fù)制原理也是類(lèi)似,甚至在業(yè)務(wù)場(chǎng)景下,和第三方同步數(shù)據(jù)也可以用到里面的思想。
When:什么時(shí)候用主從架構(gòu)?
其實(shí) Redis 有更好的高可用架構(gòu)方案:集群部署。
而集群部署就是將多個(gè)主從結(jié)構(gòu)進(jìn)行橫向擴(kuò)容 + 分片存儲(chǔ) + 哨兵。這里面的幾個(gè)名詞放到后面的文章再講,本篇主要針對(duì)主從架構(gòu)。
所以真實(shí)的大型電商的生產(chǎn)環(huán)境一般都是采取集群部署的方式,一些規(guī)模較小的系統(tǒng)直接單機(jī)就可以搞定,再提高點(diǎn)可用性的話,就用主從架構(gòu),實(shí)現(xiàn)讀寫(xiě)分離。其實(shí)架構(gòu)就是綜合考慮學(xué)習(xí)成本+部署成本+維護(hù)成本得到的一種最合適的方案。一味追求高可用,不結(jié)合實(shí)際的話,用處不大,這里推薦大家看下《架構(gòu)整潔之道》這本書(shū)。
Question:主從架構(gòu)會(huì)帶來(lái)哪些問(wèn)題?
為什么主從庫(kù)之間的復(fù)制不使用 AOF?
原因:
RDB 文件是二進(jìn)制文件,寫(xiě)入磁盤(pán)和網(wǎng)絡(luò)傳輸,IO 效率都比記錄和傳輸 AOF 高。 從庫(kù)端進(jìn)行恢復(fù)時(shí),用 RDB 的恢復(fù)效率要高于用 AOF。
主從架構(gòu)的高可用問(wèn)題
因?yàn)橹鲝募軜?gòu)只有一個(gè)主節(jié)點(diǎn),所以主節(jié)點(diǎn)宕機(jī)后,影響整個(gè)系統(tǒng)運(yùn)行。
如何監(jiān)控主節(jié)點(diǎn)?用 Redis 哨兵機(jī)制。
如何增加主節(jié)點(diǎn)?用 Redis 集群。
主從讀寫(xiě)分離坑不坑?
主從設(shè)置為讀寫(xiě)分離后,需要客戶(hù)端綁定主節(jié)點(diǎn)進(jìn)行讀寫(xiě),綁定從節(jié)點(diǎn)進(jìn)行讀,這個(gè)是比較麻煩的事情。
主從讀寫(xiě)架構(gòu)就不能自行判斷往哪個(gè)服務(wù)器讀,哪個(gè)服務(wù)器寫(xiě)嗎?其實(shí)需要我們自己來(lái)控制。
系統(tǒng)維護(hù)
主從模式肯定比單機(jī)復(fù)雜,維護(hù)成本也較高。
總結(jié)
本篇從宏觀和微觀上講解了主從架構(gòu)的原理:
微觀視角:涉及了主從架構(gòu)的三種拓?fù)浣Y(jié)構(gòu)來(lái)應(yīng)對(duì)不同的場(chǎng)景,然后深入講解了持續(xù)復(fù)制、全量復(fù)制、部分復(fù)制的區(qū)別。以及大家特別關(guān)心的復(fù)制積壓緩沖區(qū),客戶(hù)端緩沖區(qū)的使用場(chǎng)景,以及會(huì)遇到的坑。
宏觀視角:講解了主從架構(gòu)誰(shuí)需要來(lái)關(guān)心、什么時(shí)候用、以及主從架構(gòu)會(huì)帶來(lái)的問(wèn)題。
- END -

緩存和數(shù)據(jù)庫(kù)一致性問(wèn)題,看這篇就夠了
















