備胎是怎么上位的-redis高可用淺析

前言

最近在看redis,有一些心得,為了不忘,現(xiàn)在記錄下來。

我嘗試從問題出發(fā),步步遞進(jìn),給大家較好的閱讀體驗(yàn),具體如下

  1. 什么是緩存,為啥要有它
  2. 緩存的實(shí)現(xiàn)方式-進(jìn)程內(nèi)的緩存
  3. 緩存的實(shí)現(xiàn)方式-進(jìn)程級(jí)別的緩存
  4. redis作為一個(gè)進(jìn)程級(jí)別的數(shù)據(jù)庫,優(yōu)點(diǎn)
  5. redis的高可用實(shí)現(xiàn)

什么是緩存,為啥要有它

一般我們將數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫中,對(duì)于一些經(jīng)常查詢的業(yè)務(wù),比如用戶訪問某一資源,通常我們會(huì)通過查詢數(shù)據(jù)庫查看用戶是否有這個(gè)訪問權(quán)限,這樣業(yè)務(wù)的特點(diǎn)是查詢頻率高,查詢數(shù)據(jù)庫是比較重的操作,主要的耗時(shí)有數(shù)據(jù)庫本身的查詢耗時(shí)和網(wǎng)絡(luò)耗時(shí)。如果將一些常使用的數(shù)據(jù)放在程序運(yùn)行時(shí)內(nèi)存里,隨著程序的啟動(dòng),加載數(shù)據(jù)庫中信息到內(nèi)存中,這樣就減少了網(wǎng)絡(luò)交互和數(shù)據(jù)庫本身的查詢耗時(shí)。

緩存的實(shí)現(xiàn)方式-進(jìn)程內(nèi)的緩存

這種就是在寫程序時(shí)開辟一塊內(nèi)存,專門當(dāng)做緩存供程序使用

優(yōu)點(diǎn)

  1. 不需要網(wǎng)絡(luò)傳輸。
  2. 不需要線程間切換。
  3. 緩存更新方便。因?yàn)槭浅绦騼?nèi)的內(nèi)存區(qū)域,我需要更新哪個(gè)區(qū)域,我可以直接定位到內(nèi)存位置,并更新它。

缺點(diǎn)

  1. 拓展性差。還是一個(gè)商城的例子,用戶想看自己的購(gòu)物車,假設(shè)我們使用token進(jìn)行狀態(tài)保持,我解析token,抽取用戶id,查看是否具有這個(gè)業(yè)務(wù)操作的權(quán)限。如果部署的程序只有一個(gè),完全沒問題。但是為了滿足未來用戶量高速增長(zhǎng),通過nginx橫向拓展程序就可以有問題。假如我們平行的部署兩個(gè)程序,用戶來登錄,程序a處理了這個(gè)請(qǐng)求,并將該用戶的權(quán)限信息,token存在自己的內(nèi)存區(qū)域,當(dāng)該用戶發(fā)起另外一個(gè)業(yè)務(wù)請(qǐng)求時(shí),程序b接受這個(gè)請(qǐng)求,程序b拿到用戶的token,抽取用戶信息,查詢自己的內(nèi)存區(qū)域,發(fā)現(xiàn)沒有這個(gè)用戶信息,就判斷這個(gè)用戶沒有訪問權(quán)限。
  2. 如果是橫向拓展的話,很有可能浪費(fèi)內(nèi)存。多個(gè)程序都有自己的內(nèi)存區(qū)域,但是內(nèi)存區(qū)域存的東西也是基本一樣的。

緩存的實(shí)現(xiàn)方式-進(jìn)程級(jí)別的緩存

優(yōu)點(diǎn)

  1. 節(jié)約內(nèi)存資源。
  2. 職責(zé)分離更明確

缺點(diǎn)

  1. 增加網(wǎng)絡(luò)傳輸
  2. 增加線程間切換
  3. 單點(diǎn),有風(fēng)險(xiǎn)

redis作為一個(gè)進(jìn)程級(jí)別的數(shù)據(jù)庫,優(yōu)點(diǎn)

  1. 支持高可用部署
  2. 為了降低總體網(wǎng)絡(luò)傳輸?shù)难舆t,提出了一個(gè)新思想:

假設(shè)我是新街口東方餃子王老板,提供送餐服務(wù),我有2個(gè)快遞員,假設(shè)我的飯是提前做好的

  • 12:00,京師科技大廈小強(qiáng)定了一份餃子,快遞員1去送餐,十分鐘可以送到,再有十分鐘回到飯店
  • 12:02,京師科技大廈小紅定了一份餃子,快遞員2去送餐,十分鐘可以送到,再有十分鐘回到飯店
  • 12:03,京師科技大廈小花定了一份餃子,沒有快遞員送餐:快遞員1要到12:20才能回來,快遞員2要到12:22才能回來。等待
  • 12:04,京師科技大廈特朗普定了5份餃子,沒有快遞員送餐:快遞員1要到12:20才能回來,快遞員2要到12:22才能回來。等待
  • 12:05,京師科技大廈克林頓定了5份餃子,沒有快遞員送餐:快遞員1要到12:20才能回來,快遞員2要到12:22才能回來。等待
  • 12:20,快遞員1接到小花訂單,去送餐
  • 12:22,快遞員2接到特朗普訂單,去送餐

假如特朗普和小強(qiáng)小紅是一個(gè)公司的,特朗普心里就不爽了,都是同一時(shí)間定的,為啥他們到了,我的還沒到?

那有什么解決方案嗎 ?

  1. 減少每趟耗時(shí)。比如原來是快遞員騎自行車,現(xiàn)在換成摩托車,原來是摩托車,現(xiàn)在換成汽車,原來汽車,現(xiàn)在換成火箭..
  2. 增加快遞員的數(shù)量。 原來是2個(gè),我就再招十來個(gè) 。
  3. 快遞員每趟運(yùn)送的貨物爭(zhēng)取多一點(diǎn)。比如上述例子,僅僅五分鐘內(nèi),連續(xù)有京師科技大廈5單訂單,一共13份餃子,假設(shè)一個(gè)快遞員的后備箱可以裝10分餃子,那在12:05的時(shí)候,快遞員1 運(yùn)送前四個(gè)訂單,一共8份,快遞員2運(yùn)送第五個(gè)訂單,一個(gè)5分。這樣特朗普就和小強(qiáng)一起吃上飯了。

在計(jì)算機(jī)中 ,這三種解決方案分別對(duì)應(yīng)的是

  1. 減少每趟耗時(shí)。往返時(shí)間:從發(fā)送方發(fā)送數(shù)據(jù)開始,直到發(fā)送方收到接收方回復(fù)的確認(rèn)為止。數(shù)據(jù)傳輸?shù)姆绞胶?jiǎn)單來說是這樣的,先將數(shù)據(jù)轉(zhuǎn)換為字節(jié)流,然后通過一個(gè)裝置(調(diào)制解頻器)轉(zhuǎn)換為電磁波 ,通過網(wǎng)線或者無線電波傳輸,接收方接受到無線電波,將其轉(zhuǎn)換成字節(jié)流,然后在轉(zhuǎn)換成具體的可供程序使用的數(shù)據(jù)。是不是腦袋有點(diǎn)大,這個(gè)過程的優(yōu)化可能不是軟件工程師能做的。
  2. 吞吐量:?jiǎn)挝粫r(shí)間內(nèi)通過某個(gè)網(wǎng)絡(luò)的數(shù)據(jù)量。這個(gè)優(yōu)化可能不是軟件工程師能做的。
  3. 對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行緩沖,降低總體網(wǎng)絡(luò)延遲。

第三種思想在很多地方都采用了,比如郵件服務(wù)器使用這種思想可以更快的下載新郵件,

redis 也是采用了第三種解決方案

感興趣的同學(xué)可以參考官方文檔

https://redis.io/topics/pipelining

redis的高可用實(shí)現(xiàn)

高可用的業(yè)務(wù)需求,當(dāng)緩存服務(wù)因?yàn)槟承┰虿豢捎脮r(shí),可以切換到另外一臺(tái)機(jī)器的的緩存服務(wù)上。

可能涉及到的難點(diǎn)

  1. 我怎么判斷緩存服務(wù)不可用
  2. 當(dāng)不可用的時(shí)候,我怎么通知到所有使用緩存服務(wù)的客戶端,現(xiàn)在你訪問的這個(gè)有問題,你應(yīng)該訪問另外一個(gè)好的
  3. 備份的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)怎么和正在使用的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)保持一致
  4. 當(dāng)我down掉的節(jié)點(diǎn)可以重新提供使用,怎么能加入到緩存,當(dāng)做備胎使用

我嘗試著對(duì)這幾個(gè)問題提出自己的思考

1 我怎么判斷緩存服務(wù)不可用

我需要知道每一個(gè)客戶端使用緩存服務(wù)的情況,假如大家都說緩存有問題,那沒問題,就換一個(gè)好的,如果至少有一半的客戶都認(rèn)為有問題,那這個(gè)緩存就有問題。像這樣的事情肯定是誰用誰知道。哈哈

