欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis腦裂導(dǎo)致數(shù)據(jù)丟失的解決

 更新時(shí)間:2023年01月25日 10:28:46   作者:JavaEdge.  
本文主要介紹了Redis腦裂導(dǎo)致數(shù)據(jù)丟失的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 案例

主從集群有1個(gè)主庫(kù)、5個(gè)從庫(kù)和3個(gè)哨兵實(shí)例,突然發(fā)現(xiàn)客戶端發(fā)送的一些數(shù)據(jù)丟了,直接影響業(yè)務(wù)層數(shù)據(jù)可靠性。

最終排查發(fā)現(xiàn)是主從集群中的腦裂問(wèn)題導(dǎo)致:主從集群中,同時(shí)有兩個(gè)主節(jié)點(diǎn)都能接收寫請(qǐng)求。

影響

客戶端不知道應(yīng)往哪個(gè)主節(jié)點(diǎn)寫數(shù)據(jù),導(dǎo)致不同客戶端往不同主節(jié)點(diǎn)寫數(shù)據(jù)。嚴(yán)重的,腦裂會(huì)進(jìn)一步導(dǎo)致數(shù)據(jù)丟失。

2 腦裂原因

最初問(wèn)題:在主從集群中,客戶端發(fā)送的數(shù)據(jù)丟失了。

2.1 為什么數(shù)據(jù)會(huì)丟失?

① 確認(rèn)數(shù)據(jù)同步是否異常

在主從集群中發(fā)生數(shù)據(jù)丟失,最常見(jiàn)原因:主庫(kù)數(shù)據(jù)還沒(méi)同步到從庫(kù),結(jié)果主庫(kù)故障,等從庫(kù)升級(jí)為主庫(kù)后,未同步數(shù)據(jù)丟了。

新寫入主庫(kù)的數(shù)據(jù)a=1、b=3,因?yàn)樵谥鲙?kù)故障前未同步到從庫(kù),失了。

這種數(shù)據(jù)丟失case,可直接對(duì)比主從庫(kù)的復(fù)制進(jìn)度差值:

master_repl_offset - slave_repl_offset

若從庫(kù)的slave_repl_offset < 原主庫(kù)的master_repl_offset,則可認(rèn)定數(shù)據(jù)丟失是由數(shù)據(jù)同步未完成導(dǎo)致。

部署主從集群時(shí),也監(jiān)測(cè)了:

  • 主庫(kù)的master_repl_offset
  • 從庫(kù)上的slave_repl_offset

但發(fā)現(xiàn)數(shù)據(jù)丟失后,檢查了新主庫(kù)升級(jí)前的slave_repl_offset,以及原主庫(kù)的master_repl_offset,一致,說(shuō)明該升級(jí)為新主庫(kù)的從庫(kù),在升級(jí)時(shí)已和原主庫(kù)的數(shù)據(jù)一致。

那為啥還會(huì)出現(xiàn)客戶端發(fā)的數(shù)據(jù)丟失?

所有數(shù)據(jù)操作都是從客戶端發(fā)給Redis實(shí)例,是否可從客戶端操作日志發(fā)現(xiàn)問(wèn)題?

② 排查客戶端的操作日志,發(fā)現(xiàn)腦裂現(xiàn)象

發(fā)現(xiàn)主從切換后的一段時(shí)間,有個(gè)客戶端仍在和原主庫(kù)通信,并沒(méi)有和升級(jí)的新主庫(kù)交互。

相當(dāng)于主從集群中同時(shí)有兩個(gè)主庫(kù)。據(jù)此,想到主從集群故障的腦裂。但不同客戶端給兩個(gè)主庫(kù)發(fā)送數(shù)據(jù)寫操作,應(yīng)只會(huì)導(dǎo)致新數(shù)據(jù)會(huì)分布在不同主庫(kù),而不會(huì)造成數(shù)據(jù)丟失。

思路又?jǐn)嗔恕?ldquo;從原理出發(fā)是追本溯源的好方法”。腦裂是發(fā)生在主從切換過(guò)程,猜測(cè)是漏掉了主從集群切換過(guò)程中的某環(huán)節(jié),所以,聚焦主從切換的執(zhí)行過(guò)程。

