Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

這篇文章將為大家詳細(xì)講解有關(guān)redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

成都創(chuàng)新互聯(lián)是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號(hào)開發(fā),軟件開發(fā),小程序設(shè)計(jì),十載建站對(duì)成都搬家公司等多個(gè)方面,擁有豐富設(shè)計(jì)經(jīng)驗(yàn)。

高可用有兩個(gè)含義:一是數(shù)據(jù)盡量不丟失,二是服務(wù)盡可能提供服務(wù)。AOF 和 RDB 保證了數(shù)據(jù)持久化盡量不丟失,而主從復(fù)制就是增加副本,一份數(shù)據(jù)保存到多個(gè)實(shí)例上。即使有一個(gè)實(shí)例宕機(jī),其他實(shí)例依然可以提供服務(wù)。

本篇主要帶大家全方位吃透 Redis 高可用技術(shù)解決方案之一主從復(fù)制架構(gòu)。

核心知識(shí)點(diǎn)

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

開篇寄語

問題 = 機(jī)會(huì)。遇到問題的時(shí)候,內(nèi)心其實(shí)是開心的,越大的問題意味著越大的機(jī)會(huì)。

任何事情都是有代價(jià)的,有得必有失,有失必有得,所以不必計(jì)較很多東西,我們只要想清楚自己要做什么,并且想清楚自己愿意為之付出什么代價(jià),然后就放手去做吧!

1. 主從復(fù)制概述

65 哥:有了 RDB 和 AOF 再也不怕宕機(jī)丟失數(shù)據(jù)了,但是 Redis 實(shí)例宕機(jī)了怎么實(shí)現(xiàn)高可用呢?

既然一臺(tái)宕機(jī)了無法提供服務(wù),那多臺(tái)呢?是不是就可以解決了。Redis 提供了主從模式,通過主從復(fù)制,將數(shù)據(jù)冗余一份復(fù)制到其他 Redis 服務(wù)器。

前者稱為主節(jié)點(diǎn) (master),后者稱為從節(jié)點(diǎn) (slave);數(shù)據(jù)的復(fù)制是單向的,只能由主節(jié)點(diǎn)到從節(jié)點(diǎn)。

默認(rèn)情況下,每臺(tái) Redis 服務(wù)器都是主節(jié)點(diǎn);且一個(gè)主節(jié)點(diǎn)可以有多個(gè)從節(jié)點(diǎn) (或沒有從節(jié)點(diǎn)),但一個(gè)從節(jié)點(diǎn)只能有一個(gè)主節(jié)點(diǎn)。

65 哥:主從之間的數(shù)據(jù)如何保證一致性呢?

為了保證副本數(shù)據(jù)的一致性,主從架構(gòu)采用了讀寫分離的方式。

  • 讀操作:主、從庫都可以執(zhí)行;

  • 寫操作:主庫先執(zhí)行,之后將寫操作同步到從庫;

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

65 哥:為何要采用讀寫分離的方式?

我們可以假設(shè)主從庫都可以執(zhí)行寫指令,假如對(duì)同一份數(shù)據(jù)分別修改了多次,每次修改發(fā)送到不同的主從實(shí)例上,就導(dǎo)致是實(shí)例的副本數(shù)據(jù)不一致了。

如果為了保證數(shù)據(jù)一致,Redis 需要加鎖,協(xié)調(diào)多個(gè)實(shí)例的修改,Redis 自然不會(huì)這么干!

65 哥:主從復(fù)制還有其他作用么?

  1. 故障恢復(fù):當(dāng)主節(jié)點(diǎn)宕機(jī),其他節(jié)點(diǎn)依然可以提供服務(wù);

  2. 負(fù)載均衡:Master 節(jié)點(diǎn)提供寫服務(wù),Slave 節(jié)點(diǎn)提供讀服務(wù),分擔(dān)壓力;

  3. 高可用基石:是哨兵和 cluster 實(shí)施的基礎(chǔ),是高可用的基石。

2. 搭建主從復(fù)制

主從復(fù)制的開啟,完全是在從節(jié)點(diǎn)發(fā)起的,不需要我們?cè)谥鞴?jié)點(diǎn)做任何事情。

