真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Redis高可用心路歷程以及多種業(yè)務(wù)場(chǎng)景下的使用模式-創(chuàng)新互聯(lián)

Redis高可用心路歷程
    • 1、單節(jié)點(diǎn)下的redis
      • 熱點(diǎn)數(shù)據(jù)的緩存
      • 計(jì)數(shù)器
      • 緩存過(guò)期時(shí)間
      • 分布式鎖
      • 單節(jié)點(diǎn)帶來(lái)的問(wèn)題
        • 1. redis單點(diǎn)發(fā)生故障,數(shù)據(jù)丟失,影響整體服務(wù)應(yīng)用
        • 2、單節(jié)點(diǎn)redis自身資源有限,無(wú)法承載更多資源分配
        • 3、并發(fā)訪問(wèn),給服務(wù)器主機(jī)帶來(lái)壓力,性能瓶頸
    • 2、主從復(fù)制
      • 主從復(fù)制的作用
      • 如何進(jìn)行主從復(fù)制
      • 什么時(shí)候進(jìn)行全量同步
      • 主從復(fù)制存在的問(wèn)題
    • 3、哨兵集群
      • 哨兵的作用
      • 集群故障恢復(fù)原理
      • 為什么是哨兵集群?
      • 哨兵集群帶來(lái)的問(wèn)題
    • 4、分片集群
      • 為什么要引入分片集群
        • 哨兵集群留下的問(wèn)題
        • 海量數(shù)據(jù)的問(wèn)題
        • 高并發(fā)寫的問(wèn)題
        • 分片集群
        • 分片集群的好處
      • 使用建議

成都創(chuàng)新互聯(lián)專注于管城企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城網(wǎng)站建設(shè)。管城網(wǎng)站建設(shè)公司,為管城等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)1、單節(jié)點(diǎn)下的redis

正常業(yè)務(wù)中數(shù)據(jù)庫(kù)承受大量的讀寫請(qǐng)求,造成數(shù)據(jù)庫(kù)壓力過(guò)大從而導(dǎo)致服務(wù)器宕機(jī)等情況時(shí)有發(fā)生,即使通過(guò)數(shù)據(jù)庫(kù)的橫向拓展,通過(guò)搭建主從復(fù)制實(shí)現(xiàn)讀寫分離或者垂直拓展實(shí)現(xiàn)分庫(kù)分表的策略,雖然都在一定程度上能夠緩解單節(jié)點(diǎn)數(shù)據(jù)庫(kù)服務(wù)器的壓力,但是隨著業(yè)務(wù)量的持續(xù)增大,通過(guò)持續(xù)投錢買服務(wù)器顯然并不是合理的方案

為了緩和CPU與內(nèi)存之間的速度差異,計(jì)算機(jī)的制造商為CPU增加了緩存,從而緩存的概念深入人心,而java程序員都不陌生的redis,在使用起來(lái)既滿足我們大部分業(yè)務(wù)需求但同時(shí)也帶了部分隱患

熱點(diǎn)數(shù)據(jù)的緩存

redis作為熱點(diǎn)數(shù)據(jù)的緩存實(shí)現(xiàn),客戶端請(qǐng)求先去redis查詢,redis沒(méi)有再去數(shù)據(jù)庫(kù)查詢,再根據(jù)結(jié)果完成緩存重建,這是最常規(guī)的redis緩存使用方式,但是同時(shí)也引出了諸多問(wèn)題

緩存穿透:客戶端請(qǐng)求的id在redis緩存中沒(méi)有,在數(shù)據(jù)庫(kù)中也沒(méi)有,短時(shí)間有大量的請(qǐng)求都會(huì)到達(dá)數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)會(huì)承受巨大的壓力甚至可能導(dǎo)致服務(wù)器宕機(jī)而redis緩存也失去了意義

解決方案:

  • 緩存空對(duì)象:當(dāng)請(qǐng)求的id在redis緩存中沒(méi)有,數(shù)據(jù)庫(kù)也查不到時(shí),返回null并且在redis緩存中存入空對(duì)象,緩存過(guò)期時(shí)間不要太長(zhǎng),存在數(shù)據(jù)的短期不一致的情況
  • 布隆過(guò)濾器:依靠redis中bitmap特殊的數(shù)據(jù)結(jié)構(gòu),可以把bitmap理解為一個(gè)巨大的二進(jìn)制數(shù)組,通過(guò)0跟1代表數(shù)據(jù)是否存在,可以提前把某個(gè)熱點(diǎn)數(shù)據(jù)的id通過(guò)一定的hash算法存儲(chǔ)到對(duì)應(yīng)的bitmap中,客戶端請(qǐng)求的id也通過(guò)同樣的hash算法后去bitmap中查找,若為1則數(shù)據(jù)一定存在,再去redis或數(shù)據(jù)庫(kù)中查找
  • 做足權(quán)限校驗(yàn)或者id基礎(chǔ)校驗(yàn),加強(qiáng)id生成規(guī)律,避免惡意請(qǐng)求

緩存擊穿:某個(gè)高并發(fā)訪問(wèn)并且緩存重建邏輯復(fù)雜的key突然過(guò)期,在緩存重建期間大量的請(qǐng)求達(dá)到數(shù)據(jù)庫(kù)導(dǎo)致服務(wù)器存在處理緩慢的情況甚至可能導(dǎo)致服務(wù)器宕機(jī)