③ 發(fā)現(xiàn)是原主庫(kù)假故障導(dǎo)致的腦裂

我們采用哨兵機(jī)制進(jìn)行主從切換的,主從切換發(fā)生時(shí),一定有超過(guò)預(yù)設(shè)數(shù)量(quorum配置項(xiàng))的哨兵實(shí)例和主庫(kù)的心跳都超時(shí),才會(huì)把主庫(kù)判斷為客觀下線,然后,哨兵開(kāi)始執(zhí)行切換操作。

哨兵切換完成后,客戶端會(huì)和新主庫(kù)通信,發(fā)送請(qǐng)求操作。

但切換過(guò)程中,既然客戶端仍和原主庫(kù)通信,說(shuō)明原主庫(kù)并未真故障(如主庫(kù)進(jìn)程掛掉)。懷疑主庫(kù)某些原因無(wú)法處理請(qǐng)求,也沒(méi)響應(yīng)哨兵的心跳,被哨兵錯(cuò)判客觀下線。
被判下線后,原主庫(kù)又重新開(kāi)始處理請(qǐng)求了,而此時(shí),哨兵還沒(méi)完成主從切換,客戶端仍可和原主庫(kù)通信,客戶端發(fā)送的寫操作就會(huì)在原主庫(kù)寫數(shù)據(jù)。

為驗(yàn)證原主庫(kù)只是“假故障”,查看原主庫(kù)服務(wù)器的資源使用監(jiān)控。原主庫(kù)所在機(jī)器有段時(shí)間CPU利用率飆升,因某程序把機(jī)器CPU用滿,導(dǎo)致Redis主庫(kù)無(wú)法響應(yīng)心跳,這期間,哨兵就把主庫(kù)判為客觀下線,開(kāi)始主從切換。這程序很快恢復(fù)正常,CPU使用率也下來(lái)了。原主庫(kù)又繼續(xù)正常服務(wù)請(qǐng)求。

正因原主庫(kù)未真故障,在客戶端操作日志中就看到和原主庫(kù)通信記錄。從庫(kù)被升級(jí)為新主庫(kù)后,主從集群里就有兩個(gè)主庫(kù),這就是案例腦裂原因。

3 為何腦裂會(huì)導(dǎo)致數(shù)據(jù)丟失?

主從切換后,從庫(kù)一旦升級(jí)為新主,哨兵就會(huì)讓原主庫(kù)執(zhí)行slave of命令,和新主重新進(jìn)行全量同步。

在全量同步執(zhí)行最后階段,原主需清空本地?cái)?shù)據(jù),加載新主發(fā)送的RDB文件,原主在主從切換期間保存的新寫數(shù)據(jù)就丟了。

主從切換過(guò)程中,若原主只是“假故障”,會(huì)觸發(fā)哨兵啟動(dòng)主從切換,一旦等它從假故障恢復(fù),又開(kāi)始處理請(qǐng)求,這就和新主共存,導(dǎo)致腦裂。

等哨兵讓原主和新主做全量同步后,原主在切換期間保存的數(shù)據(jù)就丟了。

4 腦裂應(yīng)急方案

主從集群中的數(shù)據(jù)丟失是因?yàn)榘l(fā)生腦裂,必須有應(yīng)對(duì)腦裂方案。

問(wèn)題出在原主假故障后,仍能接收請(qǐng)求,因此,可在主從集群機(jī)制的配置項(xiàng)中查找是否有限制主庫(kù)接收請(qǐng)求的設(shè)置。Redis提供如下配置項(xiàng)限制主庫(kù)的請(qǐng)求處理:

min-replicas-to-write
主庫(kù)能進(jìn)行數(shù)據(jù)同步的最少?gòu)膸?kù)數(shù)量

min-replicas-max-lag
主從庫(kù)間進(jìn)行數(shù)據(jù)復(fù)制時(shí),從庫(kù)給主庫(kù)發(fā)送ACK消息的最大延遲(單位s)

分別設(shè)置閾值N和T,倆配置項(xiàng)組合后的要求是:

  • 主庫(kù)連接的從庫(kù)中至少有N個(gè)從庫(kù)
  • 和主庫(kù)進(jìn)行數(shù)據(jù)復(fù)制時(shí)的ACK消息延遲不能超過(guò)T秒

