Redis哨兵模式(Sentinel、1主2從3哨兵6臺服務(wù)器配置實戰(zhàn)懂牧、客戶端調(diào)用侈净、日志解析、主觀下線僧凤、客觀下線畜侦、仲裁、腦裂問題躯保、哨兵長與從節(jié)點投票選舉過程與原理)

哨兵模式

  • 官方文檔:https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel
  • 關(guān)聯(lián)博客:Redis主從復(fù)制(下文能用到)
  • 極簡概括:自動監(jiān)控Redis主節(jié)點是否故障的一種方案旋膳,若主節(jié)點故障,則Redis會根據(jù)投票數(shù)自動將從庫切換為主庫(這個過程途事,叫仲裁)溺忧。
  • 解決問題:在主從復(fù)制的架構(gòu)模式下咏连,Redis主節(jié)點掛掉后,從節(jié)點無任何補償操作鲁森,無人工干預(yù)的情況下導(dǎo)致整個緩存鏈路的寫功能喪失祟滴。而哨兵模式有哨兵看守機制,可以做到主機的檢測與自動切換從機為主機的功能歌溉。
  • 適用場景:對于需要7 * 24高可用垄懂,且公司原意投資相關(guān)運維成本的服務(wù)端應(yīng)用。畢竟作為哨兵節(jié)點的Redis實例痛垛,將無法使用緩存服務(wù)草慧,只能作為哨兵,而且要求哨兵數(shù)量往往是奇數(shù)個匙头。
  • 優(yōu)點:
    • 降低運維成本:強大的高可用機制漫谷,適當(dāng)降低運維成本。
    • 自動恢復(fù)機制:當(dāng)主節(jié)點掛掉后蹂析,哨兵會自動選出一個從節(jié)點作為主節(jié)點舔示,繼續(xù)對外提供服務(wù),無人值守电抚。
  • 缺點:
    • 場景限制:小型公司Redis都可以不用惕稻,中型公司也不一定能用到Redis主從,更何況是哨兵這么嚴(yán)謹(jǐn)?shù)倪\維策略蝙叛。
    • 資金問題:Redis需要堆多個服務(wù)器俺祠,對公司而言是不小的支出,有一定門檻借帘。
    • 延遲問題:主節(jié)點掛掉時蜘渣,雖然可以做到自動切換,但是多個哨兵認(rèn)為Redis能夠客觀下線時肺然,這個過程需要時間的宋梧,雖然可以調(diào)整,但是這個時間內(nèi)的Redis寫操作是失效的狰挡,因此有了集群策略捂龄。
    • 數(shù)據(jù)丟失問題:Redis主從是異步復(fù)制,哨兵只是增加了自動化的切換功能加叁,沒有像MySQL的redo log機制倦沧,無法保證數(shù)據(jù)100%不丟失。
    • 會引發(fā)腦裂問題(下文有說)它匕。
  • 誤區(qū):哨兵是哨兵展融,集群是集群,兩者無關(guān)豫柬。哨兵是主從復(fù)制架構(gòu)的高可用優(yōu)化方案告希,不是集群部署的高可用的方案扑浸。
  • 訪問流程:由原先的編程語言客戶端訪問Redis主節(jié)點或從節(jié)點,變成了客戶端訪問哨兵節(jié)點(通常不止一個哨兵燕偶,有奇數(shù)個哨兵組成一個哨兵集群喝噪,奇數(shù)好投票),由哨兵節(jié)點告訴客戶端訪問那個主節(jié)點或從節(jié)點指么,從而區(qū)分讀寫操作酝惧。