解決方案:

  • 互斥鎖:當(dāng)a線程在redis中緩存未命中,則通過(guò)獲取redis的分布式鎖,獲取鎖成功則去數(shù)據(jù)庫(kù)中查詢數(shù)據(jù)完成緩存重建,期間b線程同樣緩存未命中,嘗試獲取互斥鎖失敗則進(jìn)入短時(shí)間的阻塞,期間通過(guò)循環(huán)嘗試獲取數(shù)據(jù),若此時(shí)a線程還未完成緩存重建,則b線程依舊不斷阻塞、查詢緩存的自旋操作,若a線程在數(shù)據(jù)庫(kù)查詢的數(shù)據(jù)為null,則緩存空對(duì)象;
  • 邏輯過(guò)期:對(duì)高并發(fā)并且緩存重建邏輯復(fù)雜的key不在redis中設(shè)置緩存過(guò)期時(shí)間,通過(guò)創(chuàng)建DTO對(duì)象,內(nèi)置邏輯過(guò)期時(shí)間字段、緩存數(shù)據(jù)字段,當(dāng)a線程查詢到數(shù)據(jù)時(shí),判斷時(shí)間字段保存的值是否小于當(dāng)前時(shí)間,如是則說(shuō)明緩存已過(guò)期,則a線程嘗試獲取redis的分布式鎖成功,并開(kāi)辟新線程去完成緩存重建,當(dāng)前a線程返回邏輯過(guò)期數(shù)據(jù)(存在數(shù)據(jù)的短期不一致問(wèn)題),此時(shí)其他線程獲取到緩存的數(shù)據(jù),判斷是邏輯過(guò)期的,也嘗試獲取互斥鎖失敗,說(shuō)明新開(kāi)辟的線程還沒(méi)有完成緩存重建,則依舊返回邏輯過(guò)期數(shù)據(jù),若新開(kāi)辟的線程查詢數(shù)據(jù)庫(kù)中的數(shù)據(jù)為null,則緩存空對(duì)象

通過(guò)對(duì)比互斥鎖與邏輯過(guò)期的解決方案,可以發(fā)現(xiàn)其實(shí)是在數(shù)據(jù)的一致性跟服務(wù)的可用性之間做抉擇,如選擇互斥鎖,則是犧牲了響應(yīng)時(shí)間,保證了數(shù)據(jù)的一致性;若選擇的事邏輯過(guò)期的方案,則是保證了服務(wù)的可用性,犧牲的數(shù)據(jù)的一致性,存在數(shù)據(jù)的短期不一致的問(wèn)題

計(jì)數(shù)器

在當(dāng)個(gè)jvm進(jìn)程中通常使用JUC(java.util.concurrent)包下的AtomicInteger類使用的cas,避免了使用synchronized帶了的性能損耗,但是在分布式集群部署下,多進(jìn)程的jvm則不能夠滿足要求。Redis6.0之前只對(duì)外提供了單線程服務(wù),即redis的所有單條命令都是原子性的,并且通過(guò)redis的單線程,可以將并行的請(qǐng)求轉(zhuǎn)換為串行執(zhí)行,依托這個(gè)特性,可以通過(guò)redis incr命令進(jìn)行一些計(jì)數(shù)的操作,并且在多進(jìn)程jvm下可見(jiàn)

常見(jiàn)的業(yè)務(wù)使用:秒殺業(yè)務(wù),比如說(shuō)某件商品的秒殺,肯定要判斷商品的庫(kù)存,依托每次都去數(shù)據(jù)庫(kù)中查詢,如果使用悲觀鎖(synchonized,數(shù)據(jù)庫(kù)中查詢庫(kù)存,如果大于0,則執(zhí)行更新操作)效率一定很低,通過(guò)改進(jìn)樂(lè)觀鎖的sql,在update時(shí)set stockNum=stockNum-1 where stockNum>0;這個(gè)策略效率肯定比悲觀鎖要好,但是如果某件商品的庫(kù)存是1w,同時(shí)有100w用戶在搶購(gòu),豈不是如此大的并發(fā)量同時(shí)落到數(shù)據(jù)庫(kù)中了嗎? 所以我們?cè)趽Q種策略,在秒殺活動(dòng)開(kāi)始前,提前把商品的庫(kù)存放入redis緩存中,通過(guò)incr -1的命令完成庫(kù)存的自減,要知道官方提供的數(shù)據(jù),redis每秒讀11w次,寫8.1w次,在庫(kù)存為0時(shí),對(duì)其他請(qǐng)求可以立刻返回失敗,其次結(jié)合lua腳本,可以同時(shí)可以判斷用戶是否已下單(滿足一人一單的需求)

緩存過(guò)期時(shí)間

使用redis命令時(shí)set nx px,可以設(shè)置緩存過(guò)期時(shí)間,通過(guò)這種緩存自動(dòng)過(guò)期的策略,可以實(shí)現(xiàn)的業(yè)務(wù)場(chǎng)景有:優(yōu)惠卷自動(dòng)過(guò)期、訂單超時(shí)未支付過(guò)期、手機(jī)驗(yàn)證碼失效的場(chǎng)景