65 哥:怎么搭建主從復(fù)制架構(gòu)呀?

可以通過 replicaof(Redis 5.0 之前使用 slaveof)命令形成主庫和從庫的關(guān)系。

在從節(jié)點(diǎn)開啟主從復(fù)制,有 3 種方式:

  • 配置文件

    在從服務(wù)器的配置文件中加入 replicaof <masterip> <masterport>

  • 啟動(dòng)命令

    redis-server 啟動(dòng)命令后面加入 --replicaof <masterip> <masterport>

  • 客戶端命令

    啟動(dòng)多個(gè) Redis 實(shí)例后,直接通過客戶端執(zhí)行命令:replicaof <masterip> <masterport>,則該 Redis 實(shí)例成為從節(jié)點(diǎn)。

比如假設(shè)現(xiàn)在有實(shí)例 1(172.16.88.1)、實(shí)例 2(172.16.88.2)和實(shí)例 3 (172.16.88.3),在實(shí)例 2 和實(shí)例 3 上分別執(zhí)行以下命令,實(shí)例 2 和 實(shí)例 3 就成為了實(shí)例 1 的從庫,實(shí)例 1 成為 Master。

replicaof 172.16.88.1 6379復(fù)制代碼

3. 主從復(fù)制原理

主從庫模式一旦采用了讀寫分離,所有數(shù)據(jù)的寫操作只會(huì)在主庫上進(jìn)行,不用協(xié)調(diào)三個(gè)實(shí)例。

主庫有了最新的數(shù)據(jù)后,會(huì)同步給從庫,這樣,主從庫的數(shù)據(jù)就是一致的。

65 哥:主從庫同步是如何完成的呢?主庫數(shù)據(jù)是一次性傳給從庫,還是分批同步?正常運(yùn)行中又怎么同步呢?要是主從庫間的網(wǎng)絡(luò)斷連了,重新連接后數(shù)據(jù)還能保持一致嗎?

65 哥你問題咋這么多,同步分為三種情況:

  1. 第一次主從庫全量復(fù)制;

  2. 主從正常運(yùn)行期間的同步;

  3. 主從庫間網(wǎng)絡(luò)斷開重連同步。

主從庫第一次全量復(fù)制

65 哥:我好暈啊,先從主從庫間第一次同步說起吧。

主從庫第一次復(fù)制過程大體可以分為 3 個(gè)階段:連接建立階段(即準(zhǔn)備階段)、主庫同步數(shù)據(jù)到從庫階段、發(fā)送同步期間新寫命令到從庫階段;

直接上圖,從整體上有一個(gè)全局觀的感知,后面具體介紹。

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

建立連接

該階段的主要作用是在主從節(jié)點(diǎn)之間建立連接,為數(shù)據(jù)全量同步做好準(zhǔn)備。從庫會(huì)和主庫建立連接,從庫執(zhí)行 replicaof 并發(fā)送 psync 命令并告訴主庫即將進(jìn)行同步,主庫確認(rèn)回復(fù)后,主從庫間就開始同步了。

65 哥:從庫怎么知道主庫信息并建立連接的呢?

在從節(jié)點(diǎn)的配置文件中的 replicaof 配置項(xiàng)中配置了主節(jié)點(diǎn)的 IP 和 port 后,從節(jié)點(diǎn)就知道自己要和那個(gè)主節(jié)點(diǎn)進(jìn)行連接了。

從節(jié)點(diǎn)內(nèi)部維護(hù)了兩個(gè)字段,masterhost 和 masterport,用于存儲(chǔ)主節(jié)點(diǎn)的 IP 和 port 信息。

從庫執(zhí)行 replicaof 并發(fā)送 psync 命令,表示要執(zhí)行數(shù)據(jù)同步,主庫收到命令后根據(jù)參數(shù)啟動(dòng)復(fù)制。命令包含了主庫的 runID復(fù)制進(jìn)度 offset兩個(gè)參數(shù)。

  • runID:每個(gè) Redis 實(shí)例啟動(dòng)都會(huì)自動(dòng)生成一個(gè) 唯一標(biāo)識(shí) ID,第一次主從復(fù)制,還不知道主庫 runID,參數(shù)設(shè)置為 「?」。

  • offset:第一次復(fù)制設(shè)置為 -1,表示第一次復(fù)制,記錄復(fù)制進(jìn)度偏移量。

