讀配置、講原理、看面試真題,我只能幫你到這了。。。

當(dāng)我在寫(xiě)一上來(lái)就主從、集群、哨兵,這誰(shuí)受得了的時(shí)候,好多小伙伴就迫不及待的留言想看這些模式了,今天我們就從配置文件、設(shè)計(jì)原理、面試真題三個(gè)方面來(lái)聊一聊 Redis 的主從復(fù)制。

在 Redis 復(fù)制的基礎(chǔ)上,使用和配置主從復(fù)制非常簡(jiǎn)單,能使得從 Redis 服務(wù)器(下文稱 replica)能精確的復(fù)制主 Redis 服務(wù)器(下文稱 master)的內(nèi)容。每次當(dāng) replica 和 master 之間的連接斷開(kāi)時(shí), replica 會(huì)自動(dòng)重連到 master 上,并且無(wú)論這期間 master 發(fā)生了什么, replica 都將嘗試讓自身成為 master 的精確副本。

主從復(fù)制,從 5.0.0 版本開(kāi)始,Redis 正式將 SLAVEOF 命令改名成了 REPLICAOF 命令并逐漸廢棄原來(lái)的 SLAVEOF 命令

Redis使用默認(rèn)的異步復(fù)制,其特點(diǎn)是低延遲高性能,是絕大多數(shù) Redis 用例的自然復(fù)制模式。但是,replica 會(huì)異步地確認(rèn)它從主 master 周期接收到的數(shù)據(jù)量。

主從拓?fù)浼軜?gòu)

1一主多從.jpg

master 用來(lái)寫(xiě)操作,replicas 用來(lái)讀取數(shù)據(jù),適用于讀多寫(xiě)少的場(chǎng)景。而對(duì)于寫(xiě)并發(fā)量較高的場(chǎng)景,多個(gè)從節(jié)點(diǎn)會(huì)導(dǎo)致主節(jié)點(diǎn)寫(xiě)命令的多次發(fā)送從而過(guò)度消耗網(wǎng)絡(luò)帶寬,同時(shí)也加重了 master 的負(fù)載影響服務(wù)穩(wěn)定性。

2樹(shù)狀主從.jpg

replica 可以接受其它 replica 的連接。除了多個(gè) replica 可以連接到同一個(gè) master 之外, replica 之間也可以像層疊狀的結(jié)構(gòu)(cascading-like structure)連接到其他 replica 。自 Redis 4.0 起,所有的 sub-replica 將會(huì)從 master 收到完全一樣的復(fù)制流。

當(dāng) master 需要多個(gè) replica 時(shí),為了避免對(duì) master 的性能干擾,可以采用樹(shù)狀主從結(jié)構(gòu)降低主節(jié)點(diǎn)的壓力。

為了讓大家對(duì)概念有更清晰的認(rèn)識(shí),我們先來(lái)看一下配置文件中主從復(fù)制的參數(shù)介紹:

REPLICATION

replicaof <masterip> <masterport>

通過(guò)設(shè)置 master 的 ip 和 port ,可以使當(dāng)前的 Redis 實(shí)例成為另一臺(tái) Redis 實(shí)例的副本。在Redis啟動(dòng)時(shí),它會(huì)自動(dòng)從 master 進(jìn)行數(shù)據(jù)同步。

  • Redis 復(fù)制是異步的,可以通過(guò)修改 master 的配置,在 master 沒(méi)有與給定數(shù)量的 replica 連接時(shí),主機(jī)停止接收寫(xiě)入;
  • 如果復(fù)制鏈路丟失的時(shí)間相對(duì)較短,Redis replica 可以與 master 執(zhí)行部分重新同步,可以使用合理的 backlog 值來(lái)進(jìn)行配置(見(jiàn)下文);
  • 復(fù)制是自動(dòng)的,不需要用戶干預(yù)。在網(wǎng)絡(luò)分區(qū)后,replica 會(huì)自動(dòng)嘗試重新連接到 master 并與 master 重新同步;

masterauth <master-password>