但是如果緩存的數(shù)據(jù)沒(méi)有設(shè)置過(guò)期時(shí)間,當(dāng)達(dá)到內(nèi)存閾值瓶頸時(shí),要依托內(nèi)存淘汰策略去刪除key

分布式鎖

單節(jié)點(diǎn)的redis,獨(dú)立于多節(jié)點(diǎn)部署的jvm進(jìn)程之外,面對(duì)synchronized和ReentrantLock只在同一進(jìn)程內(nèi)有效的鎖而分布式集群下部署的jvm則失去了對(duì)共享資源爭(zhēng)奪的互斥性,多節(jié)點(diǎn)都能同時(shí)獲取鎖成功,此時(shí)需要存在多進(jìn)程jvm都可見(jiàn)的鎖,也就是分布式鎖,分布式鎖的實(shí)現(xiàn)方案業(yè)內(nèi)常見(jiàn)的redis和zookeeper;

redis分布式鎖常用的方式,依托string結(jié)構(gòu),set key value,nx:not exist 不存在則創(chuàng)建,px:設(shè)置鎖的過(guò)期時(shí)間避免死鎖

存在的問(wèn)題:

  • 死鎖:如果某一線程加鎖后,沒(méi)來(lái)得及刪除鎖,服務(wù)器就宕機(jī)了,那其他jvm進(jìn)程中的線程則再也獲取不到鎖,也就是set nx key value失敗,則要設(shè)置鎖的過(guò)期時(shí)間 ,避免死鎖

  • 鎖誤刪

    1. 為什么會(huì)存在鎖誤刪的情況,假如現(xiàn)在有abc3個(gè)線程,a線程獲取鎖并設(shè)置鎖的過(guò)期時(shí)間為10s,a線程被某個(gè)業(yè)務(wù)阻塞了,阻塞時(shí)間大于鎖的過(guò)期時(shí)間,10s后鎖自動(dòng)過(guò)期了,b線程此時(shí)獲取鎖成功(鎖的過(guò)期時(shí)間也為10s),b線程開(kāi)始執(zhí)行自己的業(yè)務(wù),就在此時(shí)a線程阻塞結(jié)束了,執(zhí)行釋放鎖的邏輯,則會(huì)把b線程加的鎖給刪除了,之后c開(kāi)始加鎖,惡性循環(huán)開(kāi)始了;
    2. 所以我們要防止鎖誤刪邏輯,就需要設(shè)置鎖表示,通過(guò)UUID + 當(dāng)前線程id,再解鎖時(shí)判斷鎖是否是自己的,有人就會(huì)問(wèn),判斷當(dāng)前線程id就足夠了,為什么還要加UUID,因?yàn)榭赡艽嬖?font color="red">不同jvm進(jìn)程剛好當(dāng)時(shí)線程id是一致的情況,所以要多設(shè)置個(gè)UUID,保證這種偶然性的出現(xiàn);
    3. 到這里問(wèn)題還沒(méi)有解決, 為了防止鎖誤刪,解鎖的操作分為:判斷鎖是否是自己的,然后在刪除鎖,那么可能會(huì)出現(xiàn)這種情況:當(dāng)前有abc線程,a線程獲取鎖 set nx px key value(UUID+threadID),執(zhí)行完業(yè)務(wù)后準(zhǔn)備釋放鎖,a線程判斷當(dāng)前的鎖是自己的,準(zhǔn)備執(zhí)行del鎖操作時(shí),a線程此時(shí)上下文切換了,或者被阻塞了,一段時(shí)間后鎖自動(dòng)過(guò)期了,此時(shí)b線程成功獲取到鎖后,a線程又上下文切換回來(lái)了,繼續(xù)向下執(zhí)行把b線程加的鎖給刪除了,又開(kāi)始惡性循環(huán)了;
    4. 必須保證判斷鎖標(biāo)識(shí)、刪除鎖的兩步操作時(shí)原子性的,此時(shí)要借助lua腳本,保證刪除鎖的操作時(shí)原子性的
  • 鎖不可重入:jvm實(shí)現(xiàn)的synchronized鎖和java api實(shí)現(xiàn)的ReentrantLock底層都維護(hù)了一個(gè)整型字段,用于鎖重入的實(shí)現(xiàn),而redis獲取鎖并沒(méi)有鎖重入的實(shí)現(xiàn),導(dǎo)致同一線程多次獲取鎖的業(yè)務(wù)無(wú)需求法實(shí)現(xiàn)

  • 獲取鎖失敗不可重試:使用set nx px 單次獲取鎖失敗立即返回失敗,不會(huì)再有重試的機(jī)會(huì),造成不能靈活的控制業(yè)務(wù),充分利用cpu

  • 主從復(fù)制引起的鎖重復(fù)添加成功的情況:為了保存redis的高可用性,搭建了主從集群,實(shí)現(xiàn)主從復(fù)制,現(xiàn)有ab線程,假設(shè)a現(xiàn)在在master 1 加鎖成功,在master1 跟slave1 數(shù)據(jù)同步前,master出現(xiàn)腦裂的情況,master突然網(wǎng)絡(luò)異常,但是仍舊是正常運(yùn)行的,sentinel集群判定該master為客觀下線后,開(kāi)始自動(dòng)故障轉(zhuǎn)移,選舉slave1為新的主節(jié)點(diǎn)master2,此時(shí)b線程在新的主節(jié)點(diǎn)又加鎖成功,此時(shí)master1和master2都存在同一個(gè)key