主庫收到 psync 命令后,會(huì)用 FULLRESYNC 響應(yīng)命令帶上兩個(gè)參數(shù):主庫 runID 和主庫目前的復(fù)制進(jìn)度 offset,返回給從庫。從庫收到響應(yīng)后,會(huì)記錄下這兩個(gè)參數(shù)。

FULLRESYNC 響應(yīng)表示第一次復(fù)制采用的全量復(fù)制,也就是說,主庫會(huì)把當(dāng)前所有的數(shù)據(jù)都復(fù)制給從庫。

主庫同步數(shù)據(jù)給從庫

第二階段

master 執(zhí)行 bgsave命令生成 RDB 文件,并將文件發(fā)送給從庫,同時(shí)主庫為每一個(gè) slave 開辟一塊 replication buffer 緩沖區(qū)記錄從生成 RDB 文件開始收到的所有寫命令。

從庫收到 RDB 文件后保存到磁盤,并清空當(dāng)前數(shù)據(jù)庫的數(shù)據(jù),再加載 RDB 文件數(shù)據(jù)到內(nèi)存中。

發(fā)送新寫命令到從庫

第三階段

從節(jié)點(diǎn)加載 RDB 完成后,主節(jié)點(diǎn)將 replication buffer 緩沖區(qū)的數(shù)據(jù)發(fā)送到從節(jié)點(diǎn),Slave 接收并執(zhí)行,從節(jié)點(diǎn)同步至主節(jié)點(diǎn)相同的狀態(tài)。

65 哥:主庫將數(shù)據(jù)同步到從庫過程中,可以正常接受請(qǐng)求么?

主庫不會(huì)被阻塞,Redis 作為唯快不破的男人,怎么會(huì)動(dòng)不動(dòng)就阻塞呢。

在生成 RDB 文件之后的寫操作并沒有記錄到剛剛的 RDB 文件中,為了保證主從庫數(shù)據(jù)的一致性,所以主庫會(huì)在內(nèi)存中使用一個(gè)叫 replication buffer 記錄 RDB 文件生成后的所有寫操作。

65 哥:為啥從庫收到 RDB 文件后要清空當(dāng)前數(shù)據(jù)庫?

因?yàn)閺膸煸谕ㄟ^ replcaof命令開始和主庫同步前可能保存了其他數(shù)據(jù),防止主從數(shù)據(jù)之間的影響。

replication buffer 到底是什么玩意?

一個(gè)在 master 端上創(chuàng)建的緩沖區(qū),存放的數(shù)據(jù)是下面三個(gè)時(shí)間內(nèi)所有的 master 數(shù)據(jù)寫操作。

1)master 執(zhí)行 bgsave 產(chǎn)生 RDB 的期間的寫操作;

2)master 發(fā)送 rdb 到 slave 網(wǎng)絡(luò)傳輸期間的寫操作;

3)slave load rdb 文件把數(shù)據(jù)恢復(fù)到內(nèi)存的期間的寫操作。

Redis 和客戶端通信也好,和從庫通信也好,Redis 都分配一個(gè)內(nèi)存 buffer 進(jìn)行數(shù)據(jù)交互,客戶端就是一個(gè) client,從庫也是一個(gè) client,我們每個(gè) client 連上 Redis 后,Redis 都會(huì)分配一個(gè)專有 client buffer,所有數(shù)據(jù)交互都是通過這個(gè) buffer 進(jìn)行的。

Master 先把數(shù)據(jù)寫到這個(gè) buffer 中,然后再通過網(wǎng)絡(luò)發(fā)送出去,這樣就完成了數(shù)據(jù)交互。

不管是主從在增量同步還是全量同步時(shí),master 會(huì)為其分配一個(gè) buffer ,只不過這個(gè) buffer 專門用來傳播寫命令到從庫,保證主從數(shù)據(jù)一致,我們通常把它叫做 replication buffer。