實操(1主+2從+3哨)

  • 三哨理由:一個小區(qū)也不只一個保安,至少2個保安輪班倒伯诬。但是哨兵有類似投票機制晚唇,最好用奇數(shù)個哨兵。
  • 環(huán)境決策:部署3個哨兵+1個Master+2個Slave盗似,共6臺服務(wù)器哩陕。
  • Docker方案:當(dāng)內(nèi)存扛不住的時候可以用這個,但是拉鏡像時發(fā)現(xiàn)被墻了(國內(nèi)混蛋專家搞的混蛋規(guī)則)赫舒,鏡像拉不下來悍及,本地也沒有,棄用了這條路線号阿。
  • 運行環(huán)境:CentOS 7.6并鸵,每個系統(tǒng)分配256M內(nèi)存鸳粉,Linux可輕松啟動扔涧,共占用內(nèi)存1.5GB,設(shè)備能承受届谈,但磁盤占用挺高(特別是開機時)枯夜,每個Redis實例都配置好了遠(yuǎn)程連接功能(防火墻、遠(yuǎn)程連接權(quán)限艰山、保護模式湖雹,都配置到位)。
  • IP分配:192.168.0.180(主)曙搬、192.168.0.181(從1)摔吏、192.168.0.182(從2)、192.168.0.183(哨1)纵装、192.168.0.184(哨2)征讲、192.168.0.185(哨3),如圖
                     192.168.0.183                           192.168.0.181
                  /                \                      /
                /                    \                  /
               /                      \               /
192.168.0.xxx  -->-> 192.168.0.184 ---> 192.168.0.180
               \                      /               \
                 \                   /                  \
                   \                /                     \  
                     192.168.0.185                           192.168.0.182
  • 主要配置說明:
配置3臺哨兵:
高版本Redis自帶sentinel.conf文件橡娄,可直接用诗箍。
目前用的5,沒有獨立的配置文件挽唉,可在redis.conf中配置如下:
sentinel monitor 主節(jié)點名  主節(jié)點IP 主節(jié)點端口 確認(rèn)客觀下線的最少哨兵數(shù)量滤祖。    // 配置鏈接筷狼,用于定位主機網(wǎng)絡(luò)位置。
sentinel auth-pass 主節(jié)點名  主節(jié)點密碼        //配置主機密碼
sentinel down-after-milliseconds 主節(jié)點名 毫秒 //配置心跳失去連接多少毫秒后匠童,讓哨兵認(rèn)為主機宕機
sentinel failover-timeout 主節(jié)點名 毫秒        //配置執(zhí)行故障轉(zhuǎn)移所需的超時時間
sentinel parallel-syncs 主節(jié)點名 數(shù)量          //切換新的主節(jié)點之后埂材,可同時同步其余從節(jié)點的個數(shù),數(shù)字越小性能越低俏让。
其它配置不常用楞遏,可參考官方手冊。

對于sentinel monitor 配置項首昔,“確認(rèn)客觀下線的最少哨兵數(shù)量”參數(shù)的介紹:
至少有N個哨兵節(jié)點寡喝,認(rèn)為主節(jié)點有故障,才會將其下線勒奇。
由于哨兵節(jié)點自身負(fù)載問題预鬓,或網(wǎng)絡(luò)鏈路有抖動問題,這會直接影響Redis哨兵檢測主節(jié)點的心跳赊颠,誤認(rèn)為主節(jié)點是宕機格二。
但是容易有誤判,所以設(shè)定了指定的容錯額度竣蹦,減少誤判率顶猜。
  • 實操:
第一步,先配置1主(不用配置)2從(需要在192.168.0.181和192.168.0.182上):
我之前寫過完整文章痘括,可參考https://blog.csdn.net/weixin_42100387/article/details/139667697

vim /usr/local/redis/etc/redis.conf
#配置主節(jié)點IP和端口
replicaof 192.168.0.180 6379
#配置主節(jié)點密碼
masterauth 123456

之后重啟redis

需要注意长窄,必須把每個從機的密碼設(shè)置一致,方便哨兵模式主從切換實例纲菌,避免整個緩存模塊故障挠日。



第二步,配置3哨兵:
以Redis 5為例,3臺哨兵節(jié)點(192.168.0.183~185)配置以下主要內(nèi)容翰舌,其余配置可按需添加(因為不配置也有默認(rèn)值嚣潜,不會導(dǎo)致錯誤):
補充:一個哨兵是可以監(jiān)控多個master的,但是這對于開發(fā)幾乎用不上椅贱。
firewall-cmd --add-port=26379/tcp --zone=public --permanent && systemctl restart firewalld
vim /usr/local/redis/etc/sentinel.conf
bind 0.0.0.0
#哨兵默認(rèn)端口
port 26379
daemonize yes
protected-mode no
pidfile /usr/local/redis/redis_26379.pid
logfile /usr/local/redis/redis_26379.log
sentinel monitor zs_master 192.168.0.180 6379 2
sentinel auth-pass zs_master 123456