針對(duì)上面這些問(wèn)題,可以用redisson客戶端解決這些問(wèn)題

  • redisson 利用hash結(jié)構(gòu)記錄線程id和重入次數(shù)>,實(shí)現(xiàn)鎖的可重入

    • k1就是對(duì)應(yīng)入?yún)etName():key
    • k2對(duì)應(yīng)入?yún)etLockName(threadId):UUID+threadId
    • v對(duì)應(yīng)的是鎖的重入次數(shù)
  • 獲取鎖失敗的線程,通過(guò)訂閱釋放鎖的信號(hào),靈活控制鎖的重試等待,cpu利用率比較高,不會(huì)無(wú)限等待

  • 超時(shí)續(xù)約:利用watchDog,每隔一段時(shí)間(releaseTime /3)重置超時(shí)時(shí)間,但是只有tryLock方法中參數(shù)leaseTime釋放鎖時(shí)間為-1時(shí)才能夠啟用超時(shí)續(xù)約

  • 利用multiLock:通過(guò)搭建多個(gè)獨(dú)立的Redis節(jié)點(diǎn),必須在所有節(jié)點(diǎn)獲取到鎖才算真正的獲取鎖成功,避免主從復(fù)制帶來(lái)的重復(fù)加鎖成功的情況

單節(jié)點(diǎn)帶來(lái)的問(wèn)題 1. redis單點(diǎn)發(fā)生故障,數(shù)據(jù)丟失,影響整體服務(wù)應(yīng)用

如果部署redis服務(wù)器發(fā)生故障,如果只使用RDB的持久化策略,可能會(huì)丟失最后一次RDB后的數(shù)據(jù),并且重啟服務(wù)器的這段期間,服務(wù)都是不可用的狀態(tài),況且不清楚服務(wù)器宕機(jī)的具體原因,單節(jié)點(diǎn)下的redis并沒(méi)有故障自動(dòng)恢復(fù)的能力,導(dǎo)致長(zhǎng)時(shí)間的服務(wù)不可用,此時(shí)就需要備份數(shù)據(jù),通過(guò)冗余數(shù)據(jù)來(lái)保證服務(wù)的可用性;

2、單節(jié)點(diǎn)redis自身資源有限,無(wú)法承載更多資源分配

redis的緩存是基于內(nèi)存實(shí)現(xiàn)的,單節(jié)點(diǎn)內(nèi)存是有限的,如果內(nèi)存占滿了會(huì)啟用淘汰策略,而這個(gè)期間客戶端的連接請(qǐng)求都會(huì)超時(shí),造成服務(wù)的短暫不可用,刪除一部分緩存,刪除緩存的操作并不是我們通過(guò)業(yè)務(wù)主觀的操作,可能導(dǎo)致部分查詢緩存的業(yè)務(wù)失效,從而使大量請(qǐng)求達(dá)到數(shù)據(jù)庫(kù);隨著業(yè)務(wù)的發(fā)展,數(shù)據(jù)量的增大,當(dāng)存在單臺(tái)服務(wù)器的存儲(chǔ)上限和算力上限影響業(yè)務(wù)的正常使用,此時(shí)就需要通過(guò)一些策略去橫向拓展存儲(chǔ)和算力

3、并發(fā)訪問(wèn),給服務(wù)器主機(jī)帶來(lái)壓力,性能瓶頸

客戶端的每一個(gè)tcp連接都會(huì)消耗redis服務(wù)器的資源,雖然redis官方號(hào)稱每秒讀11w次,寫8.1w次,但是這僅僅是統(tǒng)計(jì)了理想狀態(tài)下的讀寫請(qǐng)求,并沒(méi)有其他外力因素,比如說(shuō)此時(shí)主進(jìn)程需要fork出子進(jìn)程完成RDB,或者執(zhí)行rebgwriteaof,對(duì)aof文件進(jìn)行重寫等影響redis服務(wù)器性能的操作,此時(shí)需要通過(guò)部署主從節(jié)點(diǎn),對(duì)讀寫請(qǐng)求分開(kāi)處理,從而提高redis服務(wù)器集群的響應(yīng)能力,提高整體算力,在數(shù)據(jù)量非常大的情況下,還需要通過(guò)搭建分片集群,提高redis服務(wù)集群的存儲(chǔ)上限

2、主從復(fù)制

為了提高redis的并發(fā)量,通過(guò)搭建redis的主從集群,利用讀寫分離來(lái)提高并發(fā)量;通過(guò)redis來(lái)緩存數(shù)據(jù),客戶端對(duì)redis的操作肯定是讀多寫少的情況,讀操作主從庫(kù)都可以接收,寫操作,首先到主庫(kù)上執(zhí)行,在通過(guò)主從復(fù)制同步給從庫(kù)