否則,主庫(kù)就不會(huì)再接收客戶端請(qǐng)求。

即使原主假故障,假故障期間也無(wú)法響應(yīng)哨兵心跳,也不能和從庫(kù)進(jìn)行同步,自然就無(wú)法和從庫(kù)進(jìn)行ACK確認(rèn)。這倆配置項(xiàng)組合要求就無(wú)法得到滿足,原主庫(kù)就會(huì)被限制接收客戶端請(qǐng)求,客戶端也就不能在原主庫(kù)中寫新數(shù)據(jù)。

等新主上線,就只有新主能接收和處理客戶端請(qǐng)求,此時(shí),新寫的數(shù)據(jù)會(huì)被直接寫到新主。而原主會(huì)被哨兵降為從庫(kù),即使它的數(shù)據(jù)被清空,也不會(huì)有新數(shù)據(jù)的丟失。

假設(shè)

  • min-replicas-to-write=1
  • min-replicas-max-lag設(shè)為12s
  • 哨兵的down-after-milliseconds設(shè)為10s

主庫(kù)因某原因卡住15s,導(dǎo)致哨兵判斷主庫(kù)客觀下線,開(kāi)始進(jìn)行主從切換。
同時(shí),因原主庫(kù)卡住15s,沒(méi)有一個(gè)從庫(kù)能和原主庫(kù)在12s內(nèi)進(jìn)行數(shù)據(jù)復(fù)制,原主庫(kù)也無(wú)法接收客戶端請(qǐng)求。
主從切換完成后,也只有新主庫(kù)能接收請(qǐng)求,不會(huì)發(fā)生腦裂,也就不會(huì)發(fā)生數(shù)據(jù)丟失。

5 總結(jié)

腦裂,主從集群中,同時(shí)有兩個(gè)主能接收寫請(qǐng)求。Redis主從切換過(guò)程中,若發(fā)生腦裂,客戶端數(shù)據(jù)就會(huì)寫入原主,若原主被降為從庫(kù),這些新寫入數(shù)據(jù)就丟了。

腦裂主要是因?yàn)樵鲙?kù)發(fā)生了假故障,假故障的原因:

  • 和主庫(kù)部署在同一臺(tái)服務(wù)器上的其他程序臨時(shí)占用了大量資源(例如CPU資源),導(dǎo)致主庫(kù)資源使用受限,短時(shí)間內(nèi)無(wú)法響應(yīng)心跳。其它程序不再使用資源時(shí),主庫(kù)又恢復(fù)正常
  • 主庫(kù)自身遇到阻塞,如處理bigkey或是發(fā)生內(nèi)存swap(你可以復(fù)習(xí)下第19講中總結(jié)的導(dǎo)致實(shí)例阻塞的原因),短時(shí)間內(nèi)無(wú)法響應(yīng)心跳,等主庫(kù)阻塞解除后,又恢復(fù)正常的請(qǐng)求處理了。

應(yīng)對(duì)腦裂,你可以在主從集群部署時(shí),通過(guò)合理地配置參數(shù)min-slaves-to-write和min-slaves-max-lag,來(lái)預(yù)防腦裂。

在實(shí)際應(yīng)用中,可能會(huì)因?yàn)榫W(wǎng)絡(luò)暫時(shí)擁塞導(dǎo)致從庫(kù)暫時(shí)和主庫(kù)的ACK消息超時(shí)。在這種情況下,并不是主庫(kù)假故障,我們也不用禁止主庫(kù)接收請(qǐng)求。

6 最佳實(shí)踐

假設(shè)從庫(kù)有K個(gè),可將:

  • min-slaves-to-write設(shè)置為K/2+1(如果K等于1,就設(shè)為1)
  • min-slaves-max-lag設(shè)置為十幾秒(例如10~20s)

這個(gè)配置下,如果有一半以上的從庫(kù)和主庫(kù)進(jìn)行的ACK消息延遲超過(guò)十幾s,我們就禁止主庫(kù)接收客戶端寫請(qǐng)求。