當(dāng) master 設(shè)置了密碼保護(hù)時(shí),replica 服務(wù)連接 master 的密碼

replica-serve-stale-data yes

當(dāng) replica 與 master 失去連接或者主從復(fù)制在進(jìn)行時(shí),replica 可以有兩種不同的設(shè)置:

  • replica-serve-stale-data:yes(默認(rèn)值),則 replica 仍將響應(yīng)客戶端請(qǐng)求,可能會(huì)有過(guò)期數(shù)據(jù),或者如果這是第一次同步,則數(shù)據(jù)集可能為空。
  • replica-serve-stale-data:no , replica 將對(duì)所有請(qǐng)求命令(但不包含 INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST, HOST: and LATENCY)返回 SYNC with master in progress 的錯(cuò)誤。

replica-read-only

可以將 replica 配置為是否只讀,yes 代表為只讀狀態(tài),將會(huì)拒絕所有寫(xiě)入命令;no 表示可以寫(xiě)入。 從 Redis 2.6 之后, replica 支持只讀模式且默認(rèn)開(kāi)啟??梢栽谶\(yùn)行時(shí)使用 CONFIG SET 來(lái)隨時(shí)開(kāi)啟或者關(guān)閉。

對(duì) replica 進(jìn)行寫(xiě)入可能有助于存儲(chǔ)一些臨時(shí)數(shù)據(jù)(因?yàn)閷?xiě)入 replica 的數(shù)據(jù)在與 master 重新同步后很容易被刪除),計(jì)算慢速集或排序集操作并將其存儲(chǔ)到本地密鑰是多次觀察到的可寫(xiě)副本的一個(gè)用例。但如果客戶端由于配置錯(cuò)誤而向其寫(xiě)入數(shù)據(jù),則也可能會(huì)導(dǎo)致問(wèn)題。

級(jí)聯(lián)結(jié)構(gòu)中即使 replica B 節(jié)點(diǎn)是可寫(xiě)的,Sub-replica C 也不會(huì)看到 B 的寫(xiě)入,而是將擁有和 master A 相同的數(shù)據(jù)集。

設(shè)置為 yes 并不表示客戶端用集群方式以 replica 為入口連入集群時(shí),不可以進(jìn)行 set 操作,且 set 操作的數(shù)據(jù)不會(huì)被放在 replica 的槽上,會(huì)被放到某 master 的槽上。

注意:只讀 replica 設(shè)計(jì)的目的不是為了暴露于互聯(lián)網(wǎng)上不受信任的客戶端,它只是一個(gè)防止實(shí)例誤用的保護(hù)層。默認(rèn)情況下,只讀副本仍會(huì)導(dǎo)出所有管理命令,如CONFIG、DEBUG 等。在一定程度上,可以使用rename-command來(lái)隱藏所有管理/危險(xiǎn)命令,從而提高只讀副本的安全性。

repl-diskless-sync

復(fù)制同步策略:磁盤(pán)(disk)或套接字(socket),默認(rèn)為 no 使用 disk 。

新的 replicas 和重新連接的 replicas 如果因?yàn)榻邮盏讲町惗鵁o(wú)法繼續(xù)復(fù)制過(guò)程,則需要執(zhí)行“完全同步”。RDB 文件從 master 傳送到 replicas,傳輸可以通過(guò)兩種不同的方式進(jìn)行:

  1. Disk-backed:Redis master 節(jié)點(diǎn)創(chuàng)建一個(gè)新的進(jìn)程并將 RDB 文件寫(xiě)入磁盤(pán),然后文件通過(guò)父進(jìn)程增量傳輸給 replicas 節(jié)點(diǎn);
  2. Diskless:Redis master 節(jié)點(diǎn)創(chuàng)建一個(gè)新的進(jìn)程并直接將 RDB 文件寫(xiě)入到 replicas 的 sockets 中,不寫(xiě)到磁盤(pán)。
  • 當(dāng)進(jìn)行 disk-backed 復(fù)制時(shí), RDB 文件生成完畢,多個(gè) replicas 通過(guò)排隊(duì)來(lái)同步 RDB 文件。
  • 當(dāng)進(jìn)行 diskless 復(fù)制時(shí),master 節(jié)點(diǎn)會(huì)等待一段時(shí)間(下邊的repl-diskless-sync-delay 配置)再傳輸以期望會(huì)有多個(gè) replicas 連接進(jìn)來(lái),這樣 master 節(jié)點(diǎn)就可以同時(shí)同步到多個(gè) replicas 節(jié)點(diǎn)。如果超出了等待時(shí)間,則需要排隊(duì),等當(dāng)前的 replica 處理完成之后在進(jìn)行下一個(gè) replica 的處理。