replication buffer 太小會(huì)引發(fā)的問題

replication buffer 由 client-output-buffer-limit slave 設(shè)置,當(dāng)這個(gè)值太小會(huì)導(dǎo)致主從復(fù)制連接斷開。

1)當(dāng) master-slave 復(fù)制連接斷開,master 會(huì)釋放連接相關(guān)的數(shù)據(jù)。replication buffer 中的數(shù)據(jù)也就丟失了,此時(shí)主從之間重新開始復(fù)制過程。

2)還有個(gè)更嚴(yán)重的問題,主從復(fù)制連接斷開,導(dǎo)致主從上出現(xiàn)重新執(zhí)行 bgsave 和 rdb 重傳操作無限循環(huán)。

當(dāng)主節(jié)點(diǎn)數(shù)據(jù)量較大,或者主從節(jié)點(diǎn)之間網(wǎng)絡(luò)延遲較大時(shí),可能導(dǎo)致該緩沖區(qū)的大小超過了限制,此時(shí)主節(jié)點(diǎn)會(huì)斷開與從節(jié)點(diǎn)之間的連接;

這種情況可能引起全量復(fù)制 -> replication buffer 溢出導(dǎo)致連接中斷 -> 重連 -> 全量復(fù)制 -> replication buffer 緩沖區(qū)溢出導(dǎo)致連接中斷……的循環(huán)。

具體詳情:[top redis headaches for devops – replication buffer] 因而推薦把 replication buffer 的 hard/soft limit 設(shè)置成 512M。

config set client-output-buffer-limit "slave 536870912 536870912 0"復(fù)制代碼

65 哥:主從庫復(fù)制為何不使用 AOF 呢?相比 RDB 來說,丟失的數(shù)據(jù)更少。

這個(gè)問題問的好,原因如下:

  • RDB 文件是二進(jìn)制文件,網(wǎng)絡(luò)傳輸 RDB 和寫入磁盤的 IO 效率都要比 AOF 高。

  • 從庫進(jìn)行數(shù)據(jù)恢復(fù)的時(shí)候,RDB 的恢復(fù)效率也要高于 AOF。

增量復(fù)制

65 哥:主從庫間的網(wǎng)絡(luò)斷了咋辦?斷開后要重新全量復(fù)制么?

在 Redis 2.8 之前,如果主從庫在命令傳播時(shí)出現(xiàn)了網(wǎng)絡(luò)閃斷,那么,從庫就會(huì)和主庫重新進(jìn)行一次全量復(fù)制,開銷非常大。

從 Redis 2.8 開始,網(wǎng)絡(luò)斷了之后,主從庫會(huì)采用增量復(fù)制的方式繼續(xù)同步。

增量復(fù)制:用于網(wǎng)絡(luò)中斷等情況后的復(fù)制,只將中斷期間主節(jié)點(diǎn)執(zhí)行的寫命令發(fā)送給從節(jié)點(diǎn),與全量復(fù)制相比更加高效。

repl_backlog_buffer

斷開重連增量復(fù)制的實(shí)現(xiàn)奧秘就是 repl_backlog_buffer 緩沖區(qū),不管在什么時(shí)候 master 都會(huì)將寫指令操作記錄在 repl_backlog_buffer 中,因?yàn)閮?nèi)存有限, repl_backlog_buffer 是一個(gè)定長(zhǎng)的環(huán)形數(shù)組,如果數(shù)組內(nèi)容滿了,就會(huì)從頭開始覆蓋前面的內(nèi)容。

master 使用 master_repl_offset記錄自己寫到的位置偏移量,slave 則使用 slave_repl_offset記錄已經(jīng)讀取到的偏移量。

master 收到寫操作,偏移量則會(huì)增加。從庫持續(xù)執(zhí)行同步的寫指令后,在 repl_backlog_buffer 的已復(fù)制的偏移量 slave_repl_offset 也在不斷增加。

正常情況下,這兩個(gè)偏移量基本相等。在網(wǎng)絡(luò)斷連階段,主庫可能會(huì)收到新的寫操作命令,所以 master_repl_offset會(huì)大于 slave_repl_offset。

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

