深入Redis主從復(fù)制原理

復(fù)制原理

1.復(fù)制過(guò)程

復(fù)制的過(guò)程步驟如下:

10年積累的網(wǎng)站建設(shè)、做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先制作網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有岳陽(yáng)樓免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

  • 從節(jié)點(diǎn)執(zhí)行 slaveof 命令
  • 從節(jié)點(diǎn)只是保存了 slaveof 命令中主節(jié)點(diǎn)的信息,并沒(méi)有立即發(fā)起復(fù)制
  • 從節(jié)點(diǎn)內(nèi)部的定時(shí)任務(wù)發(fā)現(xiàn)有主節(jié)點(diǎn)的信息,開(kāi)始使用 socket 連接主節(jié)點(diǎn)
  • 連接建立成功后,發(fā)送 ping 命令,希望得到 pong 命令響應(yīng),否則會(huì)進(jìn)行重連
  • 如果主節(jié)點(diǎn)設(shè)置了權(quán)限,那么就需要進(jìn)行權(quán)限驗(yàn)證;如果驗(yàn)證失敗,復(fù)制終止。
  • 權(quán)限驗(yàn)證通過(guò)后,進(jìn)行數(shù)據(jù)同步,這是耗時(shí)最長(zhǎng)的操作,主節(jié)點(diǎn)將把所有的數(shù)據(jù)全部發(fā)送給從節(jié)點(diǎn)。
  • 當(dāng)主節(jié)點(diǎn)把當(dāng)前的數(shù)據(jù)同步給從節(jié)點(diǎn)后,便完成了復(fù)制的建立流程。接下來(lái),主節(jié)點(diǎn)就會(huì)持續(xù)的把寫命令發(fā)送給從節(jié)點(diǎn),保證主從數(shù)據(jù)一致性。
    深入Redis 主從復(fù)制原理

2.數(shù)據(jù)間的同步

上面說(shuō)的復(fù)制過(guò)程,其中有一個(gè)步驟是“同步數(shù)據(jù)集”,這個(gè)就是現(xiàn)在講的‘?dāng)?shù)據(jù)間的同步’。

redis 同步有 2 個(gè)命令:

sync 和 psync,前者是 redis 2.8 之前的同步命令,后者是 redis 2.8 為了優(yōu)化 sync 新設(shè)計(jì)的命令。我們會(huì)重點(diǎn)關(guān)注 2.8 的 psync 命令。

psync 命令需要 3 個(gè)組件支持:

  • 主從節(jié)點(diǎn)各自復(fù)制偏移量
  • 主節(jié)點(diǎn)復(fù)制積壓緩沖區(qū)
  • 主節(jié)點(diǎn)運(yùn)行 ID

主從節(jié)點(diǎn)各自復(fù)制偏移量:

  • 參與復(fù)制的主從節(jié)點(diǎn)都會(huì)維護(hù)自身的復(fù)制偏移量。
  • 主節(jié)點(diǎn)在處理完寫入命令后,會(huì)把命令的字節(jié)長(zhǎng)度做累加記錄,統(tǒng)計(jì)信息在 info replication 中的masterreploffset 指標(biāo)中。
  • 從節(jié)點(diǎn)每秒鐘上報(bào)自身的的復(fù)制偏移量給主節(jié)點(diǎn),因此主節(jié)點(diǎn)也會(huì)保存從節(jié)點(diǎn)的復(fù)制偏移量。
  • 從節(jié)點(diǎn)在接收到主節(jié)點(diǎn)發(fā)送的命令后,也會(huì)累加自身的偏移量,統(tǒng)計(jì)信息在 info replication 中。
  • 通過(guò)對(duì)比主從節(jié)點(diǎn)的復(fù)制偏移量,可以判斷主從節(jié)點(diǎn)數(shù)據(jù)是否一致。