硬盤(pán)性能差,網(wǎng)絡(luò)性能好的情況下 diskless 效果更佳

警告:無(wú)盤(pán)復(fù)制目前處于試驗(yàn)階段

repl-diskless-sync-delay

當(dāng)啟用 diskless 復(fù)制后,可以通過(guò)此選項(xiàng)設(shè)置 master 節(jié)點(diǎn)創(chuàng)建子進(jìn)程前等待的時(shí)間,即延遲啟動(dòng)數(shù)據(jù)傳輸,目的可以在第一個(gè) replica 就緒后,等待更多的 replica 就緒。單位為秒,默認(rèn)為5秒。

repl-ping-replica-period

Replica 發(fā)送 PING 到 master 的間隔,默認(rèn)值為 10 秒。

repl-timeout

默認(rèn)值60秒,此選項(xiàng)用于設(shè)置以下情形的 timeout 判斷:

  • 從 replica 節(jié)點(diǎn)的角度來(lái)看的 SYNC 過(guò)程中的 I/O 傳輸 —— 沒(méi)有收到 master SYNC 傳輸?shù)?rdb snapshot 數(shù)據(jù);
  • 從 replica 節(jié)點(diǎn)的角度來(lái)看的 master 的 timeout(如 data,pings)—— replica 沒(méi)有收到master發(fā)送的數(shù)據(jù)包或者ping;
  • 從 master 節(jié)點(diǎn)角度來(lái)看的 replica 的 timeout(如 REPLCONF ACK pings)—— master 沒(méi)有收到 REPLCONF ACK 的確認(rèn)信息;
    需要注意的是,此選項(xiàng)必須大于 repl-ping-replica-period,否則在 master 和 replica 之間存在低業(yè)務(wù)量的情況下會(huì)經(jīng)常發(fā)生 timeout。

repl-disable-tcp-nodelay

master 和 replicas 節(jié)點(diǎn)的連接是否關(guān)掉 TCP_NODELAY 選項(xiàng)。

  • 如果選擇“yes”,Redis 將使用更少的 TCP 數(shù)據(jù)包和更少的帶寬向 replicas 發(fā)送數(shù)據(jù)。但這會(huì)增加數(shù)據(jù)在 replicas 端顯示的延遲,對(duì)于使用默認(rèn)配置的 Linux 內(nèi)核,延遲可達(dá)40毫秒。
  • 如果選擇“no”,則數(shù)據(jù)出現(xiàn)在 replicas 端的延遲將減少,但復(fù)制將使用更多帶寬。

這個(gè)實(shí)際影響的是 TCP 層的選項(xiàng),里面會(huì)用 setsockopt 設(shè)置,默認(rèn)為 no,表示 TCP 層會(huì)禁用 Nagle 算法,盡快將數(shù)據(jù)發(fā)出, 設(shè)置為 yes 表示 TCP 層啟用 Nagle 算法,數(shù)據(jù)累積到一定程度,或者經(jīng)過(guò)一定時(shí)間 TCP 層才會(huì)將其發(fā)出。

默認(rèn)情況下,我們會(huì)針對(duì)低延遲進(jìn)行優(yōu)化,但在流量非常高的情況下,或者當(dāng) master 和 replicas 距離多個(gè) hops 時(shí),將此選項(xiàng)改為“yes”可能會(huì)更好。

repl-backlog-size

