【Redis二三事】Redis的主從復(fù)制機制
??1 主從復(fù)制
??1.1 主從復(fù)制簡介
了解主從復(fù)制之前,你的redis是否高可用?
如果我們的redis是單機的就會存在一定的風(fēng)險
問題1:機器故障
現(xiàn)象:硬盤故障,系統(tǒng)崩潰
本質(zhì):數(shù)據(jù)丟失,很可能對業(yè)務(wù)造成災(zāi)難性打擊
問題2:容量瓶頸
現(xiàn)象:內(nèi)存不足,從16G升級到64G,從64G升級到128G,無限升級內(nèi)存
本質(zhì):沒錢,硬件條件跟不上
結(jié)論:硬件的發(fā)展速度直接決定軟件的技術(shù),內(nèi)存上不去,redis存儲的數(shù)據(jù)量就很低,這樣下去就會放棄redis
因此:
為了避免Redis服務(wù)器故障造成重大損失,我們準(zhǔn)備多臺服務(wù)器,互相來南通。將數(shù)據(jù)復(fù)制多個副本保存在不同的服 務(wù)器上,連接在一起,并保證數(shù)據(jù)是同步的。即使有其中一臺服務(wù)器宕機,其他服務(wù)器依然可以繼續(xù)提供服務(wù),實現(xiàn) Redis的高可用,同時實現(xiàn)數(shù)據(jù)冗余備份
1.1.1多臺服務(wù)器連接方案
我們讓主服務(wù)器專門負(fù)責(zé)寫數(shù)據(jù),下面的從屬計算機專門負(fù)責(zé)讀數(shù)據(jù),數(shù)據(jù)由主服務(wù)器提供給從屬服務(wù)器,這樣的話我們的數(shù)據(jù)有多個備份,也就實現(xiàn)了高可用
提供數(shù)據(jù)方:master
我們可以稱之為:==主服務(wù)器,主節(jié)點,主庫,主客戶端==
接收數(shù)據(jù)方:slave
我們可以稱之為:==從節(jié)點,從庫,從客戶端==
需要解決的問題
數(shù)據(jù)同步:master的數(shù)據(jù)復(fù)制到slave
這樣,我么從主服務(wù)器向從服務(wù)器復(fù)制數(shù)據(jù),就是主從復(fù)制
??1.2 主從復(fù)制
==主從復(fù)制即:將master中的數(shù)據(jù)及時,有效的復(fù)制到slave中==
特征:一個master可以擁有多個slave,一個slave只對應(yīng)一個master
職責(zé):
master
寫數(shù)據(jù)
執(zhí)行寫操作時,將出現(xiàn)變化的數(shù)據(jù)自動同步到slave
slave
讀數(shù)據(jù)
可能會有人說:master的壓力過大崩潰了怎么辦,不要著急,我們后面會說到的的哨兵模式就是為了解決這一問題的 除此之外,當(dāng)我們的master壓力很大時,我們可以在某一個slave上給其追加從屬服務(wù)器,例如下圖,所以說, master和slave是一種相對的概念
??1.2.1主從復(fù)制的作用
讀寫分離:master寫,slave讀。提高服務(wù)器的讀寫負(fù)載能力
負(fù)載均衡:基于主從結(jié)構(gòu),配合讀寫分離,由slave分擔(dān)master負(fù)載,并根據(jù)需求的變化,改變slave的數(shù)量,==通過多個從節(jié)點分擔(dān)數(shù)據(jù)讀取負(fù)載,大大提高Redis服務(wù)器并發(fā)量與數(shù)據(jù)吞吐量==
故障恢復(fù):當(dāng)master出現(xiàn)問題時,由slave提供服務(wù),實現(xiàn)快速的故障恢復(fù)
數(shù)據(jù)冗余:實現(xiàn)數(shù)據(jù)熱備份,是持久化之外的一種數(shù)據(jù)冗余方式
高可用基石:基于主從復(fù)制,構(gòu)建哨兵模式與集群,實現(xiàn)Redis的高可用方案
??1.3 主從復(fù)制工作流程
主從復(fù)制過程大體可以分為3個階段
1.建立連接階段(即準(zhǔn)備階段)
2.數(shù)據(jù)同步階段
3.命令傳播階段
流程圖解:
??1.3.1 建立連接階段步驟
建立slave到master的連接,使master能夠識別slave,并保存slave端口號
步驟1:設(shè)置master的地址和端口,保存master信息
步驟2:建立socket連接
步驟3:發(fā)送ping命令(定時器任務(wù))
步驟4:身份驗證
步驟5:發(fā)送slave端口信息
至此,主從連接成功!
最終狀態(tài):
slave:
==保存master的地址與端口==
master:
==保存slave的端口==
總體:
==之間創(chuàng)建了連接的socket==
方式一:客戶端發(fā)送命令
slaveof masterip masterport
方式二:啟動服務(wù)器參數(shù)
redis-server -slaveof masterip maxterport
方式三:服務(wù)器配置(主流方式,建議使用)
slaveof masterip masterport
主從斷開連接
客戶端發(fā)送命令
slaveof no one
下面對這三種方式分別進行操作演示
我們以6739端口的服務(wù)器為master,以6380端口的服務(wù)器為slave進行操作
==進入6379服務(wù)器關(guān)掉守護進程配置與日志==
==6380服務(wù)器同樣==
==啟動master及slave==
方式一:在slave端發(fā)送連接請求
我們查看slave的日志信息
發(fā)現(xiàn)連接過程中master與slave的信息已經(jīng)同步
我們測試一下在master中set一個數(shù)據(jù)并在slave看能不能獲取
方式一成功
方式二:啟動slave時直接與master進行連接
我們測試一下在master中set一個數(shù)據(jù)并在slave看能不能獲取
方式二成功
現(xiàn)在上面這樣種方式都不是主流方式,主流的是直接在配置文件中進行設(shè)置
方式三:設(shè)置配置文件
==修改slave的配置文件,添加如箭頭所指的配置==
==添加完畢我們啟動slave,并查看信息是否同步==
方式三成功
??1.3.2 數(shù)據(jù)同步階段步驟
在slave初次連接master后,會復(fù)制master中的所有數(shù)據(jù)到slave,數(shù)據(jù)同步階段包括全量復(fù)制與部分復(fù)制
也就是將slave的數(shù)據(jù)庫狀態(tài)更新成master當(dāng)前的數(shù)據(jù)庫狀態(tài)
步驟1:請求同步數(shù)據(jù)
步驟2:創(chuàng)建RDB同步數(shù)據(jù)
步驟3:恢復(fù)RDB同步數(shù)據(jù)(以上階段為全量復(fù)制)
步驟4:請求部分同步數(shù)據(jù)(同步的是緩沖區(qū)中的指令引起的數(shù)據(jù))
步驟5:恢復(fù)部分同步數(shù)據(jù)(此過程會執(zhí)行bgrewriteaof重寫操作,恢復(fù)數(shù)據(jù),步驟4,步驟5階段為部分復(fù)制)
至此數(shù)據(jù)同步工作完成
全量復(fù)制
獲取發(fā)指令的那一刻開始原來的所有數(shù)據(jù)
部分復(fù)制
恢復(fù)進行RDB過程中對應(yīng)的所有數(shù)據(jù)
最終狀態(tài):
slave:
具有master端全部數(shù)據(jù),包含RDB過程接收的數(shù)據(jù)
master
保存slave當(dāng)前數(shù)據(jù)同步的位置
總體
之間完成了數(shù)據(jù)克隆
??1.3.2.1 數(shù)據(jù)同步階段master說明
如果master數(shù)據(jù)量巨大,數(shù)據(jù)同步階段應(yīng)避開流量高峰期,避免造成master堵塞,影響業(yè)務(wù)正常執(zhí)行
復(fù)制緩沖區(qū)大小設(shè)置不合理,會導(dǎo)致數(shù)據(jù)溢出,如進行全量復(fù)制周期太長,進行部分復(fù)制時發(fā)現(xiàn)數(shù)據(jù)已經(jīng)存在丟失的情況,必須進行第二次全量復(fù)制,致使slave陷入死循環(huán)狀態(tài)
我們可以通過配置修改緩沖區(qū)的大小
repl-backlog-size lmb
master單機內(nèi)存占用主機內(nèi)存的比例不應(yīng)過大,建議使用50%-70%的內(nèi)存,留下30%-50%的內(nèi)存用于執(zhí)行bgsave命令 和創(chuàng)建復(fù)制緩沖區(qū)
??1.3.2.2 數(shù)據(jù)同步階段slave說明
- 為避免slave進行全量復(fù)制,部分復(fù)制時服務(wù)器響應(yīng)阻塞或數(shù)據(jù)不同步,建議關(guān)閉此期間的對外服務(wù) - slave-serve-stale-data yes|no(當(dāng)主服務(wù)器掛掉時是否提供過期數(shù)據(jù)) - 數(shù)據(jù)同步階段,master發(fā)送給slave信息可以理解master是slave的一個客戶端,主動向slave發(fā)送命令 - 多個slave同時對master請求數(shù)據(jù)同步,master發(fā)送的RDB文件增多,會對帶寬造成巨大沖擊,如果master帶寬 不足,因此數(shù)據(jù)同步需要根據(jù)業(yè)務(wù)請求,適量錯峰 - slave過多時,建議調(diào)整拓?fù)浣Y(jié)構(gòu),由一主多從結(jié)構(gòu)變?yōu)闃錉罱Y(jié)構(gòu),中間的節(jié)點是master,也是slave,注意使用 樹狀結(jié)構(gòu)時,由于層級深度,導(dǎo)致深度越高的slave與最頂層master間數(shù)據(jù)同步延遲較大,數(shù)據(jù)一致性變差, 應(yīng)謹(jǐn)慎選擇
??1.3.2.3 命令傳播階段步驟
當(dāng)master數(shù)據(jù)庫狀態(tài)被修改后,導(dǎo)致主從服務(wù)器數(shù)據(jù)庫狀態(tài)不一致,此時需要讓主從數(shù)據(jù)同步到一致的狀態(tài),同步的動作稱為命令傳播
一句話就是實時保持主從之間的數(shù)據(jù)同步
命令傳播階段的部分復(fù)制
命令傳播階段出現(xiàn)了斷網(wǎng)情況
網(wǎng)絡(luò)閃斷閃連 忽略
短時間網(wǎng)絡(luò)中斷 部分復(fù)制
長時間網(wǎng)絡(luò)中斷 全量復(fù)制
部分復(fù)制的三個核心要素
服務(wù)器的運行id(run id)
主服務(wù)器的復(fù)制偏移量積壓緩沖區(qū)
主從服務(wù)器的復(fù)制偏移量
下面我們對這三個核心要素分別進行敘述
??1.3.2.4 服務(wù)器運行ID(runid)
概念:服務(wù)器運行ID是每一臺服務(wù)器每次運行的身份識別碼,一臺服務(wù)器多次運行可以生成多個運行id
==組成:運行id由40位字符組成,是一個隨機的十六進制字符==
==作用:運行id被用于在服務(wù)器間進行傳輸,識別身份==
如果想兩次操作均對同一臺服務(wù)器進行,必須每次操作攜帶對應(yīng)的運行id,用于對方識別
==實現(xiàn)方式:==
運行id在每臺服務(wù)器啟動時自動生成的,master在首次連接slave時,會將自己的運行ID發(fā)送給slave,slave保存此ID,通過info Server命令可以查看節(jié)點的runid
我們輸入info server命令查看服務(wù)器運行id
??1.3.2.5 主服務(wù)器的復(fù)制偏移量積壓緩沖區(qū)
概念:復(fù)制緩沖區(qū),又名復(fù)制積壓緩沖區(qū),是一個先進先出(FIFO)的隊列,用于存儲服務(wù)器執(zhí)行過的命令,每次傳播命令,master都會將傳播的命令記錄下來毛病存儲在復(fù)制緩沖區(qū)
復(fù)制緩沖區(qū)默認(rèn)數(shù)據(jù)存儲空間大小是1M,由于存儲空間大小是固定的,當(dāng)入隊元素的數(shù)量大于隊列長度時,最先入隊的元素會被彈出,而新元素會被放入隊列
==由來:每臺服務(wù)器啟動時,如果開啟有AOF或被連接為master節(jié)點,即創(chuàng)建復(fù)制緩沖區(qū)==
==作用:用于保存master收到的所有指令(僅影響數(shù)據(jù)變更的指令,例如set,select)==
==數(shù)據(jù)來源:當(dāng)master收到主用戶端的指令時,除了將指令執(zhí)行,會將該指令存儲到緩沖區(qū)中==
復(fù)制緩沖區(qū)內(nèi)部工作原理
當(dāng)master接到一個指令,例如set name itheima,它會把指令拆解開放進復(fù)制緩沖區(qū),指令在緩沖區(qū)的形式為
為了區(qū)分各個字符,每個字符都有自己的編號
==所以復(fù)制緩沖區(qū)由兩部分組成==
偏移量
字節(jié)值
==工作原理==
通過offset區(qū)分不同的slave當(dāng)前數(shù)據(jù)傳播的差異
??1.3.2.6 主從服務(wù)器的復(fù)制偏移量(offset)
概念:一個數(shù)字,描述復(fù)制緩沖區(qū)中的指令字節(jié)位置
==分類:==
master復(fù)制偏移量:記錄發(fā)送給所有slave的指令字節(jié)對應(yīng)的位置(多個)
slave復(fù)制偏移量:記錄slave接收master發(fā)送過來的指令字節(jié)對應(yīng)的位置(一個)
==數(shù)據(jù)來源==
master端:發(fā)送一次記錄一次
slave端:接受一次記錄一次
==作用:同步信息,對比master與slave的差異,當(dāng)slave斷線后,恢復(fù)數(shù)據(jù)使用==
??1.3.3 數(shù)據(jù)同步+命令傳播階段步驟
這部分比較復(fù)雜,大家可以看著流程圖和我的敘述進行理解
現(xiàn)在是數(shù)據(jù)同步階段:
首先進行全量復(fù)制
slave向master發(fā)送指令,請求數(shù)據(jù)同步,執(zhí)行psync2
master收到來自slave的指令,執(zhí)行bgsave生成RDB文件,記錄當(dāng)前的復(fù)制偏移量offset,接收的offset值為-1
因為接收到offset=-1,故master采用全量同步,將會把所有信息都發(fā)送過去,順帶自己的runid與offset,發(fā)送的 指令為+FULLRESYNC runid offset
slave收到+FULLRESYNC,保存master的runid和offset,清空當(dāng)前全部數(shù)據(jù),通過socket接收RDB文件,恢復(fù)RDB 數(shù)據(jù),至此全量復(fù)制結(jié)束
接下來進行部分復(fù)制
期間master接收客戶端命令后(這里的期間指全量復(fù)制期間),offset發(fā)生了變化,全量復(fù)制之后slave會發(fā)送指令 請求master將剩余的信息進行發(fā)送,發(fā)送的命令是psync2 runid offset
接下來進入命令傳播階段:
==master接收到psync2 指令后,==
先判斷runid是否匹配(不匹配證明不是一臺機器),然后判定offset是否在復(fù)制緩沖區(qū)中,如果runid或offset有一個不滿足,就會再次執(zhí)行全量復(fù)制
如果runid或offset檢驗通過
slave發(fā)送的offset與master緩沖區(qū)中的offset相同,則忽略,證明全量復(fù)制期間沒有其他數(shù)據(jù)進入緩沖區(qū)
slave發(fā)送的offset與master緩沖區(qū)中的offset不相同,則發(fā)送+CONTINUE offset指令,通過socket發(fā)送復(fù)制緩沖區(qū)中slave發(fā)送的offset到master本身的offset的數(shù)據(jù)
slave收到master發(fā)送的+COUNTINUE指令,保存master的offset,接收信息后,執(zhí)行bgrewriteaof對部分復(fù)制的指令進行重寫,恢復(fù)數(shù)據(jù),隨后因為心跳機制的原因,slave周期性的向master發(fā)送請求以匯報自己的offset,獲取最新的指令變更
??1.3.3.1 心跳機制
傳播階段master與slave之間的聯(lián)系是反復(fù)進行的,而這種反復(fù)進行的機制是由心跳包來控制的
==進入命令傳播階段,master與slave間需要進行信息交換,使用心跳機制進行維護,實現(xiàn)雙方連接保持在線==
master心跳
指令:PING
周期:由repl-ping-slave-period決定,默認(rèn)10秒
作用:判斷slave是否在線
查詢:INFO replication
獲取slave最后一次連接時間間隔,lag項維持在0或1視為正常
指令:PING
周期:由repl-ping-slave-period決定,默認(rèn)10秒
作用:判斷slave是否在線
查詢:INFO replication
獲取slave最后一次連接時間間隔,lag項維持在0或1視為正常
slave心跳任務(wù)
指令:REPLCONF ACK[offset]
周期:1秒
作用1:匯報slave自己的復(fù)制偏移量,獲取最新的數(shù)據(jù)變更指令
作用2:判斷master是否在線
指令:REPLCONF ACK[offset]
周期:1秒
作用1:匯報slave自己的復(fù)制偏移量,獲取最新的數(shù)據(jù)變更指令
作用2:判斷master是否在線
==如果lag不為1或者0,證明可能在ping某些時候可能丟過==
心跳階段注意事項
==當(dāng)slave多數(shù)掉線,或延遲過高時,master為保障數(shù)據(jù)穩(wěn)定性,將拒絕所有信息同步操作==
min-slaves-to-write 2
min-slaves-max-lag 8
slave數(shù)量少于2,或者所有slave的延遲都大于等于8秒時,強制關(guān)閉master寫功能,停止數(shù)據(jù)同步
==slave數(shù)量是由slave發(fā)送REPLCONF ACK命令做確認(rèn)==
==slave延遲是由slave發(fā)送REPLCONF ACK命令做確認(rèn)==
14 主從復(fù)制工作流程完整圖示
Java Redis
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。