復(fù)制
從服務(wù)器對(duì)主服務(wù)器進(jìn)行復(fù)制,以達(dá)到數(shù)據(jù)庫(kù)狀態(tài)一致。
Redis2.8以前的復(fù)制功能:同步和命令傳播。
同步
從服務(wù)器對(duì)主服務(wù)器的同步操作是通過(guò)向主服務(wù)器發(fā)送SYNC命令來(lái)完成的,步驟:
- 從服務(wù)器向主服務(wù)器發(fā)送SYNC命令;
- 收到SYNC命令的主服務(wù)器執(zhí)行BGSAVE命令,在后臺(tái)生成一個(gè)RDB文件,并使用一個(gè)緩沖區(qū)記錄從此刻開(kāi)始的所有寫(xiě)命令;
- 主服務(wù)器將RDB文件發(fā)送給從服務(wù)器,從服務(wù)器接收并載入這個(gè)RDB文件,將自己的數(shù)據(jù)庫(kù)狀態(tài)更新到主服務(wù)器執(zhí)行BGSAVE時(shí)的數(shù)據(jù)庫(kù)狀態(tài);
- 主服務(wù)器將記錄在緩沖區(qū)的所有寫(xiě)命令發(fā)送給從服務(wù)器,從服務(wù)器執(zhí)行這些寫(xiě)命令,將自己的數(shù)據(jù)庫(kù)狀態(tài)更新至主服務(wù)器數(shù)據(jù)庫(kù)當(dāng)前所處的狀態(tài)。
命令傳播
在同步后,主服務(wù)器會(huì)將自己執(zhí)行的寫(xiě)命令,也即是造成主從服務(wù)器不一致的寫(xiě)命令,發(fā)送給從服務(wù)器執(zhí)行以達(dá)到一致?tīng)顟B(tài)。
缺陷:若出現(xiàn)斷線重新連接,從服務(wù)器會(huì)再次向主服務(wù)器發(fā)送SYNC請(qǐng)求重新同步一次,而不是執(zhí)行從斷線到重連這段時(shí)間內(nèi)的寫(xiě)命令,這樣會(huì)導(dǎo)致浪費(fèi)。
Redis2.8開(kāi)始,使用PSYNC命令代替SYNC命令來(lái)執(zhí)行復(fù)制操作。PSYNC的兩種模式:
- 完整重同步:與SYNC命令一樣,主服務(wù)器創(chuàng)建并發(fā)送RDB文件,并向從服務(wù)器發(fā)送保存在緩沖區(qū)里的寫(xiě)命令來(lái)進(jìn)行同步;
- 部分重同步:當(dāng)從服務(wù)器斷線后重新連接主服務(wù)器,如果條件允許,主服務(wù)器可將斷開(kāi)期間執(zhí)行的寫(xiě)命令發(fā)送給從服務(wù)器以達(dá)到一致?tīng)顟B(tài)。
部分重同步的實(shí)現(xiàn)
- 復(fù)制偏移量
- 主服務(wù)器復(fù)制積壓緩沖區(qū)
- 服務(wù)器運(yùn)行ID
1、復(fù)制偏移量
執(zhí)行復(fù)制的雙方分別維護(hù)一個(gè)復(fù)制偏移量:
- 主服務(wù)器每次向從服務(wù)器傳播N個(gè)字節(jié)的數(shù)據(jù)時(shí),就將自己的復(fù)制偏移量的值加上N;
- 從服務(wù)器每次收到主服務(wù)器傳播來(lái)的N個(gè)字節(jié)的數(shù)據(jù)時(shí),就將自己的復(fù)制偏移量的值加上N。
通過(guò)對(duì)比主從服務(wù)器的偏移量是否相等可以判斷是否處于一致?tīng)顟B(tài)。如果主從服務(wù)器不處于一致?tīng)顟B(tài),那么需要執(zhí)行完整重同步還是部分重同步取決于復(fù)制積壓緩沖區(qū)。
2、復(fù)制積壓緩沖區(qū)
復(fù)制積壓緩沖區(qū)是由主服務(wù)器維護(hù)的一個(gè)固定長(zhǎng)度的先進(jìn)先出隊(duì)列,默認(rèn)大小為1MB。所謂固定長(zhǎng)度的隊(duì)列是指當(dāng)元素個(gè)數(shù)超過(guò)指定隊(duì)列長(zhǎng)度時(shí),若有新元素入隊(duì)尾,則必先從隊(duì)首彈出隊(duì)首元素。
當(dāng)主服務(wù)器進(jìn)行命令傳播時(shí),不僅會(huì)將寫(xiě)命令發(fā)送給從服務(wù)器,還會(huì)將寫(xiě)命令寫(xiě)入復(fù)制積壓緩沖區(qū)中。從服務(wù)器斷線重連后,會(huì)通過(guò)PSYNC將自己的復(fù)制偏移量offset發(fā)送給主服務(wù)器,則
- 若offset之后的數(shù)據(jù)仍然在復(fù)制積壓緩沖區(qū)中,則主服務(wù)器對(duì)從服務(wù)器執(zhí)行部分重同步操作;
- 若offset之后的數(shù)據(jù)已不在復(fù)制積壓緩沖區(qū)中,則主服務(wù)器(先發(fā)送+CONTINUE回復(fù),再)對(duì)從服務(wù)器執(zhí)行完整重同步操作。
3、服務(wù)器運(yùn)行ID
主從服務(wù)器都有自己的運(yùn)行ID,服務(wù)器啟動(dòng)時(shí)自動(dòng)生成,由40個(gè)隨機(jī)的十六進(jìn)制字符組成。從服務(wù)器第一次對(duì)主服務(wù)器進(jìn)行復(fù)制時(shí),主服務(wù)器將自己的運(yùn)行ID發(fā)給從服務(wù)器,從服務(wù)器將它保存起來(lái);從服務(wù)器斷線重連后,向主服務(wù)器發(fā)送該運(yùn)行ID,若與當(dāng)前主服務(wù)器ID相同,則執(zhí)行部分重同步,否則執(zhí)行完整重同步。
PSYNC命令實(shí)現(xiàn)原理
復(fù)制的實(shí)現(xiàn)
步驟:
- 從服務(wù)器根據(jù)客戶端命令設(shè)置主服務(wù)器的IP地址和端口;
- 從服務(wù)器根據(jù)IP地址和端口建立連接主服務(wù)器的套接字,再為該套接字關(guān)聯(lián)一個(gè)文件事件處理器用于處理復(fù)制工作;
- 從服務(wù)器向主服務(wù)器發(fā)送PING命令,用于
- 檢查套接字讀寫(xiě)狀態(tài)是否正常;
-
檢查主服務(wù)器能否正常處理命令請(qǐng)求。
image
-
身份驗(yàn)證:若從服務(wù)器設(shè)置了masterauth選項(xiàng),那么進(jìn)行身份驗(yàn)證,否則不驗(yàn)證;
image 從服務(wù)器向主服務(wù)器發(fā)送自己監(jiān)聽(tīng)的端口號(hào),主服務(wù)器保存該端口號(hào);
同步;
命令傳播。
心跳檢測(cè)
在命令傳播階段,從服務(wù)器會(huì)每秒一次地向主服務(wù)器發(fā)送命令:
REPLCONF ACK <replication_offset>
該命令有三個(gè)作用:
- 檢測(cè)主從服務(wù)器的網(wǎng)絡(luò)連接狀態(tài);
- 輔助實(shí)現(xiàn)min-slaves選項(xiàng)(可防止主服務(wù)器在不安全的情況下執(zhí)行寫(xiě)命令);
- 檢測(cè)命令丟失:若主服務(wù)器命令傳播丟失了,則REPLCONF ACK <replication_offset>可讓主服務(wù)器發(fā)現(xiàn)與從服務(wù)器的偏移量不一致,引發(fā)部分重同步。