這樣一來(lái),我們可以避免腦裂帶來(lái)數(shù)據(jù)丟失的情況,而且,也不會(huì)因?yàn)橹挥猩贁?shù)幾個(gè)從庫(kù)因?yàn)榫W(wǎng)絡(luò)阻塞連不上主庫(kù),就禁止主庫(kù)接收請(qǐng)求,增加了系統(tǒng)的魯棒性。

假設(shè):

  • min-slaves-to-write 置 1
  • min-slaves-max-lag 設(shè)置為 15s,哨兵的
  • down-after-milliseconds 設(shè)置為 10s
    哨兵主從切換需要 5s,主庫(kù)因?yàn)槟承┰蚩ㄗ?2s,此時(shí),還會(huì)發(fā)生腦裂嗎?主從切換完成后,數(shù)據(jù)會(huì)丟失嗎?

主庫(kù)卡住 12s,達(dá)到哨兵設(shè)定的切換閾值,所以哨兵會(huì)觸發(fā)主從切換。但哨兵切換時(shí)間5s,即哨兵還未切換完成,主庫(kù)就會(huì)從阻塞狀態(tài)中恢復(fù)回來(lái),且沒(méi)有觸發(fā) min-slaves-max-lag 閾值,所以主庫(kù)在哨兵切換剩下的 3s 內(nèi),依舊可以接收客戶端的寫操作,如果這些寫操作還未同步到從庫(kù),哨兵就把從庫(kù)提升為主庫(kù)了,那么此時(shí)也會(huì)出現(xiàn)腦裂的情況,之后舊主庫(kù)降級(jí)為從庫(kù),重新同步新主庫(kù)的數(shù)據(jù),新主庫(kù)也會(huì)發(fā)生數(shù)據(jù)丟失。

即使 Redis 配置了 min-slaves-to-write 和 min-slaves-max-lag,當(dāng)腦裂發(fā)生時(shí),還是無(wú)法嚴(yán)格保證數(shù)據(jù)不丟失,只是盡量減少數(shù)據(jù)的丟失。

這種情況下,新主庫(kù)之所以會(huì)發(fā)生數(shù)據(jù)丟失,是因?yàn)榕f主庫(kù)從阻塞中恢復(fù)過(guò)來(lái)后,收到的寫請(qǐng)求還沒(méi)同步到從庫(kù),從庫(kù)就被哨兵提升為主庫(kù)了。如果哨兵在提升從庫(kù)為新主庫(kù)前,主庫(kù)及時(shí)把數(shù)據(jù)同步到從庫(kù)了,那么從庫(kù)提升為主庫(kù)后,也不會(huì)發(fā)生數(shù)據(jù)丟失。但這種臨界點(diǎn)的情況還是有發(fā)生的可能性,因?yàn)?Redis 本身不保證主從同步的強(qiáng)一致。

還有一種腦裂情況,就是網(wǎng)絡(luò)分區(qū):主庫(kù)和客戶端、哨兵和從庫(kù)被分割成了 2 個(gè)網(wǎng)絡(luò),主庫(kù)和客戶端處在一個(gè)網(wǎng)絡(luò)中,從庫(kù)和哨兵在另一個(gè)網(wǎng)絡(luò)中,此時(shí)哨兵也會(huì)發(fā)起主從切換,出現(xiàn) 2 個(gè)主庫(kù)的情況,而且客戶端依舊可以向舊主庫(kù)寫入數(shù)據(jù)。等網(wǎng)絡(luò)恢復(fù)后,主庫(kù)降級(jí)為從庫(kù),新主庫(kù)丟失了這期間寫操作的數(shù)據(jù)。

腦裂本質(zhì)是,Redis 主從集群內(nèi)部沒(méi)有通過(guò)共識(shí)算法,來(lái)維護(hù)多個(gè)節(jié)點(diǎn)數(shù)據(jù)的強(qiáng)一致性。不像 Zookeeper,每次寫請(qǐng)求必須大多數(shù)節(jié)點(diǎn)寫成功后才認(rèn)為成功。當(dāng)腦裂發(fā)生時(shí),Zookeeper 主節(jié)點(diǎn)被孤立,此時(shí)無(wú)法寫入大多數(shù)節(jié)點(diǎn),寫請(qǐng)求會(huì)直接返回失敗,因此它可以保證集群數(shù)據(jù)的一致性。