之后啟動哨兵懂算,用以下二選一命令的方式
/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf
/usr/local/redis/bin/redis-server   /usr/local/redis/etc/sentinel.conf --sentinel

啟動后,redis 會為sentinel.conf額外增加如下配置:
sentinel myid 3feb02e7fd5a96152e217b76f11e72236c23668c
sentinel deny-scripts-reconfig yes
# Generated by CONFIG REWRITE
dir "/usr/local/redis/etc"
sentinel config-epoch zs_master 0
sentinel leader-epoch zs_master 0
sentinel known-replica zs_master 192.168.0.182 6379
sentinel known-replica zs_master 192.168.0.181 6379
sentinel current-epoch 0

它們的含義分別是:
sentinel myid:起個唯一標(biāo)識庇麦,方便定位哨兵计技,類比MySQL表id。
sentinel deny-scripts-reconfig yes: 拒絕通過腳本進行配置更改女器,這有助于提高安全性酸役,防止非授權(quán)的更改。
dir "/usr/local/redis/etc": 指定rdb文件的位置。
sentinel config-epoch zs_master 0: 記錄主節(jié)點zs_master的情況涣澡,用于判斷哨兵配置的更新情況贱呐。
sentinel leader-epoch zs_master 0: 記錄主節(jié)點zs_master的情況,用于判斷哨兵的領(lǐng)導(dǎo)者入桂。
sentinel known-replica zs_master 192.168.0.182 6379: 記錄已知的從節(jié)點奄薇,這里指定了IP地址和端口號。
sentinel current-epoch 0: 記錄當(dāng)前的紀(jì)元(直譯就這意思)抗愁,用于標(biāo)識哨兵配置的更新情況馁蒂。



第三步,檢測1主2從是否能正常使用
可在主節(jié)點Redis會話中執(zhí)行 set a 123蜘腌,從節(jié)點執(zhí)行 get a 判斷主從是否正常復(fù)制沫屡。



第四步,檢測3臺哨兵是否啟動(3臺設(shè)備分別執(zhí)行撮珠,逐一檢測):
ps aux | grep redis
root      81041  0.4  0.5 153996  2788 ?        Ssl  00:34   0:00 /usr/local/redis/bin/redis-sentinel 0.0.0.0:26379 [sentinel]
root      81084  0.0  0.2 112828   992 pts/0    R+   00:35   0:00 grep --color=auto redis

netstat -nlp | grep redis
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN      81041/redis-sentin

模擬主節(jié)點故障

經(jīng)過實測:

  • 主節(jié)點執(zhí)行shutdown模擬宕機沮脖,半分鐘內(nèi),Redis哨兵自動完成了主節(jié)點的下線芯急,并將某個從節(jié)點切換為主節(jié)點勺届。
  • 從節(jié)點升級為主節(jié)點的節(jié)點,以及其它從節(jié)點娶耍,的配置文件都會被強制更改免姿,作用到配置文件,是持久化的榕酒。
  • 哨兵切換流程執(zhí)行完畢后原主節(jié)點恢復(fù)訪問胚膊,那么原主節(jié)點會變成從節(jié)點,不會因為本身的恢復(fù)奈应,就再次改為主節(jié)點澜掩。
  • 一些情情況下购披,當(dāng)掛掉的主節(jié)點再次啟動時杖挣,可成功啟動,但是redis的機制會把master-auth配置項干丟掉刚陡,造成啟動之后(變?yōu)閺墓?jié)點)連不上主節(jié)點的情況惩妇。