主從復(fù)制的作用
  • 數(shù)據(jù)冗余:冗余并不是完全不被允許的,對(duì)于數(shù)據(jù)的熱備份,通過(guò)添加多余的服務(wù)器來(lái)完成數(shù)據(jù)的熱備份,在主機(jī)節(jié)點(diǎn)宕機(jī)時(shí),可以快速地完成數(shù)據(jù)的恢復(fù),但是還是存在一定的數(shù)據(jù)丟失,因?yàn)橹鲝耐讲⒉皇菍?shí)時(shí)的,需要我們?nèi)ネㄟ^(guò)代碼策略去避免主從復(fù)制帶來(lái)數(shù)據(jù)丟失的情況(redisson的redLock、mutilLock),數(shù)據(jù)冗余是持久化之外的一種數(shù)據(jù)冗余方式。
  • 故障恢復(fù):當(dāng)主節(jié)點(diǎn)出現(xiàn)問(wèn)題時(shí),可以由從節(jié)點(diǎn)提供服務(wù),實(shí)現(xiàn)快速地故障恢復(fù),這也是一種服務(wù)的冗余
  • 負(fù)載均衡:在實(shí)現(xiàn)主從復(fù)制的基礎(chǔ)上,配合讀寫分離策略,分擔(dān)服務(wù)器負(fù)載,在讀多寫少的場(chǎng)景下,通過(guò)多個(gè)從節(jié)點(diǎn)分擔(dān)負(fù)載,可以大大提高redis服務(wù)器的并發(fā)量
  • 高可用基石:主從復(fù)制是所有中間件實(shí)現(xiàn)集群或者分片集群的高可用基礎(chǔ)
如何進(jìn)行主從復(fù)制

每臺(tái)redis服務(wù)節(jié)點(diǎn)默認(rèn)的角色都是master,可以登錄redis服務(wù)端,通過(guò)info replication命令查看當(dāng)前服務(wù)節(jié)點(diǎn)的主從關(guān)系,也可以通過(guò)slaveof ip port 主master 設(shè)置從節(jié)點(diǎn)綁定的主節(jié)點(diǎn)

主從復(fù)制是通過(guò)RBD實(shí)現(xiàn)的,分為全量復(fù)制增量復(fù)制

全量復(fù)制:

  1. 從節(jié)點(diǎn)執(zhí)行slaveof master_ip master_port 命令后,slave向master發(fā)送psync命令,同時(shí)攜帶runId、offset,每個(gè)節(jié)點(diǎn)都有自己的runId,第一次進(jìn)行主從復(fù)制發(fā)送的runId是自己的runId,offset默認(rèn)為-1,master接收到psync命令后,發(fā)現(xiàn)runId不是自己,則返回fullresync命令,并且攜帶自身的runId,以及offset(為下一次增量同步做準(zhǔn)備)
  2. master執(zhí)行bgsave命令,fork出子進(jìn)程將內(nèi)存中的快照數(shù)據(jù)保存在RBD文件中,再次期間master接收的寫命令會(huì)寫入到repl_backlog中,在全量復(fù)制完成后,在將repl_backlog的數(shù)據(jù)發(fā)送給slave
  3. slave接收到RBD文件后,會(huì)先清空本地的數(shù)據(jù),然后回放master發(fā)送的RDB文件完成數(shù)據(jù)同步

增量復(fù)制:

從節(jié)點(diǎn)向master發(fā)送psync命令,請(qǐng)求的runId是第一次全量同步時(shí)接收master的runId,以及當(dāng)前同步的offset,master接收到psync命令后,確認(rèn)runId是自己,就從repl_backlog_buffer(環(huán)形緩沖區(qū)),該緩沖區(qū)中存放了master 的offset,以及諸多slave 的salve_repl_offset,用于保存master與slave之間的數(shù)據(jù)的差異,master就將這部分差異的數(shù)據(jù)repl_backlog發(fā)送給slave

什么時(shí)候進(jìn)行全量同步
  • 主從同步時(shí),slave節(jié)點(diǎn)執(zhí)行slaveof master_ip port_ip ,發(fā)送psync,攜帶runId,offset,第一次請(qǐng)求數(shù)據(jù)同步是全量同步,master通過(guò)校驗(yàn)runId不是自己的runId,則返回fullresync命令開(kāi)始全量同步
  • 主從節(jié)點(diǎn)由于網(wǎng)絡(luò)原因斷開(kāi)連接,這期間的數(shù)據(jù)差異會(huì)在repl_backlog_buffer的環(huán)形緩沖區(qū)體現(xiàn)出來(lái),master的offset在環(huán)形緩沖區(qū)中一直領(lǐng)先于slave的slave_repl_offset,當(dāng)master的offset領(lǐng)先超過(guò)一整圈時(shí)會(huì)覆蓋slave_repl_offset,網(wǎng)絡(luò)恢復(fù),slave節(jié)點(diǎn)請(qǐng)求增量同步,但是請(qǐng)求的offset在repl_backlog_buffer已經(jīng)找不到了,此時(shí)要進(jìn)行全量同步
主從復(fù)制存在的問(wèn)題

1、搭建主從集群后,Slave節(jié)點(diǎn)宕機(jī)恢復(fù)后可以找master節(jié)點(diǎn)同步數(shù)據(jù),那master節(jié)點(diǎn)宕機(jī)怎么辦?

