2.8版本以前
同步(snyc)
執(zhí)行步驟:
- 從服務(wù)器發(fā)送snyc給主服務(wù)器
- 主服務(wù)器收到命令后,開始執(zhí)行bgsave操作,將生成RDB文件,將生成的RDB文件同步給從服務(wù)。并使用一個緩沖區(qū)記錄從現(xiàn)在開始的寫命令
- 從服務(wù)載入接受到的RDB文件,期間不可進(jìn)行其他操作。
- 主服務(wù)將緩沖區(qū)里的命令同步給從服務(wù)器
傳播
同步完成之后,后續(xù)的命令都是通過傳播的方式發(fā)送給從服務(wù)器的。即當(dāng)主服務(wù)執(zhí)行完一條命令后,將該命令發(fā)送給從服務(wù),完成數(shù)據(jù)的同步。
缺陷
場景:
- 首次復(fù)制,不存在問題,畢竟新連接上一個master服務(wù)器,則需要復(fù)制其全量的數(shù)據(jù)
- 斷開后重連復(fù)制,這是,仍是需要通過sync進(jìn)行全量的復(fù)制,這就是很耗費(fèi)資源的。畢竟如果斷開時間短,如中間網(wǎng)絡(luò)抖動,導(dǎo)致中間短暫性斷開,再次復(fù)制全量數(shù)據(jù),成本太高。
關(guān)于sync命令:
- 主服務(wù)器需要執(zhí)行bgsave命令來生成RDB文件,這個操作會耗費(fèi)主服務(wù)器的大量CPU、內(nèi)存和磁盤IO資源。
- 主服務(wù)器將RDB文件發(fā)送給從服務(wù)器,會消耗雙方的網(wǎng)絡(luò)資源(帶寬和流量)。
- 接受到RDB文件后,從服務(wù)器需要載入RDB文件,這個載入期間,從服務(wù)器因?yàn)樽枞鴽]有辦法處理命令請求。
2.8版本以后
psnyc具備完整重同步(full resynchronization)和部分重同步(partial resynchronization)。
其中,完整重同步和sync的首次同步是一致的,通過主服務(wù)器生成RDB文件進(jìn)行全量數(shù)據(jù)的同步,如果存在多個從服務(wù)器,主服務(wù)器僅會生成一份RDB文件,分別同步給各個從服務(wù)器。部分重同步則解決了sync斷開重連的問題,當(dāng)斷開重連后,主服務(wù)器在條件允許的前提下,僅會發(fā)送斷開期間的寫命令。部分重同步的主要實(shí)現(xiàn)由以下三部分組成:
- 主服務(wù)器的復(fù)制偏移量(replication offset)和從服務(wù)器的復(fù)制偏移量
- 主服務(wù)器的復(fù)制積壓緩沖區(qū)(replication backlogs)
- 服務(wù)器的運(yùn)行ID(run ID)
復(fù)制偏移量
主服務(wù)器記錄的是自己發(fā)給從服務(wù)器的偏移量,從服務(wù)器記錄的是自己接受到的數(shù)據(jù)偏移量。比如:當(dāng)前主從服務(wù)器的偏移量均為100,在有新的寫入命令后,主服務(wù)器的偏移量變成了110,而從服務(wù)器的是100,此時會有短暫的不一致,待主服務(wù)器將新寫入命令同步給從服務(wù)器后,從服務(wù)器的偏移量會變更為110,此時主從服務(wù)器又是保持一致的數(shù)據(jù)了。
復(fù)制積壓緩沖區(qū)
一個固定長度的先進(jìn)先出隊(duì)列,默認(rèn)1M,可通過配置repl_backlog_size調(diào)整其大小。當(dāng)收到一條寫入命令,除了發(fā)給從服務(wù)器外,還會將命令寫入到復(fù)制積壓緩沖區(qū)一份。
當(dāng)從服務(wù)器A與主服務(wù)器斷開后,中間的寫入命令會無法同步給從服務(wù)器A,之后,重連后,從服務(wù)器會將其復(fù)制偏移量告知主服務(wù)器,如果該偏移量還在復(fù)制積壓緩沖區(qū)中,則直接將復(fù)制積壓緩沖區(qū)該偏移量后的命令發(fā)送給從服務(wù)器。
服務(wù)器的運(yùn)行ID
每個redis實(shí)例在啟動時候,都會隨機(jī)生成一個長度為40的唯一字符串來標(biāo)識當(dāng)前運(yùn)行的redis節(jié)點(diǎn)。當(dāng)從服務(wù)器對主服務(wù)器進(jìn)行首次復(fù)制時,則將自己的runID發(fā)送給從服務(wù)器,從服務(wù)器會將這個ID保存起來。當(dāng)從服務(wù)器與主服務(wù)器斷開后重連時,會向主服務(wù)器發(fā)送當(dāng)前存儲的runID,主服務(wù)器收到后,會判斷與當(dāng)前自己的runID是否一致,如果不一致,則進(jìn)行全量復(fù)制;如果一致,則判斷復(fù)制偏移量是否還在復(fù)制積壓緩沖區(qū)中,如果還在,則進(jìn)行部分重同步。
psync命令
psync <runId> <offset>
首次發(fā)送時為psync ? -1,之后發(fā)送的為上次master的runID和當(dāng)前的復(fù)制偏移量。
缺陷
由于每次實(shí)例重啟都會重新生成runID,或者發(fā)生故障遷移后,新Master的runId必然與上一次的不一致,仍會導(dǎo)致完整重同步。
4.0版本以后的優(yōu)化
解決了psnyc的缺陷,簡稱:psync2
第一種情況:redis重啟
第一步,在redis關(guān)閉時,通過shutdown save,都會調(diào)用rdbSaveInfoAuxFields函數(shù),把當(dāng)前實(shí)例的repl-id和repl-offset保存到RDB文件中。
第二步,重啟后加載RDB文件中的復(fù)制信息。把其中repl_id和repl_offset加載到實(shí)例中,分別賦給master_replid和master_repl_offset兩個變量值。
當(dāng)從庫開啟了AOF持久化,redis加載順序發(fā)生變化優(yōu)先加載AOF文件,但是由于aof文件中沒有復(fù)制信息,所以導(dǎo)致重啟后從實(shí)例依舊使用全量復(fù)制!
第三步:向主庫上報(bào)復(fù)制信息,判斷是否進(jìn)行部分同步。
- 從實(shí)例向主庫上報(bào)master_replid與主實(shí)例的master_replid1或replid2有一個相等,用于判斷主從未發(fā)生改變;
- 從實(shí)例上報(bào)的master_repl_offset+1字節(jié),還存在于主實(shí)例的復(fù)制積壓緩沖區(qū)中,用于判斷從庫丟失部分是否在復(fù)制緩沖區(qū)中;
第二種情況: 故障切換
redis從庫默認(rèn)開始復(fù)制積壓緩沖區(qū),方便從庫切換為主庫,其他從庫可以直接從master節(jié)點(diǎn)獲取缺失的命令。通過兩組replId實(shí)現(xiàn)。
第一組:master_replid和master_repl_offset:如果redis是主實(shí)例,則表示為自己的replid和復(fù)制偏移量; 如果redis是從實(shí)例,則表示為自己主實(shí)例的replid1和同步主實(shí)例的復(fù)制偏移量。
第二組:master_replid2和second_repl_offset:無論主從,都表示自己上次主實(shí)例repid1和復(fù)制偏移量;用于兄弟實(shí)例或級聯(lián)復(fù)制,主庫故障切換psync。
判斷是否使用部分復(fù)制條件:如果從庫提供的master_replid與master的replid不同,且與master的replid2不同,或同步速度快于master; 就必須進(jìn)行全量復(fù)制,否則執(zhí)行部分復(fù)制。
文章來自
https://www.cnblogs.com/woniu4/p/16182384.html