主節(jié)點(diǎn)復(fù)制積壓緩沖區(qū):

  • 復(fù)制積壓緩沖區(qū)是一個(gè)保存在主節(jié)點(diǎn)的一個(gè)固定長(zhǎng)度的先進(jìn)先出的隊(duì)列。默認(rèn)大小 1MB。
  • 這個(gè)隊(duì)列在 slave 連接是創(chuàng)建。這時(shí)主節(jié)點(diǎn)響應(yīng)寫命令時(shí),不但會(huì)把命令發(fā)送給從節(jié)點(diǎn),也會(huì)寫入復(fù)制緩沖區(qū)。
  • 他的作用就是用于部分復(fù)制和復(fù)制命令丟失的數(shù)據(jù)補(bǔ)救。通過(guò) info replication 可以看到相關(guān)信息。

主節(jié)點(diǎn)運(yùn)行 ID:

  • 每個(gè) redis 啟動(dòng)的時(shí)候,都會(huì)生成一個(gè) 40 位的運(yùn)行 ID。
  • 運(yùn)行 ID 的主要作用是用來(lái)識(shí)別 Redis 節(jié)點(diǎn)。如果使用 ip+port 的方式,那么如果主節(jié)點(diǎn)重啟修改了 RDB/AOF 數(shù)據(jù),從節(jié)點(diǎn)再基于偏移量進(jìn)行復(fù)制將是不安全的。所以,當(dāng)運(yùn)行 id 變化后,從節(jié)點(diǎn)將進(jìn)行全量復(fù)制。也就是說(shuō),redis 重啟后,默認(rèn)從節(jié)點(diǎn)會(huì)進(jìn)行全量復(fù)制。

如果在重啟時(shí)不改變運(yùn)行 ID 呢?

  • 可以通過(guò) debug reload 命令重新加載 RDB 并保持運(yùn)行 ID 不變。從而有效的避免不必要的全量復(fù)制。
  • 他的缺點(diǎn)則是:debug reload 命令會(huì)阻塞當(dāng)前 Redis 節(jié)點(diǎn)主線程,因此對(duì)于大數(shù)據(jù)量的主節(jié)點(diǎn)或者無(wú)法容忍阻塞的節(jié)點(diǎn),需要謹(jǐn)慎使用。一般通過(guò)故障轉(zhuǎn)移機(jī)制可以解決這個(gè)問(wèn)題。

psync 命令的使用方式:

命令格式為psync{runId}{offset}

runId:從節(jié)點(diǎn)所復(fù)制主節(jié)點(diǎn)的運(yùn)行 id
offset:當(dāng)前從節(jié)點(diǎn)已復(fù)制的數(shù)據(jù)偏移量

psync 執(zhí)行流程:
深入Redis 主從復(fù)制原理

流程說(shuō)明:從節(jié)點(diǎn)發(fā)送 psync 命令給主節(jié)點(diǎn),runId 就是目標(biāo)主節(jié)點(diǎn)的 ID,如果沒(méi)有默認(rèn)為 -1,offset 是從節(jié)點(diǎn)保存的復(fù)制偏移量,如果是第一次復(fù)制則為 -1.

主節(jié)點(diǎn)會(huì)根據(jù) runid 和 offset 決定返回結(jié)果:

  • 如果回復(fù) +FULLRESYNC {runId} {offset} ,那么從節(jié)點(diǎn)將觸發(fā)全量復(fù)制流程。
  • 如果回復(fù) +CONTINUE,從節(jié)點(diǎn)將觸發(fā)部分復(fù)制。
  • 如果回復(fù) +ERR,說(shuō)明主節(jié)點(diǎn)不支持 2.8 的 psync 命令,將使用 sync 執(zhí)行全量復(fù)制。

到這里,數(shù)據(jù)之間的同步就講的差不多了,篇幅還是比較長(zhǎng)的。主要是針對(duì) psync 命令相關(guān)之間的介紹。

3.全量復(fù)制

全量復(fù)制是 Redis 最早支持的復(fù)制方式,也是主從第一次建立復(fù)制時(shí)必須經(jīng)歷的的階段。觸發(fā)全量復(fù)制的命令是 sync 和 psync。之前說(shuō)過(guò),這兩個(gè)命令的分水嶺版本是 2.8,redis 2.8 之前使用 sync 只能執(zhí)行全量不同,2.8 之后同時(shí)支持全量同步和部分同步。