哨兵對應(yīng)日志說明

  • 由于Redis哨兵模式趨向于自動化運維,所以日常日志的排查七分重要筐乳,故在此說明其中1個哨兵(192.168.0.184)的日志記錄概況(最起碼要看懂【何時主節(jié)點掛】歌殃、【讓誰做主節(jié)點】)。
  • 速查方法(根據(jù)關(guān)鍵字搜索蝙云,若搜索出多個值氓皱,最后一個為最新):
    • 查詢何時主節(jié)點掛:odown master 原主節(jié)點名 原主節(jié)點IP 原主節(jié)點端口 #quorum
    • 查詢讓誰做主節(jié)點:+switch-master 原主節(jié)點名 原主節(jié)點IP 原主節(jié)點端口(后面緊跟新主節(jié)點)
  • 哨兵啟動時:
Redis哨兵初始化
99136:X 19 Jun 2024 05:58:54.697 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
99136:X 19 Jun 2024 05:58:54.697 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=99136, just started
99136:X 19 Jun 2024 05:58:54.697 # Configuration loaded
99137:X 19 Jun 2024 05:58:54.701 * Running mode=sentinel, port=26379.
99137:X 19 Jun 2024 05:58:54.701 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
99137:X 19 Jun 2024 05:58:54.702 # Sentinel ID is 0da5ef8126894b04e2572c4f2f9e1e636543ceee
主節(jié)點從節(jié)點信息獲取
99137:X 19 Jun 2024 05:58:54.702 # +monitor master zs_master 192.168.0.180 6379 quorum 2
99137:X 19 Jun 2024 05:58:54.720 * +slave slave 192.168.0.181:6379 192.168.0.181 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:58:54.722 * +slave slave 192.168.0.182:6379 192.168.0.182 6379 @ zs_master 192.168.0.180 6379
添加了兩個哨兵
99137:X 19 Jun 2024 05:58:56.059 * +sentinel sentinel 91e7adffd0d7fc08fc1eb622001eb78b7c230901 192.168.0.183 26379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:58:59.359 * +sentinel sentinel cadd108977e5634179172b6a2f84f4712f2c9185 192.168.0.185 26379 @ zs_master 192.168.0.180 6379
  • 主節(jié)點宕機時:
當(dāng)前哨兵認(rèn)為主機已下線,主觀下線。
99137:X 19 Jun 2024 05:59:59.572 # +sdown master zs_master 192.168.0.180 6379
其它哨兵也認(rèn)為主機已下線波材,并達(dá)到了sentinel monitor設(shè)定的閾值股淡,主觀下線升級為客觀下線
99137:X 19 Jun 2024 05:59:59.627 # +odown master zs_master 192.168.0.180 6379 #quorum 2/2
故障切換,當(dāng)前切換廷区,讓0da5ef8126894b04e2572c4f2f9e1e636543ceee 哨兵說了算唯灵,其余哨兵投票。
99137:X 19 Jun 2024 05:59:59.627 # +new-epoch 1
99137:X 19 Jun 2024 05:59:59.627 # +try-failover master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:59:59.628 # +vote-for-leader 0da5ef8126894b04e2572c4f2f9e1e636543ceee 1
99137:X 19 Jun 2024 05:59:59.630 # cadd108977e5634179172b6a2f84f4712f2c9185 voted for 0da5ef8126894b04e2572c4f2f9e1e636543ceee 1
99137:X 19 Jun 2024 05:59:59.630 # 91e7adffd0d7fc08fc1eb622001eb78b7c230901 voted for 0da5ef8126894b04e2572c4f2f9e1e636543ceee 1
選擇192.168.0.182作為主節(jié)點隙轻,客觀下線老主節(jié)點埠帕,并將180的主節(jié)點轉(zhuǎn)移為182的主節(jié)點,換人和交換權(quán)利的動作不重復(fù)玖绿。
99137:X 19 Jun 2024 05:59:59.732 # +elected-leader master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:59:59.732 # +failover-state-select-slave master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:59:59.837 # +selected-slave slave 192.168.0.182:6379 192.168.0.182 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:59:59.837 * +failover-state-send-slaveof-noone slave 192.168.0.182:6379 192.168.0.182 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 05:59:59.907 * +failover-state-wait-promotion slave 192.168.0.182:6379 192.168.0.182 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:00.239 # +promoted-slave slave 192.168.0.182:6379 192.168.0.182 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:00.239 # +failover-state-reconf-slaves master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:00.298 * +slave-reconf-sent slave 192.168.0.181:6379 192.168.0.181 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:00.788 # -odown master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:01.280 * +slave-reconf-inprog slave 192.168.0.181:6379 192.168.0.181 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:01.281 * +slave-reconf-done slave 192.168.0.181:6379 192.168.0.181 6379 @ zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:01.353 # +failover-end master zs_master 192.168.0.180 6379
99137:X 19 Jun 2024 06:00:01.353 # +switch-master zs_master 192.168.0.180 6379 192.168.0.182 6379
將180敛瓷,181節(jié)點,當(dāng)做從節(jié)點處理斑匪。
99137:X 19 Jun 2024 06:00:01.354 * +slave slave 192.168.0.181:6379 192.168.0.181 6379 @ zs_master 192.168.0.182 6379
99137:X 19 Jun 2024 06:00:01.354 * +slave slave 192.168.0.180:6379 192.168.0.180 6379 @ zs_master 192.168.0.182 6379
當(dāng)前哨兵發(fā)現(xiàn)180從節(jié)點仍不能用琐驴,主觀下線。
99137:X 19 Jun 2024 06:00:31.393 # +sdown slave 192.168.0.180:6379 192.168.0.180 6379 @ zs_master 192.168.0.182 6379