設(shè)置復(fù)制的 backlog 緩沖大小,默認(rèn) 1mb。backlog 是一個(gè)緩沖區(qū),當(dāng) replica 斷開(kāi)一段時(shí)間連接時(shí),它會(huì)累積 replica 數(shù)據(jù),所以當(dāng) replica 想要再次重新連接時(shí),一般不需要全量同步,只需要進(jìn)行部分同步即可,只傳遞 replica 在斷開(kāi)連接時(shí)丟失的部分?jǐn)?shù)據(jù)。

更大的 backlog 緩沖大小,意味著 replicas 斷開(kāi)重連后,依然可以進(jìn)行續(xù)傳的時(shí)間越長(zhǎng)(支持?jǐn)嚅_(kāi)更長(zhǎng)時(shí)間)。

backlog 緩沖只有在至少一個(gè) replica 節(jié)點(diǎn)連過(guò)來(lái)的時(shí)候 master 節(jié)點(diǎn)才需要?jiǎng)?chuàng)建。

repl-backlog-ttl

當(dāng) replicas 節(jié)點(diǎn)斷開(kāi)連接后,master 節(jié)點(diǎn)會(huì)在一段時(shí)間后釋放 backlog 緩沖區(qū)。 這個(gè)選項(xiàng)設(shè)置的是當(dāng)最后一個(gè) replica 斷開(kāi)鏈接后,master 需要等待多少秒再釋放緩沖區(qū)。默認(rèn)3600 秒,0表示永遠(yuǎn)不釋放。

replicas 節(jié)點(diǎn)永遠(yuǎn)都不會(huì)釋放這個(gè)緩沖區(qū),因?yàn)樗锌赡茉俅芜B接到 master 節(jié)點(diǎn), 然后嘗試進(jìn)行 “增量同步”。

replica-priority

replica-priority 是 Redis 通過(guò) INFO 接口發(fā)布的整數(shù),默認(rèn)值為 100。 當(dāng) master 節(jié)點(diǎn)無(wú)法正常工作后 Redis Sentinel 通過(guò)這個(gè)值來(lái)決定將哪個(gè) replica 節(jié)點(diǎn)提升為 master 節(jié)點(diǎn)。這個(gè)數(shù)值越小表示越優(yōu)先進(jìn)行提升。如有三個(gè) replica 節(jié)點(diǎn)其 priority 值分別為 10,100,25, Sentinel 會(huì)選擇 priority 為 10 的節(jié)點(diǎn)進(jìn)行提升。這個(gè)值為 0 表示 replica 節(jié)點(diǎn)永遠(yuǎn)不能被提升為 master 節(jié)點(diǎn)。

min-replicas-to-write

min-replicas-max-lag

//表示要求至少3個(gè)延遲<=10秒的副本存在
min-replicas-to-write 3  //下文中的 N
min-replicas-max-lag 10 //下文中的 M

從 Redis 2.8 開(kāi)始,如果連接的 replica 延遲小于或等于M秒的個(gè)數(shù)少于N個(gè)(N個(gè) replica 需要處于“online”狀態(tài)),則 master 可能停止接受寫(xiě)入并回復(fù) error。由于 Redis 使用異步復(fù)制,因此無(wú)法確保 replica 是否實(shí)際接收到給定的寫(xiě)命令,因此總會(huì)有一個(gè)數(shù)據(jù)丟失窗口。

原理如下:

  • replica 每秒鐘都會(huì) ping master,確認(rèn)已處理的復(fù)制流的數(shù)量;
  • master 會(huì)記得上一次從每個(gè) replica 都收到 ping 的時(shí)間,延遲就是根據(jù) master 從 replica 接收的最后一次 ping 計(jì)算的;
  • 用戶可以配置延遲不超過(guò)最大秒數(shù)的最小 replica 數(shù);

此選項(xiàng)不保證 N 個(gè)副本將接受寫(xiě)入,但在沒(méi)有足夠的副本可用的情況下,將丟失寫(xiě)入的暴露窗口限制在指定的秒數(shù)內(nèi)。