2、Master宕機(jī)期間,重啟數(shù)據(jù)恢復(fù)期間,都不能接收客戶端的寫請(qǐng)求該怎么辦?

3、腦裂以及redis的數(shù)據(jù)丟失

  1. 異步復(fù)制導(dǎo)致的數(shù)據(jù)丟失
    ? 因?yàn)橹鲝膹?fù)制是通過(guò)bgsave進(jìn)行的復(fù)制是異步的,所以可能有部分?jǐn)?shù)據(jù)還沒(méi)復(fù)制到slave,master就宕機(jī)了,此時(shí)這些部分?jǐn)?shù)據(jù)就丟失了

  2. 腦裂導(dǎo)致的數(shù)據(jù)丟失
    腦裂,主從集群中,master如果網(wǎng)絡(luò)異常,被哨兵集群判定為客觀下線,但是實(shí)際上master還運(yùn)行著,開(kāi)啟選舉,將最接近master的slave節(jié)點(diǎn)通過(guò)slave no one 將slave切換成主節(jié)點(diǎn),其他slave執(zhí)行slaveof ip port完成主從切換,此時(shí)整個(gè)集群就會(huì)有兩個(gè)master;
    此時(shí)雖然某個(gè)slave被切換成了master,但是可能client還沒(méi)來(lái)得及切換到新的master,還繼續(xù)寫向舊master的數(shù)據(jù)可能也丟失了,因此舊master再次恢復(fù)的時(shí)候,會(huì)被作為一個(gè)slave掛到新的master上去,自己的數(shù)據(jù)會(huì)清空,重新從新的master復(fù)制數(shù)據(jù)

3、哨兵集群

使用redis主從集群架構(gòu)后,實(shí)現(xiàn)讀寫分離,但是不能夠保證主節(jié)點(diǎn)宕機(jī)后依舊能夠響應(yīng)客戶端請(qǐng)求,當(dāng)然我們可以通過(guò)人工的方式手動(dòng)執(zhí)行 slaveof no one去完成slave切換為master,然后通過(guò)slaveof ip port命令去告知其他從節(jié)點(diǎn)更換了新的master,但是我們更希望的是提供故障的自動(dòng)解決,如果由人工完成,則需要增加人力成本,且容易產(chǎn)生人工錯(cuò)誤,還會(huì)造成一段時(shí)間的程序不可用;當(dāng)master節(jié)點(diǎn)異常時(shí)自動(dòng)從多個(gè)slave中選舉出最接近master節(jié)點(diǎn)的新master,redis為我們提供了哨兵集群,保證Redis的高可用,使得系統(tǒng)更加健壯

哨兵的作用
  • 監(jiān)聽(tīng):哨兵集群會(huì)監(jiān)聽(tīng)主從節(jié)點(diǎn)的狀況,通過(guò)每秒發(fā)送一次ping確認(rèn)整個(gè)主從集群中的每個(gè)節(jié)點(diǎn)是否能夠正常響應(yīng)
  • 故障轉(zhuǎn)移(failover):當(dāng)確認(rèn)master節(jié)點(diǎn)客觀下線后,自動(dòng)從slave選舉出新的節(jié)點(diǎn)
  • 告知:Sentinel充當(dāng)Redis客戶端的服務(wù)發(fā)現(xiàn)來(lái)源,當(dāng)集群發(fā)生故障轉(zhuǎn)移時(shí),會(huì)將最新信息推送給Redis的客戶端(將從節(jié)點(diǎn)切換為主節(jié)點(diǎn),而從節(jié)點(diǎn)是負(fù)責(zé)讀,主節(jié)點(diǎn)負(fù)責(zé)寫,在節(jié)點(diǎn)切換后需要通知java客戶端)
集群故障恢復(fù)原理

會(huì)從slave集群中選擇與master數(shù)據(jù)最接近的slave作為新的master節(jié)點(diǎn),一旦發(fā)現(xiàn)master故障,sentinel需要在salve中選擇一個(gè)作為新的master,選擇依據(jù)是這樣的:

  • 首先會(huì)判斷slave節(jié)點(diǎn)與master節(jié)點(diǎn)斷開(kāi)時(shí)間長(zhǎng)短,如果超過(guò)指定值(down-after-milliseconds * 10)則會(huì)排除該slave節(jié)點(diǎn)
  • 然后判斷slave節(jié)點(diǎn)的slave-priority值,越小優(yōu)先級(jí)越高,如果是0則永不參與選舉
  • 如果slave-prority一樣,則判斷slave節(jié)點(diǎn)的offset值,越大說(shuō)明數(shù)據(jù)越新,優(yōu)先級(jí)越高
  • 最后是判斷slave節(jié)點(diǎn)的運(yùn)行id大小,越小優(yōu)先級(jí)越高。

當(dāng)選出一個(gè)新的master后,該如何實(shí)現(xiàn)切換呢?