編程語言調(diào)用

  • 以原生PHP為例:
// 創(chuàng)建Redis哨兵對象秤标,通過這個對象獲取主節(jié)點的地址绝淡,這里是寫死的,可以寫成數(shù)組苍姜,隨機訪問1個節(jié)點牢酵,用于減輕壓力。
$sentinel = new RedisSentinel('tcp://192.168.0.183', 26379);
//主機名
$master = $sentinel->getMasterAddrByName('zs_master');

if(! $master) {
    echo '主節(jié)點獲取失敗';
    die;
}


//獲取到的主節(jié)點地址進行寫操作
$redis = new Redis();
$redis->connect($master[0], $master[1]);
$redis->auth('123456');
$redis->set('key', 'val');


//從節(jié)點讀操作衙猪。
$slave = $sentinel->slaves('zs_master');
if(empty($slave)) {
    echo '從節(jié)點獲取失敗';
    die;
}

//隨機從節(jié)點配置數(shù)組的下標(biāo)馍乙,使其讀寫趨向于均衡,防止訪問壓力傾斜
$slave_arr_key = mt_rand(0, count($slave));

//這塊的從節(jié)點配置不能寫死垫释,一定要寫活丝格,萬一這里的從節(jié)點,變成了主節(jié)點呢棵譬?
$redis->connect($slave[$slave_arr_key]['ip'], $slave[$slave_arr_key]['port']);
$redis->auth('123456');
$res = $redis->get('key');
print_r($res);


// 關(guān)閉連接
$redis->close();
composer require monospice/laravel-redis-sentinel-drivers

Laravel5.5以下版本需要再config/app.php中配置如下內(nèi)容
'providers' => [
    ...
    Monospice\LaravelRedisSentinel\RedisSentinelServiceProvider::class,
    ...
],