N 默認(rèn)值為 0,M 默認(rèn)值為10。任意一個(gè)設(shè)置為 0 表示不啟用此功能。

replica-announce-ip 5.5.5.5

replica-announce-port 1234

Redis master 可以通過(guò)不同方式列出連接上來(lái)的 replicas 節(jié)點(diǎn)的地址和端口。 如 Redis Sentinel 等會(huì)使用 “INFO replication” 命令來(lái)獲取 replica 實(shí)例信息,master 的“ROLE“ 命令也會(huì)提供此信息。

這個(gè)信息一般來(lái)說(shuō)是通過(guò) replica 節(jié)點(diǎn)通過(guò)以下方式獲取然后報(bào)告上來(lái)的:

  • IP:通過(guò)自動(dòng)識(shí)別連接到 Socket 的信息自動(dòng)獲取
  • Port:一般來(lái)說(shuō)這個(gè)值就是 replicas 節(jié)點(diǎn)用來(lái)接受客戶端的連接的監(jiān)聽(tīng)端口

但是,若啟用了端口轉(zhuǎn)發(fā)或者 NAT,可能需要其他地址和端口才能連接到 replicas 節(jié)點(diǎn)。 這種情況下,需要設(shè)置這兩個(gè)選項(xiàng),這樣 replicas 就會(huì)用這兩個(gè)選項(xiàng)設(shè)置的值覆蓋默認(rèn)行為獲取的值,然后報(bào)告給 master 節(jié)點(diǎn)。 根據(jù)實(shí)際情況,你可以只設(shè)置其中某個(gè)選項(xiàng),而不用兩個(gè)選項(xiàng)都設(shè)置。

配置的介紹到這里就結(jié)束了,接下來(lái)我們把上邊提到的概念串起來(lái),聊一下主從復(fù)制的相關(guān)原理。

原理

系統(tǒng)的運(yùn)行依靠三個(gè)主要的機(jī)制

  • 當(dāng)一個(gè) master 實(shí)例和一個(gè) replica 實(shí)例連接正常時(shí), master 會(huì)發(fā)送一連串的命令流來(lái)保持對(duì) replica 的更新,以便于將自身數(shù)據(jù)集的改變復(fù)制給 replica ,包括客戶端的寫(xiě)入、key 的過(guò)期或被逐出等等。
  • 當(dāng) master 和 replica 之間的連接斷開(kāi)之后,因?yàn)榫W(wǎng)絡(luò)問(wèn)題、或者是主從意識(shí)到連接超時(shí), replica 重新連接上 master 并會(huì)嘗試進(jìn)行部分重同步。這意味著它會(huì)嘗試只獲取在斷開(kāi)連接期間內(nèi)丟失的命令流。
  • 當(dāng)無(wú)法進(jìn)行部分重同步時(shí), replica 會(huì)請(qǐng)求進(jìn)行全量重同步。這會(huì)涉及到一個(gè)更復(fù)雜的過(guò)程,例如 master 需要?jiǎng)?chuàng)建所有數(shù)據(jù)的快照,將之發(fā)送給 replica ,之后在數(shù)據(jù)集更改時(shí)持續(xù)發(fā)送命令流到 replica 。

Redis 復(fù)制功能是如何工作的

每一個(gè) Redis master 都有一個(gè) replication ID :這是一個(gè)較大的偽隨機(jī)字符串,標(biāo)記了一個(gè)給定的數(shù)據(jù)集。每個(gè) master 也持有一個(gè)偏移量,master 將自己產(chǎn)生的復(fù)制流發(fā)送給 replica 時(shí),發(fā)送多少個(gè)字節(jié)的數(shù)據(jù),自身的偏移量就會(huì)增加多少,目的是當(dāng)有新的操作修改自己的數(shù)據(jù)集時(shí),它可以以此更新 replica 的狀態(tài)。

復(fù)制偏移量即使在沒(méi)有一個(gè) replica 連接到 master 時(shí),也會(huì)自增,所以基本上每一對(duì)給定的 Replication ID, offset 都會(huì)標(biāo)識(shí)一個(gè) master 數(shù)據(jù)集的確切版本。