當(dāng)主從斷開重連后,slave 會(huì)先發(fā)送 psync 命令給 master,同時(shí)將自己的 runID,slave_repl_offset發(fā)送給 master。

master 只需要把 master_repl_offsetslave_repl_offset之間的命令同步給從庫即可。

增量復(fù)制執(zhí)行流程如下圖:

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

65 哥:repl_backlog_buffer 太小的話從庫還沒讀取到就被 Master 的新寫操作覆蓋了咋辦?

我們要想辦法避免這個(gè)情況,一旦被覆蓋就會(huì)執(zhí)行全量復(fù)制。我們可以調(diào)整 repl_backlog_size 這個(gè)參數(shù)用于控制緩沖區(qū)大小。計(jì)算公式:

repl_backlog_buffer = second * write_size_per_second復(fù)制代碼
  • second:從服務(wù)器斷開重連主服務(wù)器所需的平均時(shí)間;

  • write_size_per_second:master 平均每秒產(chǎn)生的命令數(shù)據(jù)量大?。▽懨詈蛿?shù)據(jù)大小總和);

例如,如果主服務(wù)器平均每秒產(chǎn)生 1 MB 的寫數(shù)據(jù),而從服務(wù)器斷線之后平均要 5 秒才能重新連接上主服務(wù)器,那么復(fù)制積壓緩沖區(qū)的大小就不能低于 5 MB。

為了安全起見,可以將復(fù)制積壓緩沖區(qū)的大小設(shè)為2 * second * write_size_per_second,這樣可以保證絕大部分?jǐn)嗑€情況都能用部分重同步來處理。

基于長(zhǎng)連接的命令傳播

65 哥:完成全量同步后,正常運(yùn)行過程如何同步呢?

當(dāng)主從庫完成了全量復(fù)制,它們之間就會(huì)一直維護(hù)一個(gè)網(wǎng)絡(luò)連接,主庫會(huì)通過這個(gè)連接將后續(xù)陸續(xù)收到的命令操作再同步給從庫,這個(gè)過程也稱為基于長(zhǎng)連接的命令傳播,使用長(zhǎng)連接的目的就是避免頻繁建立連接導(dǎo)致的開銷。

在命令傳播階段,除了發(fā)送寫命令,主從節(jié)點(diǎn)還維持著心跳機(jī)制:PING 和 REPLCONF ACK。

主->從:PING

每隔指定的時(shí)間,主節(jié)點(diǎn)會(huì)向從節(jié)點(diǎn)發(fā)送 PING 命令,這個(gè) PING 命令的作用,主要是為了讓從節(jié)點(diǎn)進(jìn)行超時(shí)判斷。

從->主:REPLCONF ACK

在命令傳播階段,從服務(wù)器默認(rèn)會(huì)以每秒一次的頻率,向主服務(wù)器發(fā)送命令:

REPLCONF ACK <replication_offset>復(fù)制代碼

其中 replication_offset 是從服務(wù)器當(dāng)前的復(fù)制偏移量。發(fā)送 REPLCONF ACK 命令對(duì)于主從服務(wù)器有三個(gè)作用:

  • 檢測(cè)主從服務(wù)器的網(wǎng)絡(luò)連接狀態(tài)。

  • 輔助實(shí)現(xiàn) min-slaves 選項(xiàng)。

  • 檢測(cè)命令丟失, 從節(jié)點(diǎn)發(fā)送了自身的 slave_replication_offset,主節(jié)點(diǎn)會(huì)用自己的 master_replication_offset 對(duì)比,如果從節(jié)點(diǎn)數(shù)據(jù)缺失,主節(jié)點(diǎn)會(huì)從 repl_backlog_buffer緩沖區(qū)中找到并推送缺失的數(shù)據(jù)。注意,offset 和 repl_backlog_buffer 緩沖區(qū),不僅可以用于部分復(fù)制,也可以用于處理命令丟失等情形;區(qū)別在于前者是在斷線重連后進(jìn)行的,而后者是在主從節(jié)點(diǎn)沒有斷線的情況下進(jìn)行的。