在config/database.php的Redis段的同級中添加脏嚷,這是演示骆撇,生產(chǎn)環(huán)境推薦參數(shù)寫活
這插件支持直接配置到.env,不用配config父叙,但是一旦執(zhí)行php artisan optimize加速神郊,那么env('config_key')將會是null肴裙,所以不用。
    'redis-sentinel' => [
        'default' => [
            ['host' => '192.168.0.183', 'port' => 26379,],
            ['host' => '192.168.0.184', 'port' => 26379,],
            ['host' => '192.168.0.185', 'port' => 26379,],
        ],

        'options' => [
        //主機名
        'service' =>  'zs_master',
        'parameters' => [
            'password' => '123456',
            'database' => 0,
        ],
    ],


若要配置Redos Facdeds:
.env文件添加REDIS_DRIVER=redis-sentinel
這個不用配置config涌乳,因為沒有地方配置践宴,插件直接讀取env文件,測試php artisan optimize,發(fā)現(xiàn)能照常讀取爷怀。


若要配置Cache Facdeds:
config/cache.php的'default' => env('CACHE_DRIVER', 'file'), 此處最好修改env阻肩,將值改為redis-sentinel
并添加:
'stores' => [ //注意層級關(guān)系
    ...
    'redis-sentinel' => [
        'driver' => 'redis-sentinel',
        'connection' => 'default',
    ],
],


若要配置Session Facdeds:
config/session.php的'driver' => env('SESSION_DRIVER', 'file'),,此處最好修改env运授,將值改為redis-sentinel,
并將connection項設(shè)置為'',否則報錯烤惊。


若要配置Queue隊列:
config/queue.php的'default' => env('QUEUE_CONNECTION', 'sync'),, 此處最好修改env吁朦,將值改為redis-sentinel,
并在connections項內(nèi)部配置:
    'redis-sentinel' => [
        'driver' => 'redis-sentinel',
        'connection' => 'default',
        'queue' => 'default',
        'retry_after' => 90, // Laravel >= 5.4.30
        'expire' => 90,      // Laravel < 5.4.30
    ],
測試延時隊列柒室,可正常使用。

其余常用配置說明

  • redis.conf
    • min-replicas-to-write 1與min-replicas-max-lag 10:這個是高可用的兩個配置項逗宜,它根筷子一樣通常在一塊出現(xiàn)雄右,默認(rèn)是禁用的配置,配置在主節(jié)點和從節(jié)點纺讲。表示主節(jié)點一個寫操作擂仍,至少有1個確認(rèn)接收,且確認(rèn)回復(fù)(ack)時間不能超過10毫秒熬甚,否則返回的既不是nil也不是0逢渔,而是錯誤異常。它能夠保證主從復(fù)制時的高可用乡括,弊端就是若有從節(jié)點掛掉肃廓,達(dá)不到min-replicas-to-write設(shè)置的數(shù)量,主節(jié)點寫入將會報錯诲泌,導(dǎo)致寫功能廢掉盲赊。一般情況下,前者設(shè)置看情況敷扫,后者設(shè)置為3000~5000哀蘑。
    • replica-priority 100:被選中作為從節(jié)點的優(yōu)先級,從1設(shè)置為10呻澜,從2設(shè)置為100递礼,則主節(jié)點掛掉惨险,從1(小的優(yōu)先)優(yōu)先被設(shè)定為從機羹幸。

主觀下線(Sdown)與客觀下線(Odown)

  • 主觀下線:當(dāng)前(單個)哨兵認(rèn)為主節(jié)點掛了,有可能沒掛辫愉。
  • 客觀下線:多個哨兵都認(rèn)為主節(jié)點掛了栅受,則主節(jié)點大概率掛了,準(zhǔn)備開始選舉其它從節(jié)點做主節(jié)點。

仲裁(Failover)

哨兵在主節(jié)點失效時進行自動故障轉(zhuǎn)移(failover)的行為屏镊。

腦裂(Split-brain)導(dǎo)致的數(shù)據(jù)丟失問題

  • 分布式系統(tǒng)的概念:腦裂是一種在分布式系統(tǒng)中可能出現(xiàn)的情況依疼,指當(dāng)網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點無法與其它節(jié)點通信時,這些節(jié)點可能會錯誤地認(rèn)為自己是系統(tǒng)中唯一的活躍實例而芥,從而導(dǎo)致數(shù)據(jù)的不一致(一個地方每個山頭都獨立為王律罢,那就亂了,多了個頭頭棍丐,好比腦裂了)误辑。
  • 在哨兵模式下(極少出現(xiàn)):客戶端與主節(jié)點連接正常,但是哨兵與主節(jié)點連接異常歌逢,那么哨兵可能就會讓其它從節(jié)點變?yōu)橹鞴?jié)點巾钉,此時分布式節(jié)點中,就會有多個主節(jié)點秘案。然而客戶端仍舊和舊的數(shù)據(jù)通信(執(zhí)行寫操作)砰苍,在這個過程下,數(shù)據(jù)會丟失阱高。
    若此時舊主節(jié)點恢復(fù)與哨兵的連接赚导,舊主節(jié)點就會降級為從節(jié)點,舊主節(jié)點未同步的數(shù)據(jù)也會被新節(jié)點強制覆蓋赤惊。

