<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          讀者訴苦:Redis 宕機(jī),數(shù)據(jù)丟了,老板要辭退我

          共 3162字,需瀏覽 7分鐘

           ·

          2021-12-05 09:11

          最近跟一位讀者聊天,小哥非常郁悶,公司的Redis宕機(jī)了,線上業(yè)務(wù)受到了影響,老板非常憤怒,小哥擔(dān)心會(huì)不會(huì)被辭退!

          我也很好奇,問(wèn)小哥Redis主節(jié)點(diǎn)掛了,還有備機(jī)啊。怎么會(huì)影響到業(yè)務(wù)呢?

          小哥說(shuō),他們的系統(tǒng)架構(gòu)只部署一個(gè)Redis單實(shí)例。節(jié)點(diǎn)掛了,數(shù)據(jù)也丟了。

          125d9128d40426b2df8632ec4dfdc47d.webp


          好吧,既然提到了備份,那今天,我們就來(lái)聊下 Redis的主從同步

          首先,什么是主從?

          主從也稱主從集群,部署了多個(gè)Redis實(shí)例,如下圖所示:

          e04deb3065f85ce21d69fcbbaaa3adae.webp


          其中,每個(gè)實(shí)例又有自己的專屬職責(zé)

          • 主庫(kù):負(fù)責(zé)接收讀操作、寫(xiě)操作

          • 從庫(kù):定期同步主庫(kù)的數(shù)據(jù),對(duì)外提供讀操作

          好奇的寶寶可能要問(wèn)了,為什么從庫(kù)不能寫(xiě)?

          考慮到數(shù)據(jù)合并的復(fù)雜性,假如一個(gè)key,多次更新,每次操作在不同的實(shí)例上執(zhí)行,為了保證數(shù)據(jù)的全局一致性,勢(shì)必要加全局鎖,保證在集群范圍上串行化操作且在最新的數(shù)據(jù)基礎(chǔ)上更新,這個(gè)成本還是很大的。

          為了降低系統(tǒng)復(fù)雜度,節(jié)約成本。主從同步架構(gòu)方案一般都是在主庫(kù)上寫(xiě),在從庫(kù)上讀。分工明確,職責(zé)單一。

          可能有同學(xué)會(huì)提到 Redis Cluster 模式,這個(gè)是另一種設(shè)計(jì)方案。采用水平分割方式,通過(guò)CRC16(key)算法,將數(shù)據(jù)拆分到若干個(gè)實(shí)例中,每個(gè)實(shí)例只對(duì)自己負(fù)責(zé)的槽位的數(shù)據(jù)讀、寫(xiě),從而分?jǐn)偧簤毫?。這個(gè)屬于另一種玩法,本期就不深入展開(kāi)了。

          為了保證數(shù)據(jù)不丟失,Redis提供兩種數(shù)據(jù)同步方式

          1、RDB,全量數(shù)據(jù)同步

          2、AOF,增量數(shù)據(jù)同步,回放日志

          這兩者有什么區(qū)別?

          什么時(shí)候采用 RDB ? 什么時(shí)候采用 AOF ?

          接下來(lái),我們逐步分析展開(kāi)

          建立主從關(guān)系

          首先,啟動(dòng)兩個(gè)redis 實(shí)例,IP地址分別是?192.168.0.1?和?192.168.0.2?,開(kāi)始時(shí),他們之間沒(méi)有任何關(guān)聯(lián)。

          我們通過(guò)終端命令,登錄?192.168.0.2?機(jī)器,執(zhí)行命令

          replicaof?192.168.0.1?6379

          此時(shí)?192.168.0.2?實(shí)例就成了 ?192.168.0.1??的從庫(kù)。

          b832e712e127016a70af478a25ec3f7d.webp


          當(dāng)主從實(shí)例建立好關(guān)聯(lián)后,接下來(lái),就開(kāi)始進(jìn)入數(shù)據(jù)同步環(huán)節(jié)

          主從同步

          212d7b19a37fcbb0d4463f11f7fc1fe4.webp


          主從庫(kù)數(shù)據(jù)同步分為三步:

          1、第一步

          從庫(kù)(192.1768.0.2)向主庫(kù)(192.168.0.1)發(fā)送 psync 命令,帶了兩個(gè)參數(shù)(主庫(kù)的runID和同步進(jìn)度offset)。

          • 第一次建立連接時(shí),從庫(kù)并不知道主庫(kù)的runID,所以會(huì)設(shè)置為 ?。offset = -1,表示第一次復(fù)制。

          說(shuō)明:每個(gè) Redis 實(shí)例初始啟動(dòng)時(shí),會(huì)自動(dòng)生成一個(gè)隨機(jī)ID,用來(lái)標(biāo)識(shí)當(dāng)前實(shí)例。

          主庫(kù)接收到psync請(qǐng)求后,會(huì)響應(yīng) FULLRESYNC ,帶有兩個(gè)參數(shù)(主庫(kù)的runID和同步進(jìn)度offset)

          說(shuō)明:FULLRESYNC 表示采用全量復(fù)制

          2、第二步

          • 主庫(kù)fork子進(jìn)程,執(zhí)行?bgsave?命令,生成 RDB 文件

          • 主庫(kù)將 RDB 文件發(fā)給從庫(kù)

          • 從庫(kù)接到響應(yīng)后,會(huì)先清空當(dāng)前數(shù)據(jù)庫(kù),然后加載 RDB 文件

          說(shuō)明:主庫(kù)在生成RDB文件時(shí),主線程是阻塞的,對(duì)外不提供服務(wù)。一旦RDB文件生成,在數(shù)據(jù)同步過(guò)程中,不受影響,主庫(kù)可以對(duì)外服務(wù)。后續(xù)的寫(xiě)命令數(shù)據(jù)會(huì)存到 replication buffer

          3、第三步

          主庫(kù)將增量寫(xiě)命令發(fā)送給從庫(kù),從庫(kù)放映式執(zhí)行這些命令,從而實(shí)現(xiàn)了主從同步。

          到這里,主從的核心邏輯基本講完了。

          但生產(chǎn)環(huán)境,通常是一主多從,每個(gè)從庫(kù)初始同步時(shí),都要主庫(kù)生成RDB文件,顯然開(kāi)銷很大。有什么解決方案?

          一主多從,主庫(kù)減壓

          當(dāng)從節(jié)點(diǎn)存在多個(gè)時(shí),主庫(kù)的壓力顯著增加,具體體現(xiàn)在兩個(gè)方面:

          1、當(dāng)從庫(kù)同步主庫(kù)時(shí),要fork子進(jìn)程,有多少個(gè)從節(jié)點(diǎn),就要fork多少個(gè)子進(jìn)程,每個(gè)子進(jìn)程都要生成RDB。導(dǎo)致主庫(kù)系統(tǒng)壓力過(guò)大

          2、生成的RDB要同步給從庫(kù),占用網(wǎng)絡(luò)帶寬

          基于上面的困境,演化出新的模式,“主--從--從”模式,具體玩法如下圖:

          502c6e50059512d7f2eda44103dca94f.webp


          現(xiàn)有雖然有四個(gè)從庫(kù),但直接跟主庫(kù)關(guān)聯(lián)同步數(shù)據(jù)的只有?192.168.0.2?和?192.168.0.3?兩個(gè)實(shí)例,大大減輕了主庫(kù)的壓力。

          任何事情都不是一成不變的,網(wǎng)絡(luò)傳輸就存在很大的風(fēng)險(xiǎn),網(wǎng)絡(luò)閃斷了怎么辦?對(duì)主從同步有什么影響?

          網(wǎng)絡(luò)閃斷對(duì)主從同步的影響

          我們知道主從實(shí)例間同步數(shù)據(jù)主要有兩種方式:全量同步?和?增量同步?。?全量同步就是同步RDB文件,那增量同步是如何實(shí)現(xiàn)的呢?

          這里要引入一個(gè)緩沖區(qū),repl_backlog_buffer,它是一個(gè)環(huán)形設(shè)計(jì),增量命令都是先存入這個(gè)緩沖區(qū)的。主庫(kù)有生產(chǎn)位移,稱之為master_repl_offset?。從庫(kù)有拉取位移,稱之為slave_repl_offset

          e4c803c5e9e9d65896254a21b3a56c26.webp


          正常情況下,master_repl_offset?和?slave_repl_offset?大小是接近的,也就是說(shuō)主從庫(kù)兩者間的數(shù)據(jù)近乎同步。

          每次同步數(shù)據(jù)時(shí),從庫(kù)向主庫(kù)發(fā)送 psync 命令,把自己的?slave_repl_offset?發(fā)給主庫(kù),主庫(kù)基于此偏移位置,向從庫(kù)發(fā)送增量數(shù)據(jù)。這個(gè)很容易理解。

          是不是就萬(wàn)無(wú)一失了呢?

          由于采用了環(huán)形結(jié)構(gòu),如果主庫(kù)的生產(chǎn)速度比從庫(kù)的拉取速度快很多時(shí),就會(huì)出現(xiàn)套圈現(xiàn)象。

          為什么采用環(huán)形?主要為了讓空間循環(huán)使用,像市場(chǎng)的行車記錄儀、監(jiān)控設(shè)備等,大多都是采用循環(huán)覆蓋式存儲(chǔ)。如果空間滿了,將之前最老的數(shù)據(jù)覆蓋掉。雖然可能丟失了部分?jǐn)?shù)據(jù),但是性價(jià)比高。

          回到上面的問(wèn)題,如果被套圈了怎么辦?

          f09253dd2956a59ac3e00cd123ee438f.webp


          如上圖所示,從庫(kù) psync 命令,請(qǐng)求的offset 是 4,但是主節(jié)點(diǎn)已經(jīng)生產(chǎn)到了 15 ,將之前的 1、2、3、4、5 全部覆蓋掉了。

          這下傻眼了,需要同步的數(shù)據(jù)被覆蓋了,惹大麻煩了....

          69702ea3d11c5af0f96eef73debbd903.webp

          有兩個(gè)解決方案:

          1、調(diào)大?repl_backlog_buffer?緩沖區(qū)大小,該值是由?repl_backlog_size參數(shù)控制

          緩沖空間大小 = 主庫(kù)寫(xiě)入速度 * 操作大小 - 從庫(kù)拉取速度 * 操作大小

          這是我們能主觀控制的。比如擔(dān)心大促帶來(lái)的流量高峰,可以將這個(gè)值調(diào)大2倍、3倍、4倍,大家可以根據(jù)自己的業(yè)務(wù)情況自由設(shè)置。

          2、還有一種方式是Redis 自身提供的解決方案。

          此時(shí)會(huì)觸發(fā)全量復(fù)制,跟第一次建立主從關(guān)系同步數(shù)據(jù)一樣。通過(guò)全量方式,一次性彌補(bǔ)主從間的數(shù)據(jù)大缺口。

          主節(jié)點(diǎn)掛了怎么辦

          如果只是傳統(tǒng)意義上的主從模式,主節(jié)點(diǎn)掛了,通常要手工完成切換。

          效率不言而喻了,尤其是線上生產(chǎn)系統(tǒng),根本沒(méi)法接受這種方案。

          這時(shí)候,要引入哨兵機(jī)制了,哨兵機(jī)制可以實(shí)現(xiàn)主從庫(kù)的自動(dòng)切換,有效解決了故障轉(zhuǎn)移。整個(gè)過(guò)程分為三個(gè)階段:監(jiān)控、選主、通知。

          1、監(jiān)控。哨兵進(jìn)程會(huì)周期給所有的主庫(kù)、從庫(kù)發(fā)送 PING 命令,檢測(cè)機(jī)器是否處于服務(wù)狀態(tài)。如果沒(méi)有在設(shè)置時(shí)間內(nèi)收到回復(fù),則判定為下線。

          當(dāng)然,網(wǎng)絡(luò)抖動(dòng),也會(huì)存在誤判可能,如何避免?

          引入哨兵集群,多個(gè)哨兵實(shí)例一起判斷,降低誤判率。判斷標(biāo)準(zhǔn)就是,假如 n 個(gè)哨兵實(shí)例,至少有 n/2+1 個(gè)判定一致,才可以定論。

          2、選主。主要是看各個(gè)節(jié)點(diǎn)的打分情況,打分規(guī)則分為?從庫(kù)優(yōu)先級(jí)、從庫(kù)復(fù)制進(jìn)度從庫(kù)ID號(hào)。只要有一輪,某個(gè)從庫(kù)得分最高,則選舉它為主庫(kù)。

          • 從庫(kù)優(yōu)先級(jí),主要是考慮到不同的機(jī)器可能配置不一樣,配置高的機(jī)器,優(yōu)先級(jí)高一些,通過(guò)slave-priority?來(lái)配置

          • 從庫(kù)復(fù)制進(jìn)度,主要是看slave_repl_offset?的值大小,值越大表示已經(jīng)同步的數(shù)據(jù)越多,得分越高。

          • 從庫(kù)ID號(hào),每個(gè)Redis 實(shí)例啟動(dòng)時(shí),都會(huì)生成一個(gè) ID,在優(yōu)先級(jí)和復(fù)制進(jìn)度相同的條件下,ID號(hào)最小的從庫(kù)分?jǐn)?shù)最高,會(huì)被選為新主庫(kù)。

          3、通知。把選舉后的新主庫(kù)發(fā)送給所有節(jié)點(diǎn),讓所有的從庫(kù)執(zhí)行?replicaof?命令,和master建立主從關(guān)系、數(shù)據(jù)同步復(fù)制。另外,也會(huì)把最新的主庫(kù)信息同步給客戶端。


          有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號(hào)


          好文章,我在看??

          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字字幕在线中文乱码 | 亚洲黄视频在线播放网址 | 精品视频在线观看免费 | 国产成人69免费看 | 日韩特级视频 |