自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

跟隨杠精的視角一起來了解Redis的主從復(fù)制

存儲(chǔ) 存儲(chǔ)軟件 Redis
雖然說單機(jī)的Redis性能很好,也有完備的持久化機(jī)制,那如果你的業(yè)務(wù)體量真的很大,超過了單機(jī)能夠承載的上限了怎么辦?不做任何處理的話Redis掛了怎么辦?

 [[354948]]

本文轉(zhuǎn)載自微信公眾號「SH的全棧筆記」,作者SH 。轉(zhuǎn)載本文請聯(lián)系SH的全棧筆記公眾號。 

雖然說單機(jī)的Redis性能很好,也有完備的持久化機(jī)制,那如果你的業(yè)務(wù)體量真的很大,超過了單機(jī)能夠承載的上限了怎么辦?不做任何處理的話Redis掛了怎么辦?帶著這個(gè)問題開始我們今天的主題-「Redis高可用」,由于篇幅原因,本章就只聊聊主從復(fù)制。

為啥要先從主從復(fù)制開始聊,是因?yàn)椤钢鲝膹?fù)制」可以說是整個(gè)Redis高可用實(shí)現(xiàn)的基石,你可以先有這么一個(gè)概念,至于具體為什么是基石,這個(gè)后面聊到Sentinel和Redis集群的時(shí)候會(huì)說到。

首先我們需要知道,對于我們開發(fā)人員來說,為什么需要「主從架構(gòu)」?一個(gè)Redis實(shí)例難道不行嗎?

其實(shí)除了開篇提到的負(fù)載超過了Redis單機(jī)能夠處理的上限,還有一種情況Redis也無法保證自身的高可用性。那就是即便Redis能夠扛住所有流量,但是如果這個(gè)Redis進(jìn)程所在的機(jī)器掛了呢?請求會(huì)直接調(diào)轉(zhuǎn)槍口,大量的流量會(huì)瞬間把你的DB打掛,然后你就可以背個(gè)P0,打包回家了。

而且,假設(shè)你對Redis的需求真的超過了單機(jī)的容量,你怎么辦?搞多臺(tái)獨(dú)立的Redis實(shí)例嗎?那如果用戶緩存的數(shù)據(jù)這一次存在了實(shí)例一,下一次如果用戶又訪問到了實(shí)例二,難道又要去走一遍DB嗎?除非你能夠維護(hù)好用戶和Redis實(shí)例的對應(yīng)關(guān)系(但是通常這樣的邏輯比較復(fù)雜),否則部署多個(gè)Redis實(shí)例也就失去了它的意義,沒有辦法做到橫向擴(kuò)展了。

那換成主從架構(gòu)就能解決這個(gè)問題嗎?

我們可以從一個(gè)圖來直觀的了解一下。

Redis主從復(fù)制

在主從同步中,我們將節(jié)點(diǎn)的角色劃分為master和slave,形成「一主多從」。slave對外提供讀操作,而master負(fù)責(zé)寫操作,形成一個(gè)讀寫分離的架構(gòu),這樣一來就能夠承載更多的業(yè)務(wù)請求。

在多數(shù)的業(yè)務(wù)場景下,對于Redis的「讀操作」都要多于「寫操作」,所以當(dāng)讀請求量特別大的時(shí)候,我們可以通過增加slave節(jié)點(diǎn)來使Redis扛住更多的流量。

你這不行啊老弟,你往master寫數(shù)據(jù),那我要是連接到slave上去了,不就拿不到之前的數(shù)據(jù)了?

我這個(gè)小標(biāo)題的不是寫了嗎?「主從復(fù)制」,slave會(huì)按照某種策略從master同步數(shù)據(jù)。Redis中我們可以通過slaveof命令讓一個(gè)Redis實(shí)例去復(fù)制(replicate)另外一臺(tái)Redis的狀態(tài)。被復(fù)制的Redis實(shí)例就是master節(jié)點(diǎn),而執(zhí)行slaveof命令的機(jī)器就是slave節(jié)點(diǎn)。

Redis的主從復(fù)制分為兩個(gè)步驟,分別是「同步」和「命令傳播」。