腦裂(Split-brain)導(dǎo)致的數(shù)據(jù)丟失原因

  • 感謝IT老奇的架構(gòu)600講:https://www.bilibili.com/video/BV1eF41147iL/?vd_source=19da1fcedca1050975549448303b95c2
  • 背景:接上文辟癌,因為腦裂問題引發(fā)的哨兵模式自動故障轉(zhuǎn)移(failover)的行為(仲裁),荐捻,舊的主節(jié)點黍少,有著最近的進度。
  • 過程:當(dāng)這個舊主節(jié)點與哨兵恢復(fù)連接后处面,并且已經(jīng)有新的主節(jié)點誕生厂置,舊主節(jié)點會被降級為從節(jié)點。
  • 數(shù)據(jù)丟失內(nèi)部機制:舊主節(jié)點魂角,會向新的主節(jié)點申請全量數(shù)據(jù)昵济,新主節(jié)點會通過bgsave命令,異步生成rdb文件野揪,回傳到從節(jié)點访忿,從節(jié)點拿到后先清空自身的所有數(shù)據(jù),用一個干凈的數(shù)據(jù)倉庫承接主節(jié)點發(fā)來的數(shù)據(jù)斯稳,這個清空的過程海铆,造成了數(shù)據(jù)的丟失。
  • 結(jié)論:客戶端與Redis服務(wù)端通信期間挣惰,最新的進度沒了卧斟,數(shù)據(jù)自然也就丟失了殴边。

腦裂(Split-brain)問題改善

由于網(wǎng)絡(luò)的隔離,通信無法像MySQL本地事務(wù)那樣做到幾乎完美的一致性策略珍语,說白了哨兵與主節(jié)點的通信斷了就是網(wǎng)斷了锤岸,斷了就是斷了,不可控也無規(guī)律板乙,代碼寫的再好也不能解決這個問題是偷。所以這個問題的解決方案,不能用解決修飾募逞,用改善修飾會更好晓猛。

可在主節(jié)點和其它從節(jié)點添加min-replicas-to-write 與min-replicas-max-lag參數(shù)去改善,參數(shù)含義上文有講凡辱。
思路就是:判斷主節(jié)點寫入數(shù)據(jù)時從節(jié)點發(fā)送ack的數(shù)量戒职,以及延遲,若發(fā)生腦裂透乾,則主節(jié)點數(shù)量+1洪燥,從節(jié)點數(shù)量-1,達(dá)不到min-replicas-to-write閾值時乳乌,就會報錯捧韵。這也會導(dǎo)致緩存寫功能不可用,將異常兜底下推到代碼層汉操。

哨兵監(jiān)控主節(jié)點(哨兵切換步驟0)

哨兵探測主節(jié)點是否異常是用的心跳機制再来,就是每隔一段時間,向主節(jié)點發(fā)送ping進而保持連接磷瘤。

哨兵長(Zhang)選舉(哨兵切換步驟1)

  • 動作:當(dāng)主節(jié)點掛掉芒篷,哨兵進行選舉主節(jié)點時,實際上進行了兩步:第一步采缚,哨兵會投票選舉一個哨兵長针炉,第二步,哨兵長選舉主節(jié)點扳抽。
  • 選舉算法:Redis使用的時Raft算法篡帕。
  • 算法流程(個人理解):
    時序不同,數(shù)量不同會得到不同的結(jié)果贸呢,具體讀者可深入理解Raft算法官方說明镰烧。
步驟 哨1 哨2 哨3
1 給自己投1票,將投票請求發(fā)送給哨2哨3楞陷,告訴他們自己要成為哨兵長
2 給自己投1票怔鳖,將投票請求發(fā)送給哨1哨2,告訴他們自己要成為哨兵長
3 收到哨3請求猜谚,拒絕 收到哨3請求败砂,同意
4 收到哨1請求赌渣,拒絕
5 1票同意 2票同意魏铅,成為哨兵長