2 當(dāng)緩存不可用的時(shí)候,我怎么通知到所有使用緩存服務(wù)的客戶端,現(xiàn)在你訪問的這個(gè)有問題,你應(yīng)該訪問另外一個(gè)好的

這個(gè)就要在程序部署的時(shí)候記錄一下需要使用緩存服務(wù)的client,當(dāng)要切換緩存時(shí),我就逐一通知client就行

3 備份的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)怎么和正在使用的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)保持一致

這個(gè)其實(shí)很簡(jiǎn)單,把訪問緩存的請(qǐng)求copy一份給備份的緩存就行。當(dāng)然這個(gè)操作應(yīng)該誰來做。如果是我的話,我就在client里來做,我做完一個(gè)操作,就把這個(gè)操作加到一個(gè)緩存隊(duì)列中,讓后臺(tái)線程處理這個(gè)copy操作。

4 當(dāng)我down掉的節(jié)點(diǎn)可以重新提供使用,怎么能加入到緩存,當(dāng)做備胎使用

這個(gè)有兩種方式,一種是down掉的緩存直接通知我,我活了,我想當(dāng)備胎,你看怎么辦。一種是 我每隔一段的時(shí)間對(duì)down掉的節(jié)點(diǎn)看一下,如果好了,我就將他允許他當(dāng)備胎。

現(xiàn)在看看redis怎么做的

它提出了一種類型的人:哨兵,他的的職責(zé)如下

  • 監(jiān)控。他負(fù)責(zé)檢查緩存和備胎的健康情況
  • 通知。他監(jiān)控出現(xiàn)異常的時(shí)候,可以通知管理員,或者其他程序。
  • 自動(dòng)故障恢復(fù)。當(dāng)緩存不可以時(shí),在備胎請(qǐng)求緩存的時(shí)候啟動(dòng)一個(gè)故障恢復(fù)的進(jìn)程,當(dāng)client使用緩存的時(shí)候就會(huì)被通知,你要換個(gè)備胎來用了。
  • 配置提供者。client不能直接的訪問緩存,需要先問一下這哥們我應(yīng)該訪問那個(gè)緩存。

針對(duì)上面的四個(gè)問題,看看redis是怎么做的

1 我怎么判斷緩存服務(wù)不可用

他提出了一個(gè)閾值的概念 quorum ,當(dāng)且僅當(dāng)這兩個(gè)條件滿足時(shí),才能確定一個(gè)緩存不可用

  • 有幾個(gè)哨兵同意當(dāng)前緩存不可用
  • 為了找到一個(gè)哨兵啟動(dòng)故障恢復(fù)的進(jìn)程,哨兵們需要選舉一個(gè)領(lǐng)導(dǎo),由他來執(zhí)行這個(gè)操作。

這個(gè)就有點(diǎn)坑爹了,如果是這樣部署的緩存服務(wù)

  • server001 master soilder01
  • server002 replica1 soilder02

閾值設(shè)置的是1 ,當(dāng)soilder02說 master不能使了,ok滿足第一個(gè)條件,那第二個(gè)條件是找到一個(gè)哨兵來啟動(dòng)故障恢復(fù)程序,就剩一個(gè)soilder,還怎么選舉,還需要選舉嗎?

當(dāng)然這種情況可以認(rèn)為的避免,比如可以將哨兵也可以安排在client里

  • server001 master soilder01
  • server002 replica1 soilder02
  • server003 client1 soilder03
  • server004 client2 soilder04

我把閾值設(shè)置為 1,就可以解決這個(gè)問題。

2 當(dāng)緩存不可用的時(shí)候,我怎么通知到所有使用緩存服務(wù)的客戶端,現(xiàn)在你訪問的這個(gè)有問題,你應(yīng)該訪問另外一個(gè)好的

客戶端通過哨兵來間接的訪問緩存服務(wù)。這樣做的弊端就是增加了一層網(wǎng)絡(luò)消耗。本來我直接訪問緩存拿到數(shù)據(jù)了,現(xiàn)在我需要問一下哨兵,現(xiàn)在的緩存地址是啥,我再根據(jù)這個(gè)地址訪問緩存服務(wù)。

3 備份的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)怎么和正在使用的緩存服務(wù)存儲(chǔ)的數(shù)據(jù)保持一致

當(dāng)備胎和緩存master連上時(shí),master負(fù)責(zé)備胎和自己保持一致性。

4 當(dāng)我down掉的節(jié)點(diǎn)可以重新提供使用,怎么能加入到緩存,當(dāng)做備胎使用

當(dāng)備胎和緩存master連上時(shí),master負(fù)責(zé)備胎和自己保持一致性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容