「同步操作」用于將Master節(jié)點(diǎn)內(nèi)存狀態(tài)復(fù)制給Slave節(jié)點(diǎn),而「命令傳播」則是在同步時(shí),客戶端又執(zhí)行了一些「寫」操作改變了服務(wù)器的狀態(tài),此時(shí)master節(jié)點(diǎn)的狀態(tài)與同步操作執(zhí)行的時(shí)候不一致了,所以需要命令傳播來使master和slave狀態(tài)重新一致。

同步的大致的流程如下:

  • slave節(jié)點(diǎn)向master節(jié)點(diǎn)發(fā)送sync命令
  • master收到sync命令之后會(huì)執(zhí)行bgsave命令,Redis會(huì)fork出一個(gè)子進(jìn)程在后臺(tái)生成RDB文件,同時(shí)將同步過程中的寫命令記錄到緩沖區(qū)中
  • 文件生成后,master會(huì)把RDB文件發(fā)送給slave,從服務(wù)器接收到RDB文件會(huì)將其載入內(nèi)存
  • 然后master將記錄在緩沖區(qū)的所有寫命令發(fā)送給slave,slave對這些命令進(jìn)行「重放」,將其數(shù)據(jù)庫的狀態(tài)更新至和master一致

為了讓大家更加清晰的認(rèn)識(shí)到這個(gè)過程,我們通過圖再來了解一下。

Redis主從復(fù)制

那如果同步完了之后slave又掛了咋辦?slave重啟之后很可能就又跟maste不一致了?

的確是這樣,這就涉及到一個(gè)名詞叫「斷點(diǎn)續(xù)傳」了。上面討論的是slave第一次連接到master,會(huì)執(zhí)行「全量復(fù)制」,而針對上面這種情況,Redis新老版本處理方式不一樣。

Redis2.8之前,當(dāng)主從完成了同步之后,slave如果斷線重連,向master發(fā)送sync命令,master會(huì)將全量的數(shù)據(jù)再次同給slave。

但是我們會(huì)發(fā)現(xiàn)一個(gè)問題,就是大部分?jǐn)?shù)據(jù)都是有序的,再次全量同步顯得沒有必要。而在 Redis2.8之后,為了解決這個(gè)問題,便使用了psync命令來代替sync。

簡單來說psync命令就是將slave斷線期間master接收到的寫命令全部發(fā)送給slave,slave重放之后狀態(tài)便與master一致了。

呵呵,就這?那你知道psync具體怎么實(shí)現(xiàn)的嗎?還是說就只會(huì)用用?

psync的實(shí)現(xiàn)依賴于主從雙方共同維護(hù)的offset偏移量。

每次master向slave進(jìn)行「命令傳播」,傳播了多少個(gè)字節(jié)的數(shù)據(jù),就將自己的offset加上傳播的字節(jié)數(shù)。而slave每次收到多少字節(jié)的數(shù)據(jù),也會(huì)同樣的更新自己的offset。

基于offset,只需要簡單的比對就知道當(dāng)前主從的狀態(tài)是否是一致的了,然后基于offset,將對應(yīng)偏移量所對應(yīng)的指令傳播給slave重放即可。所以即使同步的時(shí)候slave掛掉了,基于offset,也能達(dá)到斷點(diǎn)續(xù)傳的效果。

不是吧不是吧,那master也掛了呢?你slave重新啟動(dòng)之后master的數(shù)據(jù)也更新了,按照你的說法,這兩永遠(yuǎn)不可能達(dá)到數(shù)據(jù)一致了

這個(gè)問題Redis的確也有想到,實(shí)際上除了offset之外,slave斷線重連之后還會(huì)帶上上一個(gè)master的實(shí)例的runid,每個(gè)服務(wù)實(shí)例都有自己的唯一的runid,只要Redis服務(wù)重啟,其runid就會(huì)發(fā)生改變。

master收到這個(gè)runid之后會(huì)判斷是否與自己當(dāng)前的runid一致,如果一致說明斷線之前還是與自己建立的連接,而如果不一致就說明slave斷線期間,master也發(fā)生了宕機(jī),此時(shí)就需要將數(shù)據(jù)「全量同步」給slave了。

redis-runid

就算你能解決這個(gè)問題,但是你就維護(hù)了一個(gè)偏移量,偏移量對應(yīng)的命令從哪兒來?天上掉下來嗎?我哪兒知道這些命令是啥?