主節(jié)點選舉(哨兵切換步驟2)

  • 引言:多個從節(jié)點昌犹,都有可能被選擇其中一個為主節(jié)點,隨機算法可以實現(xiàn)览芳,但是有更好的判斷策略斜姥,所以不用隨機,而這些策略受一些因素限制沧竟。
  • 因素1:如果發(fā)現(xiàn)副本服務(wù)器與主服務(wù)器斷開連接的時間超過所配置的主服務(wù)器超時時間(down-after-milliseconds)的10倍铸敏,再加上從執(zhí)行故障切換的哨兵的角度來看主服務(wù)器也不可用的時間,則副本服務(wù)器被認(rèn)為不適合進行故障切換悟泵,并被跳過杈笔。
  • 因素2:優(yōu)先級:replica-priority參數(shù),redis.conf中默認(rèn)為100糕非,開發(fā)人員根據(jù)當(dāng)前實例情況可設(shè)置不同的值蒙具,有較小值的節(jié)點會被設(shè)置為主節(jié)點。
  • 因素3:進度大行喾省:若優(yōu)先級一樣禁筏,就看進度,進度就是所謂的偏移量衡招。偶爾受網(wǎng)絡(luò)抖動或者其它因素影響篱昔,會有一個進度快(進度新),進度慢的始腾,進度新的就做了主節(jié)點州刽。若讓進度舊的做主節(jié)點,則會讓整個鏈路整體丟失小部分?jǐn)?shù)據(jù)浪箭。
  • 因素4:若權(quán)限和進度一樣怀伦,則就看Run ID,這個每個Redis實例上都會有山林,根據(jù)Run ID做ASICC的字典排序房待,最終選取一臺從節(jié)點實例做主節(jié)點。
  • 當(dāng)某個從節(jié)點被哨兵選中當(dāng)做主節(jié)點時驼抹,哨兵會發(fā)送replicaof no one命令給從節(jié)點桑孩,讓其不做任何節(jié)點的從節(jié)點。

從節(jié)點換綁主節(jié)點(哨兵切換步驟3)

能走到這個階段框冀,就說明新的主節(jié)點已經(jīng)誕生流椒,其它從節(jié)點已經(jīng)有了切換主節(jié)點的目標(biāo)。
哨兵使用Redis發(fā)布/訂閱消息功能明也,在主服務(wù)器和所有從服務(wù)器中連續(xù)廣播相關(guān)配置宣虾,直到每個節(jié)點配置完成惯裕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绣硝,隨后出現(xiàn)的幾起案子蜻势,更是在濱河造成了極大的恐慌,老刑警劉巖鹉胖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件握玛,死亡現(xiàn)場離奇詭異,居然都是意外死亡甫菠,警方通過查閱死者的電腦和手機挠铲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寂诱,“玉大人拂苹,你說我怎么就攤上這事√等鳎” “怎么了瓢棒?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長带迟。 經(jīng)常有香客問我音羞,道長,這世上最難降的妖魔是什么仓犬? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任嗅绰,我火速辦了婚禮,結(jié)果婚禮上搀继,老公的妹妹穿的比我還像新娘窘面。我一直安慰自己,他們只是感情好叽躯,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布财边。 她就那樣靜靜地躺著,像睡著了一般点骑。 火紅的嫁衣襯著肌膚如雪酣难。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天黑滴,我揣著相機與錄音憨募,去河邊找鬼。 笑死袁辈,一個胖子當(dāng)著我的面吹牛菜谣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼尾膊,長吁一口氣:“原來是場噩夢啊……” “哼媳危!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冈敛,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤待笑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后莺债,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滋觉,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡签夭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年齐邦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片第租。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡措拇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慎宾,到底是詐尸還是另有隱情丐吓,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布趟据,位于F島的核電站券犁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汹碱。R本人自食惡果不足惜粘衬,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咳促。 院中可真熱鬧稚新,春花似錦、人聲如沸跪腹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冲茸。三九已至屯阀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間轴术,已是汗流浹背难衰。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留膳音,地道東北人召衔。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像祭陷,于是被迫代替她去往敵國和親苍凛。 傳聞我的和親對象是個殘疾皇子趣席,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容