流程如下:

深入Redis 主從復(fù)制原理

介紹一下上圖步驟:

  • 發(fā)送 psync 命令(spync ? -1)
  • 主節(jié)點(diǎn)根據(jù)命令返回 FULLRESYNC
  • 從節(jié)點(diǎn)記錄主節(jié)點(diǎn) ID 和 offset
  • 主節(jié)點(diǎn) bgsave 并保存 RDB 到本地
  • 主節(jié)點(diǎn)發(fā)送 RBD 文件到從節(jié)點(diǎn)
  • 從節(jié)點(diǎn)收到 RDB 文件并加載到內(nèi)存中
  • 主節(jié)點(diǎn)在從節(jié)點(diǎn)接受數(shù)據(jù)的期間,將新數(shù)據(jù)保存到“復(fù)制客戶端緩沖區(qū)”,當(dāng)從節(jié)點(diǎn)加載 RDB 完畢,再發(fā)送過(guò)去。(如果從節(jié)點(diǎn)花費(fèi)時(shí)間過(guò)長(zhǎng),將導(dǎo)致緩沖區(qū)溢出,最后全量同步失?。?/li>
  • 從節(jié)點(diǎn)清空數(shù)據(jù)后加載 RDB 文件,如果 RDB 文件很大,這一步操作仍然耗時(shí),如果此時(shí)客戶端訪問(wèn),將導(dǎo)致數(shù)據(jù)不一致,可以使用配置slave-server-stale-data 關(guān)閉.
  • 從節(jié)點(diǎn)成功加載完 RBD 后,如果開(kāi)啟了 AOF,會(huì)立刻做 bgrewriteaof。

以上加粗的部分是整個(gè)全量同步耗時(shí)的地方。

注意:

  • 如過(guò) RDB 文件大于 6GB,并且是千兆網(wǎng)卡,Redis 的默認(rèn)超時(shí)機(jī)制(60 秒),會(huì)導(dǎo)致全量復(fù)制失敗。可以通過(guò)調(diào)大 repl-timeout 參數(shù)來(lái)解決此問(wèn)題。
  • Redis 雖然支持無(wú)盤復(fù)制,即直接通過(guò)網(wǎng)絡(luò)發(fā)送給從節(jié)點(diǎn),但功能不是很完善,生產(chǎn)環(huán)境慎用。

4.部分復(fù)制

當(dāng)從節(jié)點(diǎn)正在復(fù)制主節(jié)點(diǎn)時(shí),如果出現(xiàn)網(wǎng)絡(luò)閃斷和其他異常,從節(jié)點(diǎn)會(huì)讓主節(jié)點(diǎn)補(bǔ)發(fā)丟失的命令數(shù)據(jù),主節(jié)點(diǎn)只需要將復(fù)制緩沖區(qū)的數(shù)據(jù)發(fā)送到從節(jié)點(diǎn)就能夠保證數(shù)據(jù)的一致性,相比較全量復(fù)制,成本小很多。

步驟如下:

深入Redis 主從復(fù)制原理

  • 當(dāng)從節(jié)點(diǎn)出現(xiàn)網(wǎng)絡(luò)中斷,超過(guò)了 repl-timeout 時(shí)間,主節(jié)點(diǎn)就會(huì)中斷復(fù)制連接。
  • 主節(jié)點(diǎn)會(huì)將請(qǐng)求的數(shù)據(jù)寫入到“復(fù)制積壓緩沖區(qū)”,默認(rèn) 1MB。
  • 當(dāng)從節(jié)點(diǎn)恢復(fù),重新連接上主節(jié)點(diǎn),從節(jié)點(diǎn)會(huì)將 offset 和主節(jié)點(diǎn) id 發(fā)送到主節(jié)點(diǎn)
  • 主節(jié)點(diǎn)校驗(yàn)后,如果偏移量的數(shù)后的數(shù)據(jù)在緩沖區(qū)中,就發(fā)送 cuntinue 響應(yīng) —— 表示可以進(jìn)行部分復(fù)制
  • 主節(jié)點(diǎn)將緩沖區(qū)的數(shù)據(jù)發(fā)送到從節(jié)點(diǎn),保證主從復(fù)制進(jìn)行正常狀態(tài)。

5.心跳

主從節(jié)點(diǎn)在建立復(fù)制后,他們之間維護(hù)著長(zhǎng)連接并彼此發(fā)送心跳命令。

心跳的關(guān)鍵機(jī)制如下:

  • 中從都有心跳檢測(cè)機(jī)制,各自模擬成對(duì)方的客戶端進(jìn)行通信,通過(guò) client list 命令查看復(fù)制相關(guān)客戶端信息,主節(jié)點(diǎn)的連接狀態(tài)為 flags = M,從節(jié)點(diǎn)的連接狀態(tài)是 flags = S。
  • 主節(jié)點(diǎn)默認(rèn)每隔 10 秒對(duì)從節(jié)點(diǎn)發(fā)送 ping 命令,可修改配置 repl-ping-slave-period 控制發(fā)送頻率。
  • 從節(jié)點(diǎn)在主線程每隔一秒發(fā)送 replconf ack{offset} 命令,給主節(jié)點(diǎn)上報(bào)自身當(dāng)前的復(fù)制偏移量。
  • 主節(jié)點(diǎn)收到 replconf 信息后,判斷從節(jié)點(diǎn)超時(shí)時(shí)間,如果超過(guò) repl-timeout 60 秒,則判斷節(jié)點(diǎn)下線。

深入Redis 主從復(fù)制原理

注意:為了降低主從延遲,一般把 redis 主從節(jié)點(diǎn)部署在相同的機(jī)房/同城機(jī)房,避免網(wǎng)絡(luò)延遲帶來(lái)的網(wǎng)絡(luò)分區(qū)造成的心跳中斷等情況。

6.異步復(fù)制

主節(jié)點(diǎn)不但負(fù)責(zé)數(shù)據(jù)讀寫,還負(fù)責(zé)把寫命令同步給從節(jié)點(diǎn),寫命令的發(fā)送過(guò)程是異步完成,也就是說(shuō)主節(jié)點(diǎn)處理完寫命令后立即返回客戶度,并不等待從節(jié)點(diǎn)復(fù)制完成。

異步復(fù)制的步驟很簡(jiǎn)單,如下:

  • 主節(jié)點(diǎn)接受處理命令
  • 主節(jié)點(diǎn)處理完后返回響應(yīng)結(jié)果
  • 對(duì)于修改命令,異步發(fā)送給從節(jié)點(diǎn),從節(jié)點(diǎn)在主線程中執(zhí)行復(fù)制的命令。

總結(jié)

本文主要分析了 Redis 的復(fù)制原理,包括復(fù)制過(guò)程,數(shù)據(jù)之間的同步,全量復(fù)制的流程,部分復(fù)制的流程,心跳設(shè)計(jì),異步復(fù)制流程。

其中,可以看出,RDB 數(shù)據(jù)之間的同步非常耗時(shí)。所以,Redis 在 2.8 版本退出了類似增量復(fù)制的 psync 命令,當(dāng) Redis 主從直接發(fā)生了網(wǎng)絡(luò)中斷,不會(huì)進(jìn)行全量復(fù)制,而是將數(shù)據(jù)放到緩沖區(qū)(默認(rèn) 1MB)里,在通過(guò)主從之間各自維護(hù)復(fù)制 offset 來(lái)判斷緩存區(qū)的數(shù)據(jù)是否溢出,如果沒(méi)有溢出,只需要發(fā)送緩沖區(qū)數(shù)據(jù)即可,成本很小,反之,則要進(jìn)行全量復(fù)制,因此,控制緩沖區(qū)大小非常的重要。

好了,關(guān)于redis 主從復(fù)制的原理就介紹到這里 ,篇幅有限,難免疏漏。

本文題目:深入Redis主從復(fù)制原理
文章路徑:http://bm7419.com/article26/pcedjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司自適應(yīng)網(wǎng)站、網(wǎng)站設(shè)計(jì)網(wǎng)站導(dǎo)航、定制網(wǎng)站

廣告

聲明:本網(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í)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司