如何確定執(zhí)行全量同步還是部分同步?

在 Redis 2.8 及以后,從節(jié)點(diǎn)可以發(fā)送 psync 命令請(qǐng)求同步數(shù)據(jù),此時(shí)根據(jù)主從節(jié)點(diǎn)當(dāng)前狀態(tài)的不同,同步方式可能是全量復(fù)制部分復(fù)制。本文以 Redis 2.8 及之后的版本為例。

關(guān)鍵就是 psync的執(zhí)行:

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

  • 從節(jié)點(diǎn)根據(jù)當(dāng)前狀態(tài),發(fā)送 psync命令給 master:

    • 如果從節(jié)點(diǎn)從未執(zhí)行過 replicaof ,則從節(jié)點(diǎn)發(fā)送 psync ? -1,向主節(jié)點(diǎn)發(fā)送全量復(fù)制請(qǐng)求;

    • 如果從節(jié)點(diǎn)之前執(zhí)行過 replicaof 則發(fā)送 psync <runID> <offset>, runID 是上次復(fù)制保存的主節(jié)點(diǎn) runID,offset 是上次復(fù)制截至?xí)r從節(jié)點(diǎn)保存的復(fù)制偏移量。

  • 主節(jié)點(diǎn)根據(jù)接受到的psync命令和當(dāng)前服務(wù)器狀態(tài),決定執(zhí)行全量復(fù)制還是部分復(fù)制:

    • runID 與從節(jié)點(diǎn)發(fā)送的 runID 相同,且從節(jié)點(diǎn)發(fā)送的 slave_repl_offset 之后的數(shù)據(jù)在 repl_backlog_buffer 緩沖區(qū)中都存在,則回復(fù) CONTINUE,表示將進(jìn)行部分復(fù)制,從節(jié)點(diǎn)等待主節(jié)點(diǎn)發(fā)送其缺少的數(shù)據(jù)即可;

    • runID 與從節(jié)點(diǎn)發(fā)送的 runID 不同,或者從節(jié)點(diǎn)發(fā)送的 slave_repl_offset 之后的數(shù)據(jù)已不在主節(jié)點(diǎn)的 repl_backlog_buffer 緩沖區(qū)中 (在隊(duì)列中被擠出了),則回復(fù)從節(jié)點(diǎn) FULLRESYNC <runid> <offset>,表示要進(jìn)行全量復(fù)制,其中 runID 表示主節(jié)點(diǎn)當(dāng)前的 runID,offset 表示主節(jié)點(diǎn)當(dāng)前的 offset,從節(jié)點(diǎn)保存這兩個(gè)值,以備使用。

一個(gè)從庫如果和主庫斷連時(shí)間過長(zhǎng),造成它在主庫 repl_backlog_buffer 的 slave_repl_offset 位置上的數(shù)據(jù)已經(jīng)被覆蓋掉了,此時(shí)從庫和主庫間將進(jìn)行全量復(fù)制。

總結(jié)下

每個(gè)從庫會(huì)記錄自己的 slave_repl_offset,每個(gè)從庫的復(fù)制進(jìn)度也不一定相同。

在和主庫重連進(jìn)行恢復(fù)時(shí),從庫會(huì)通過 psync 命令把自己記錄的 slave_repl_offset 發(fā)給主庫,主庫會(huì)根據(jù)從庫各自的復(fù)制進(jìn)度,來決定這個(gè)從庫可以進(jìn)行增量復(fù)制,還是全量復(fù)制。

replication buffer 和 repl_backlog

  • replication buffer 對(duì)應(yīng)于每個(gè) slave,通過 config set client-output-buffer-limit slave 設(shè)置。

  • repl_backlog_buffer 是一個(gè)環(huán)形緩沖區(qū),整個(gè) master 進(jìn)程中只會(huì)存在一個(gè),所有的 slave 公用。repl_backlog 的大小通過 repl-backlog-size 參數(shù)設(shè)置,默認(rèn)大小是 1M,其大小可以根據(jù)每秒產(chǎn)生的命令、(master 執(zhí)行 rdb bgsave) +( master 發(fā)送 rdb 到 slave) + (slave load rdb 文件)時(shí)間之和來估算積壓緩沖區(qū)的大小,repl-backlog-size 值不小于這兩者的乘積。