當(dāng) replica 連接到 master 時(shí),它使用 PSYNC 命令來(lái)發(fā)送它記錄的舊的 master replication ID 和它至今為止處理的偏移量。通過(guò)這種方式, master 能夠僅發(fā)送 replica 所需的增量部分。但是如果 master 的緩沖區(qū)中沒(méi)有足夠的 backlog 或者 replica 引用了 master 不知道的歷史記錄(replication ID),則會(huì)轉(zhuǎn)而進(jìn)行一個(gè)全量重同步:在這種情況下, replica 會(huì)得到一個(gè)完整的數(shù)據(jù)集副本,從頭開(kāi)始。

說(shuō)到這兒,那什么是全量同步,那什么又是增量同步呢?

全量同步

3全量同步.jpg
  1. replica 連接 master,發(fā)送 PSYNC 命令;
  2. master 執(zhí)行 bgsave 開(kāi)啟一個(gè)后臺(tái)保存進(jìn)程,以便于生產(chǎn)一個(gè) RDB 文件。同時(shí)它開(kāi)始緩沖所有從客戶端接收到的新的寫(xiě)入命令。
  3. 當(dāng)后臺(tái)保存完成時(shí), master 將數(shù)據(jù)集文件傳輸給所有的 replica,并在發(fā)送期間繼續(xù)記錄被執(zhí)行的寫(xiě)命令;
  4. replica 收到 RDB 文件之后,丟棄所有的舊數(shù)據(jù),然后加載新文件到內(nèi)存;
  5. replica 加載完成后,通知 master 發(fā)送所有緩沖的命令給 replica,這個(gè)過(guò)程以指令流的形式完成并且和 Redis 協(xié)議本身的格式相同;
  6. replica 開(kāi)始接收命令請(qǐng)求,并執(zhí)行來(lái)自 master 緩沖區(qū)的寫(xiě)命令。

注意:SYNC 是一個(gè)舊協(xié)議,在新的 Redis 中已經(jīng)不再被使用,但是仍然向后兼容。因?yàn)樗辉试S部分重同步,所以現(xiàn)在 PSYNC 被用來(lái)替代 SYNC。

正常情況下,一個(gè)全量重同步要求在磁盤(pán)上創(chuàng)建一個(gè) RDB 文件,然后將它從磁盤(pán)加載進(jìn)內(nèi)存,然后 replica 以此進(jìn)行數(shù)據(jù)同步。如果磁盤(pán)性能很低的話,這對(duì) master 是一個(gè)壓力很大的操作。Redis 2.8.18 是第一個(gè)支持無(wú)磁盤(pán)復(fù)制的版本。在此設(shè)置中,子進(jìn)程直接發(fā)送 RDB 文件給 replica 的 sockets 中,無(wú)需使用磁盤(pán)作為中間儲(chǔ)存介質(zhì)。

增量同步

master 把命令發(fā)送給所有的 replica 的同時(shí),還會(huì)將命令寫(xiě)入 backlog 緩沖區(qū)里面。

當(dāng) replica 與 master 斷開(kāi)連接又重新連接之后,此時(shí)要判斷 replica 的偏移量與 master 的偏移量的差集有沒(méi)有超過(guò) backlog 的大小,

  • 如果沒(méi)有則給 replica 發(fā)送 CONTINUE,等待 master 將 backlog 中的數(shù)據(jù)發(fā)送給 replica;
  • 如果超過(guò)了則返回 FULLRESYNC runid offset,replica 將 runid 保存起來(lái),并進(jìn)行全量同步;

最后我們來(lái)聊幾個(gè)在面試過(guò)程中經(jīng)常提到的面試題。

面試題

在主從復(fù)制過(guò)程中,關(guān)閉 master 的持久化會(huì)引發(fā)什么問(wèn)題呢?