的確,我們需要通過這個(gè)offset去拿到真正需要的數(shù)據(jù)—也就是指令,而Redis是通過「復(fù)制積壓緩沖區(qū)」來實(shí)現(xiàn)的。

名字高大上,實(shí)際上就是一隊(duì)列。就跟什么遞歸、輪詢、透傳一樣,聽著高大上,實(shí)際上簡單的一匹。言歸正傳,復(fù)制積壓緩沖區(qū)的默認(rèn)大小為1M,Redis在進(jìn)行「命令傳播」時(shí),除了將寫命令發(fā)送給slave,還會(huì)將命令寫到「復(fù)制積壓緩沖區(qū)」內(nèi),并和當(dāng)前的offset關(guān)聯(lián)起來。這樣一來就能夠通過offset獲取到對應(yīng)的指令了。

redis-backlog

但是由于緩沖區(qū)的大小有限,如果slave的斷線時(shí)間太久,復(fù)制積壓緩沖區(qū)內(nèi)早些時(shí)候的指令就已經(jīng)被新的指令覆蓋掉了,此處可以理解為一個(gè)隊(duì)列,早些時(shí)候入隊(duì)的元素已經(jīng)被出隊(duì)了。

由于沒有相對應(yīng)的offset了,也就無法獲取指令數(shù)據(jù),此時(shí)Redis就會(huì)進(jìn)行「全量同步」。當(dāng)然,如果offset還存在于復(fù)制積壓緩沖區(qū)中,則按照對應(yīng)的offset進(jìn)行「部分同步」。

基于以上的全量、增量的主從復(fù)制,能夠在master出現(xiàn)故障的情況下,進(jìn)行主從的切換,保證服務(wù)的正常運(yùn)行。除此之外還能解決異常情況下數(shù)據(jù)丟失的問題?;谧x寫分離的策略還能夠提高整個(gè)Redis服務(wù)的并發(fā)量。

可別吹了,你說的這個(gè)什么「主從復(fù)制」就沒啥缺點(diǎn)嗎?

其實(shí)是有的,例如剛剛提到的主從的切換,如果不用現(xiàn)成的「HA」框架,這個(gè)過程需要程序員自己手動(dòng)的完成,同時(shí)通知服務(wù)調(diào)用方Redis的IP發(fā)生了變化,這個(gè)過程可以說是十分的復(fù)雜,甚至還可能涉及到代碼配置的改動(dòng)。而且之前的slave復(fù)制的可都是掛掉的master,還得去slave上更改其復(fù)制的主庫,就更加復(fù)雜了。

除此之外,雖然實(shí)現(xiàn)了讀寫分離,但是由于是「一主多從」的架構(gòu),集群的「讀請求」可以擴(kuò)展,但是「寫請求」的并發(fā)是有上限的,那就是master能夠扛住的上限,這個(gè)沒有辦法擴(kuò)展。

 

責(zé)任編輯:武曉燕 來源: SH的全棧筆記
相關(guān)推薦

2020-12-31 23:31:13

網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊漏洞

2023-09-24 14:32:15

2021-01-12 09:03:17

MySQL復(fù)制半同步

2022-05-07 07:43:07

Redis存儲(chǔ)系統(tǒng)數(shù)據(jù)庫

2023-02-27 07:33:14

MySQL數(shù)據(jù)庫服務(wù)器

2023-03-15 08:30:37

2023-12-25 08:02:09

2024-01-24 07:24:18

物聯(lián)網(wǎng)通信協(xié)議IOT

2023-03-19 11:53:27

2023-03-19 22:38:12

邏輯復(fù)制PostgreSQL

2018-07-06 09:58:38

Redis高可用主從復(fù)制

2021-01-12 08:03:19

Redis數(shù)據(jù)系統(tǒng)

2023-07-03 08:57:45

Master服務(wù)TCP

2021-01-11 14:45:35

Redis數(shù)據(jù)庫命令

2017-09-05 16:00:49

MySQL主從復(fù)制備份

2017-10-11 15:40:20

MySQL主從復(fù)制拓?fù)浣Y(jié)構(gòu)

2025-01-15 15:47:36

2020-12-02 11:00:59

Redis多線程數(shù)據(jù)庫

2021-09-09 08:47:52

Dependency 安全漏洞工具

2021-10-27 07:15:37

SpringAOP編程(
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號