流程如下:

  • sentinel給備選的slave1節(jié)點(diǎn)發(fā)送slaveof no one命令,讓該節(jié)點(diǎn)成為master
  • sentinel給所有其它slave發(fā)送slaveof ip port 命令,讓這些slave成為新master的從節(jié)點(diǎn),開(kāi)始從新的master上同步數(shù)據(jù)。
  • 最后,sentinel將故障節(jié)點(diǎn)標(biāo)記為slave,當(dāng)故障節(jié)點(diǎn)恢復(fù)后會(huì)自動(dòng)成為新的master的slave節(jié)點(diǎn)
為什么是哨兵集群?
  • 首先哨兵本身也有單點(diǎn)故障的問(wèn)題,所以在一個(gè)一主多從的Redis系統(tǒng)中,可以使用多個(gè)哨兵進(jìn)行監(jiān)控,哨兵不僅會(huì)監(jiān)控主數(shù)據(jù)庫(kù)和從數(shù)據(jù)庫(kù),哨兵之間也會(huì)相互監(jiān)控。每一個(gè)哨兵都是一個(gè)獨(dú)立的進(jìn)程,作為進(jìn)程,它會(huì)獨(dú)立運(yùn)行;
  • 哨兵集群必須部署2個(gè)以上節(jié)點(diǎn),因?yàn)楫?dāng)一個(gè)哨兵發(fā)現(xiàn)master節(jié)點(diǎn)未響應(yīng)判定該master為主觀下線,此時(shí)就需要其他哨兵節(jié)點(diǎn)去監(jiān)測(cè)master節(jié)點(diǎn)的情況,需要達(dá)到設(shè)定的quorum值,才能將該節(jié)點(diǎn)設(shè)定為客觀下線,此時(shí)才能夠從哨兵集群中選舉出leader(第一個(gè)發(fā)現(xiàn)master主觀下線的哨兵節(jié)點(diǎn))去完成故障自動(dòng)轉(zhuǎn)移;
  • 如果哨兵集群僅僅部署了個(gè)2個(gè)哨兵實(shí)例,那么它的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),如果其中一個(gè)哨兵宕機(jī)了,就無(wú)法滿足majority>=2這個(gè)條件,那么在master發(fā)生故障的時(shí)候也就無(wú)法進(jìn)行主從切換
哨兵集群帶來(lái)的問(wèn)題
  • 是一種中心化的集群實(shí)現(xiàn)方案:始終只有一個(gè)Redis主機(jī)來(lái)接收和處理寫請(qǐng)求,寫操作受單機(jī)瓶頸影響。
  • 集群里所有節(jié)點(diǎn)保存的都是全量數(shù)據(jù),浪費(fèi)內(nèi)存空間,沒(méi)有真正實(shí)現(xiàn)分布式存儲(chǔ)。數(shù)據(jù)量過(guò)大時(shí),主從同步嚴(yán)重影響master的性能。
  • Redis主機(jī)宕機(jī)后,哨兵模式正在投票選舉的情況之外,因?yàn)橥镀边x舉結(jié)束之前,誰(shuí)也不知道主機(jī)和從機(jī)是誰(shuí),此時(shí)Redis也會(huì)開(kāi)啟保護(hù)機(jī)制,禁止寫操作,直到選舉出了新的Redis主機(jī)。

主從模式或哨兵模式每個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)都是全量的數(shù)據(jù),數(shù)據(jù)量過(guò)大時(shí),就需要對(duì)存儲(chǔ)的數(shù)據(jù)進(jìn)行分片后存儲(chǔ)到多個(gè)redis實(shí)例上。此時(shí)就要用到Redis Sharding技術(shù)。

4、分片集群 為什么要引入分片集群 哨兵集群留下的問(wèn)題

Redis的master宕機(jī)后,在主從切換的過(guò)程中,Redis開(kāi)啟了保護(hù)機(jī)制,禁止一切的寫操作,直到選舉出新的Redis主節(jié)點(diǎn)

海量數(shù)據(jù)的問(wèn)題

為了提供主從同步的性能,我們通過(guò)不會(huì)將的redis的master內(nèi)存設(shè)置得太高,如果內(nèi)存設(shè)置得太高,在一定頻率下進(jìn)行RDB持久化或者多從節(jié)點(diǎn)進(jìn)行全量同步時(shí)會(huì)有很多進(jìn)程爭(zhēng)奪的磁盤帶寬,并且redis的master主節(jié)點(diǎn)內(nèi)存過(guò)大還會(huì)導(dǎo)致fork出子進(jìn)程時(shí)阻塞的時(shí)間過(guò)長(zhǎng),此時(shí)無(wú)法接受客戶端的寫請(qǐng)求。

但是如果降低master節(jié)點(diǎn)的內(nèi)存上限,此時(shí)還有海量數(shù)據(jù)該如何存儲(chǔ)?

高并發(fā)寫的問(wèn)題

我們通過(guò)搭建主從集群、哨兵集群來(lái)保證服務(wù)的高可用,并且為了適應(yīng)讀多寫少的情況,通過(guò)讀寫分離分擔(dān)master服務(wù)器壓力,來(lái)解決高并發(fā)讀的問(wèn)題,并且從節(jié)點(diǎn)故障恢復(fù)后可以通過(guò)主從復(fù)制中的全量同步或者增量同步來(lái)保證數(shù)據(jù)的一致性,主節(jié)點(diǎn)宕機(jī)后通過(guò)哨兵集群完成服務(wù)的自動(dòng)故障轉(zhuǎn)移,保證讀的可靠性,但是高并發(fā)寫的問(wèn)題依舊沒(méi)有解決