數(shù)據(jù)會(huì)從 master 和所有 replica 中被刪除。我們用案例來(lái)說(shuō)明一下:

  1. 我們?cè)O(shè)置節(jié)點(diǎn) A 為 master 并關(guān)閉它的持久化設(shè)置,設(shè)置節(jié)點(diǎn) B 和 C 為 replica;
  2. 當(dāng) master 崩潰時(shí),由于系統(tǒng)中配置了自動(dòng)重啟的腳本,此時(shí) master 會(huì)自動(dòng)重啟。但是由于持久化被關(guān)閉了,master 重啟后其數(shù)據(jù)集合為空;
  3. 此時(shí),如果 replica 從 master 中同步數(shù)據(jù),就會(huì)導(dǎo)致 replica 中的數(shù)據(jù)也會(huì)變?yōu)榭占稀?/li>

因此,我們?cè)谑褂?Redis 復(fù)制功能時(shí),強(qiáng)烈建議在 master 和 replica 中啟用持久化。如果因?yàn)榉浅B拇疟P(pán)性能導(dǎo)致的延遲問(wèn)題而不啟用持久化時(shí),應(yīng)該配置節(jié)點(diǎn)來(lái)避免重置后自動(dòng)重啟

Redis 復(fù)制如何處理 key 的過(guò)期問(wèn)題

Redis 的過(guò)期機(jī)制可以限制 key 的生存時(shí)間,該機(jī)制取決于 Redis 計(jì)算時(shí)間的能力。但是,即使使用 Lua 腳本將這些 key 變?yōu)檫^(guò)期的 key,Redis replicas 也能正確地復(fù)制這些 key。

為了實(shí)現(xiàn)這樣的功能,Redis 不能依靠主從使用同步時(shí)鐘,因?yàn)檫@是一個(gè)無(wú)法解決的并且會(huì)導(dǎo)致 race condition 和數(shù)據(jù)集不一致的問(wèn)題,所以 Redis 使用三種主要的技術(shù)使過(guò)期的 key 的復(fù)制能夠正確工作:

  • replica 不會(huì)讓 key 過(guò)期,而是等待 master 讓 key 過(guò)期。當(dāng)一個(gè) master 讓一個(gè) key 到期(或由于 LRU 算法將之驅(qū)逐)時(shí),它會(huì)合成一個(gè) DEL 命令并傳輸?shù)剿械?replica;
  • 由于主驅(qū)動(dòng)的原因,master 無(wú)法及時(shí)提供 DEL 命令,所以有時(shí)候 replica 的內(nèi)存中仍然可能存在邏輯上已經(jīng)過(guò)期的 key。為了處理這個(gè)問(wèn)題,replica 使用它的邏輯時(shí)鐘來(lái)報(bào)告在不違反數(shù)據(jù)一致性的前提下,讀取操作的 key 不存在。用這種方法,replica 避免報(bào)告邏輯過(guò)期的 key 仍然存在。在實(shí)際應(yīng)用中,使用 replica 程序進(jìn)行擴(kuò)展的 HTML 碎片緩存,將避免返回已經(jīng)比期望的時(shí)間更早的數(shù)據(jù)項(xiàng)。
  • 在Lua腳本執(zhí)行期間,不執(zhí)行任何 key 過(guò)期操作。當(dāng)一個(gè)Lua腳本運(yùn)行時(shí),從概念上講,master 中的時(shí)間是被凍結(jié)的,這樣腳本運(yùn)行的時(shí)候,一個(gè)給定的鍵要么存在要么不存在。這可以防止 key 在腳本中間過(guò)期,保證將相同的腳本發(fā)送到 replica ,從而在二者的數(shù)據(jù)集中產(chǎn)生相同的效果。

一旦一個(gè) replica 被提升為一個(gè) master ,它將開(kāi)始獨(dú)立地過(guò)期 key,而不需要任何舊 master 的幫助。

以上就是今天的全部?jī)?nèi)容了,如果你有不同的意見(jiàn)或者更好的idea,歡迎聯(lián)系阿Q,添加阿Q可以加入技術(shù)交流群參與討論呦!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容