總的來說,replication buffer 是主從庫在進(jìn)行全量復(fù)制時(shí),主庫上用于和從庫連接的客戶端的 buffer,而 repl_backlog_buffer 是為了支持從庫增量復(fù)制,主庫上用于持續(xù)保存寫操作的一塊專用 buffer。

repl_backlog_buffer 是一塊專用 buffer,在 Redis 服務(wù)器啟動(dòng)后,開始一直接收寫操作命令,這是所有從庫共享的。主庫和從庫會(huì)各自記錄自己的復(fù)制進(jìn)度,所以,不同的從庫在進(jìn)行恢復(fù)時(shí),會(huì)把自己的復(fù)制進(jìn)度(slave_repl_offset)發(fā)給主庫,主庫就可以和它獨(dú)立同步。

如圖所示:

Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析

4. 主從應(yīng)用問題

4.1 讀寫分離的問題

數(shù)據(jù)過期問題

65 哥:主從復(fù)制的場(chǎng)景下,從節(jié)點(diǎn)會(huì)刪除過期數(shù)據(jù)么?

這個(gè)問題問得好,為了主從節(jié)點(diǎn)的數(shù)據(jù)一致性,從節(jié)點(diǎn)不會(huì)主動(dòng)刪除數(shù)據(jù)。我們知道 Redis 有兩種刪除策略:

  • 惰性刪除:當(dāng)客戶端查詢對(duì)應(yīng)的數(shù)據(jù)時(shí),Redis 判斷該數(shù)據(jù)是否過期,過期則刪除。

  • 定期刪除:Redis 通過定時(shí)任務(wù)刪除過期數(shù)據(jù)。

65 哥:那客戶端通過從節(jié)點(diǎn)讀取數(shù)據(jù)會(huì)不會(huì)讀取到過期數(shù)據(jù)?

Redis 3.2 開始,通過從節(jié)點(diǎn)讀取數(shù)據(jù)時(shí),先判斷數(shù)據(jù)是否已過期。如果過期則不返回客戶端,并且刪除數(shù)據(jù)。

4.2 單機(jī)內(nèi)存大小限制

如果 Redis 單機(jī)內(nèi)存達(dá)到 10GB,一個(gè)從節(jié)點(diǎn)的同步時(shí)間在幾分鐘的級(jí)別;如果從節(jié)點(diǎn)較多,恢復(fù)的速度會(huì)更慢。如果系統(tǒng)的讀負(fù)載很高,而這段時(shí)間從節(jié)點(diǎn)無法提供服務(wù),會(huì)對(duì)系統(tǒng)造成很大的壓力。

如果數(shù)據(jù)量過大,全量復(fù)制階段主節(jié)點(diǎn) fork + 保存 RDB 文件耗時(shí)過大,從節(jié)點(diǎn)長(zhǎng)時(shí)間接收不到數(shù)據(jù)觸發(fā)超時(shí),主從節(jié)點(diǎn)的數(shù)據(jù)同步同樣可能陷入全量復(fù)制->超時(shí)導(dǎo)致復(fù)制中斷->重連->全量復(fù)制->超時(shí)導(dǎo)致復(fù)制中斷……的循環(huán)。

此外,主節(jié)點(diǎn)單機(jī)內(nèi)存除了絕對(duì)量不能太大,其占用主機(jī)內(nèi)存的比例也不應(yīng)過大:最好只使用 50% - 65% 的內(nèi)存,留下 30%-45% 的內(nèi)存用于執(zhí)行 bgsave 命令和創(chuàng)建復(fù)制緩沖區(qū)等。

關(guān)于“Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

網(wǎng)頁名稱:Redis中主從架構(gòu)數(shù)據(jù)一致性同步原理的示例分析
鏈接URL:http://www.muchs.cn/article42/gcehhc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)小程序開發(fā)、網(wǎng)站制作、云服務(wù)器關(guān)鍵詞優(yōu)化、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作