分片集群

其他中間件也是通過(guò)主從復(fù)制來(lái)解決高并發(fā)讀的問(wèn)題,通過(guò)多主多從來(lái)解決高并發(fā)寫的問(wèn)題,在redis中提供了分片集群也是以多主多從的形式來(lái)解決高并發(fā)寫的問(wèn)題

使用分片集群與之前的主從集群、哨兵集群的區(qū)別:

  • 集群中有多個(gè)master,每個(gè)master保存的不同的數(shù)據(jù),注意使用分片集群后<數(shù)據(jù)是跟著插槽走的,不會(huì)因?yàn)槊看芜B接到不同的master節(jié)點(diǎn)后導(dǎo)致出現(xiàn)數(shù)據(jù)查詢不到的問(wèn)題,每個(gè)master可以通過(guò)主從復(fù)制有多個(gè)slave節(jié)點(diǎn);多主多從后可以解決海量數(shù)據(jù)存儲(chǔ)的問(wèn)題,并且當(dāng)個(gè)master redis節(jié)點(diǎn)的內(nèi)存也不用設(shè)置得太高,同時(shí)通過(guò)多個(gè)master節(jié)點(diǎn)可以將高并發(fā)的寫請(qǐng)求通過(guò)負(fù)載均衡分散到多個(gè)master節(jié)點(diǎn),解決高并發(fā)寫的問(wèn)題
  • 使用分片集群后就不需要用到哨兵集群了,因?yàn)閙aster之間通過(guò)ping來(lái)監(jiān)測(cè)著彼此的健康狀態(tài),master同時(shí)也扮演著哨兵的角色,某一個(gè)master宕機(jī), 其他的master也會(huì)進(jìn)行投票,從主觀下線到客觀下線的一個(gè)過(guò)程,最后完成主從的切換
  • 分片集群采用虛擬哈希槽分區(qū)而非一致性hash算法,預(yù)先分配一些卡槽,所有的key根據(jù)哈希函數(shù)映射到這些槽內(nèi),每一個(gè)分區(qū)的master節(jié)點(diǎn)負(fù)責(zé)維護(hù)一部分槽以及槽鎖映射的鍵
分片集群的好處
  • 分片集群完全是去中心化的思想,采用多主多從的模式,所有的節(jié)點(diǎn)彼此通過(guò)ping來(lái)相互監(jiān)測(cè)健康狀態(tài),內(nèi)部使用二進(jìn)制協(xié)議優(yōu)化傳輸速度和網(wǎng)絡(luò)帶寬
  • 客戶端與分片redis集群中的某個(gè)節(jié)點(diǎn)直連,具體看key通過(guò)crc16算法計(jì)算出在哪個(gè)插槽對(duì)應(yīng)的哪個(gè)redis節(jié)點(diǎn),客戶端不需要連接集群中的所有節(jié)點(diǎn)
  • 全量數(shù)據(jù)分布在0~16383插槽上,總共16384個(gè)插槽,如果是3主3從模式,則會(huì)把16384個(gè)插槽分配在3個(gè)主節(jié)點(diǎn)上稱作3個(gè)分配,同時(shí)主節(jié)點(diǎn)又會(huì)跟從節(jié)點(diǎn)進(jìn)行主從復(fù)制同步數(shù)據(jù);每個(gè)主節(jié)點(diǎn)負(fù)責(zé)維護(hù)一部分槽,以及槽鎖映射的鍵值數(shù)據(jù),集群中每個(gè)節(jié)點(diǎn)都有全部插槽的信息,通過(guò)插槽每個(gè)node結(jié)點(diǎn)都知道數(shù)據(jù)具體存儲(chǔ)到哪個(gè)node上,通過(guò)crc16算法計(jì)算出key如果不在本分片,在會(huì)路由到其他分片
使用建議

主從集群:數(shù)據(jù)量不大,業(yè)務(wù)中只需要滿足讀寫分離,并且對(duì)服務(wù)的可用性不高,允許短暫的服務(wù)不可用帶來(lái)的風(fēng)險(xiǎn),并且需要手動(dòng)完成主從切換,則單使用主從集群完全夠用

哨兵集群:數(shù)據(jù)量不大,并且對(duì)服務(wù)的可用性要求比較高,可以使用主從集群搭配哨兵集群,完成故障的自動(dòng)轉(zhuǎn)移,主節(jié)點(diǎn)不可用時(shí)自動(dòng)完成主從切換

分片集群:主要針對(duì)海量數(shù)據(jù)、高并發(fā)、高可用的場(chǎng)景

以上便是Redis在多種業(yè)務(wù)場(chǎng)景下的使用方案,如有誤解,請(qǐng)?jiān)谠u(píng)論區(qū)指出,謝謝

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)頁(yè)標(biāo)題:Redis高可用心路歷程以及多種業(yè)務(wù)場(chǎng)景下的使用模式-創(chuàng)新互聯(lián)
文章出自:http://weahome.cn/article/dhecid.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部