對(duì)于min-slaves-to-write,如果只有 1 個(gè)從庫(kù),當(dāng)把 min-slaves-to-write 設(shè)置為 1 時(shí),在運(yùn)維時(shí)需要小心一些,當(dāng)日常對(duì)從庫(kù)做維護(hù)時(shí),例如更換從庫(kù)的實(shí)例,需要先添加新的從庫(kù),再移除舊的從庫(kù)才可以,或者使用 config set 修改 min-slaves-to-write 為 0 再做操作,否則會(huì)導(dǎo)致主庫(kù)拒絕寫,影響到業(yè)務(wù)。

到此這篇關(guān)于Redis腦裂導(dǎo)致數(shù)據(jù)丟失的解決的文章就介紹到這了,更多相關(guān)Redis腦裂內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis?異常?read?error?on?connection?的解決方案

    Redis?異常?read?error?on?connection?的解決方案

    這篇文章主要介紹了Redis異常read?error?on?connection的解決方案,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-08-08
  • Redis主從復(fù)制詳解

    Redis主從復(fù)制詳解

    今天小編就為大家分享一篇關(guān)于Redis主從復(fù)制詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Redis 哨兵高模式搭建及Java代碼配置

    Redis 哨兵高模式搭建及Java代碼配置

    這篇文章主要介紹了Redis 哨兵高模式搭建及Java代碼配置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Redis實(shí)現(xiàn)分布式鎖(setnx、getset、incr)以及如何處理超時(shí)情況

    Redis實(shí)現(xiàn)分布式鎖(setnx、getset、incr)以及如何處理超時(shí)情況

    本文主要介紹了Redis實(shí)現(xiàn)分布式鎖(setnx、getset、incr)以及如何處理超時(shí)情況,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Redis集群的相關(guān)詳解

    Redis集群的相關(guān)詳解

    這篇文章主要介紹了Redis集群的相關(guān),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Redis基本數(shù)據(jù)類型List常用操作命令

    Redis基本數(shù)據(jù)類型List常用操作命令

    這篇文章主要為大家介紹了Redis數(shù)據(jù)類型List常用命令操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Redis中SDS簡(jiǎn)單動(dòng)態(tài)字符串詳解

    Redis中SDS簡(jiǎn)單動(dòng)態(tài)字符串詳解

    Redis中的SDS(Simple?Dynamic?String)是一種自動(dòng)擴(kuò)容的字符串實(shí)現(xiàn)方式,它可以提供高效的字符串操作,并且支持二進(jìn)制安全。SDS的設(shè)計(jì)使得它可以在O(1)時(shí)間內(nèi)實(shí)現(xiàn)字符串長(zhǎng)度的獲取和修改,同時(shí)也可以在O(N)的時(shí)間內(nèi)進(jìn)行字符串的拼接和截取。
    2023-04-04
  • Redis過(guò)期Key刪除策略和內(nèi)存淘汰策略的實(shí)現(xiàn)

    Redis過(guò)期Key刪除策略和內(nèi)存淘汰策略的實(shí)現(xiàn)

    當(dāng)內(nèi)存使用達(dá)到上限,就無(wú)法存儲(chǔ)更多數(shù)據(jù)了,為了解決這個(gè)問(wèn)題,Redis內(nèi)部會(huì)有兩套內(nèi)存回收的策略,過(guò)期Key刪除策略和內(nèi)存淘汰策略,本文就來(lái)詳細(xì)的介紹一下這兩種方法,感興趣的可以了解一下
    2024-02-02
  • redis.clients.jedis.exceptions.JedisBusyException無(wú)法處理異常的解決方法

    redis.clients.jedis.exceptions.JedisBusyException無(wú)法處理異常的解決方法

    redis.clients.jedis.exceptions.JedisBusyException異常通常不是 Jedis客戶端直接拋出的標(biāo)準(zhǔn)異常,本文就來(lái)介紹一下異常的解決方法,感興趣的可以了解一下
    2024-05-05
  • Redis安裝圖文教程(Windows和Linux)

    Redis安裝圖文教程(Windows和Linux)

    這篇文章主要介紹了Redis安裝教程(Windows和Linux),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03

最新評(píng)論