1. 程式人生 > 資料庫 >Redis高階-資料刪除淘汰策略、主從複製流程、哨兵模式、叢集結構、企業級解決方案

Redis高階-資料刪除淘汰策略、主從複製流程、哨兵模式、叢集結構、企業級解決方案

學習目標

目標1:能夠說出redis中的資料刪除策與略淘汰策略

目標2:能夠說出主從複製的概念,工作流程以及場景問題及解決方案

目標3:能夠說出哨兵的作用以及工作原理,以及如何啟用哨兵

目標4:能夠說出叢集的架構設計,完成叢集的搭建

目標5:能夠說出快取預熱,雪崩,擊穿,穿透的概念,能說出redis的相關監控指標

1.資料刪除與淘汰策略

1.1 過期資料

1.1.1 Redis中的資料特徵

Redis是一種記憶體級資料庫,所有資料均存放在記憶體中,記憶體中的資料可以通過TTL指令獲取其狀態

TTL返回的值有三種情況:正數,-1,-2

  • 正數:代表該資料在記憶體中還能存活的時間
  • -1:永久有效的資料
  • -2 :已經過期的資料 或被刪除的資料 或 未定義的資料

刪除策略就是針對已過期資料的處理策略,已過期的資料是真的就立即刪除了嗎?其實也不是,我們會有多種刪除策略,是分情況的,在不同的場景下使用不同的刪除方式會有不同效果,這也正是我們要將的資料的刪除策略的問題

1.1.2 時效性資料的儲存結構

在Redis中,如何給資料設定它的失效週期呢?資料的時效在redis中如何儲存呢?看下圖:

在這裡插入圖片描述

過期資料是一塊獨立的儲存空間,Hash結構,field是記憶體地址,value是過期時間,儲存了所有key的過期描述,在最終進行過期處理的時候,對該空間的資料進行檢測, 當時間到期之後通過field找到記憶體該地址處的資料,然後進行相關操作。

1.2 資料刪除策略

1.2.1 資料刪除策略的目標

在記憶體佔用與CPU佔用之間尋找一種平衡,顧此失彼都會造成整體redis效能的下降,甚至引發伺服器宕機或 記憶體洩露

針對過期資料要進行刪除的時候都有哪些刪除策略呢?

  • 1.定時刪除
  • 2.惰性刪除
  • 3.定期刪除

1.2.2 定時刪除

建立一個定時器,當key設定有過期時間,且過期時間到達時,由定時器任務立即執行對鍵的刪除操作

  • 優點:節約記憶體,到時就刪除,快速釋放掉不必要的記憶體佔用
  • 缺點:CPU壓力很大,無論CPU此時負載量多高,均佔用CPU,會影響redis伺服器響應時間和指令吞吐量
  • 總結:用處理器效能換取儲存空間(拿時間換空間)

在這裡插入圖片描述

1.2.3 惰性刪除

資料到達過期時間,不做處理。等下次訪問該資料時,我們需要判斷

  1. 如果未過期,返回資料
  2. 發現已過期,刪除,返回不存在
  • 優點:節約CPU效能,發現必須刪除的時候才刪除
  • 缺點:記憶體壓力很大,出現長期佔用記憶體的資料
  • 總結:用儲存空間換取處理器效能(拿空間換時間)

在這裡插入圖片描述

1.2.4 定期刪除

定時刪除和惰性刪除這兩種方案都是走的極端,那有沒有折中方案?

我們來講redis的定期刪除方案:

  • Redis啟動伺服器初始化時,讀取配置server.hz的值,預設為10

  • 每秒鐘執行server.hz次serverCron()-------->databasesCron()--------->activeExpireCycle()

  • **activeExpireCycle()**對每個expires[*]逐一進行檢測,每次執行耗時:250ms/server.hz

  • 對某個expires[*]檢測時,隨機挑選W個key檢測

  如果key超時,刪除key

  如果一輪中刪除的key的數量>W*25%,迴圈該過程

  如果一輪中刪除的key的數量≤W*25%,檢查下一個expires[*],0-15迴圈

  W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP屬性值
  • 引數current_db用於記錄activeExpireCycle() 進入哪個expires[*] 執行

  • 如果activeExpireCycle()執行時間到期,下次從current_db繼續向下執行

在這裡插入圖片描述

總的來說:定期刪除就是週期性輪詢redis庫中的時效性資料,採用隨機抽取的策略,利用過期資料佔比的方式控制刪除頻度

  • 特點1:CPU效能佔用設定有峰值,檢測頻度可自定義設定
  • 特點2:記憶體壓力不是很大,長期佔用記憶體的冷資料會被持續清理
  • 總結:週期性抽查儲存空間(隨機抽查,重點抽查)

1.2.5 刪除策略對比

1:定時刪除:

節約記憶體,無佔用,
不分時段佔用CPU資源,頻度高,
拿時間換空間

2:惰性刪除:

記憶體佔用嚴重
延時執行,CPU利用率高
拿空間換時間

3:定期刪除:

記憶體定期隨機清理
每秒花費固定的CPU資源維護記憶體
隨機抽查,重點抽查

1.3 資料淘汰策略(逐出演算法)

1.3.1 淘汰策略概述

什麼叫資料淘汰策略?什麼樣的應用場景需要用到資料淘汰策略?

當新資料進入redis時,如果記憶體不足怎麼辦?在執行每一個命令前,會呼叫**freeMemoryIfNeeded()**檢測記憶體是否充足。如果記憶體不滿足新 加入資料的最低儲存要求,redis要臨時刪除一些資料為當前指令清理儲存空間。清理資料的策略稱為逐出演算法。

注意:逐出資料的過程不是100%能夠清理出足夠的可使用的記憶體空間,如果不成功則反覆執行。當對所有資料嘗試完畢, 如不能達到記憶體清理的要求,將出現錯誤資訊如下

(error) OOM command not allowed when used memory >'maxmemory'

1.3.2 策略配置

影響資料淘汰的相關配置如下:

1:最大可使用記憶體,即佔用實體記憶體的比例,預設值為0,表示不限制。生產環境中根據需求設定,通常設定在50%以上

maxmemory ?mb

2:每次選取待刪除資料的個數,採用隨機獲取資料的方式作為待檢測刪除資料

maxmemory-samples count

3:對資料進行刪除的選擇策略

maxmemory-policy policy

那資料刪除的策略policy到底有幾種呢?一共是3類8種

第一類:檢測易失資料(可能會過期的資料集server.db[i].expires )

volatile-lru:挑選最近最少使用的資料淘汰
volatile-lfu:挑選最近使用次數最少的資料淘汰
volatile-ttl:挑選將要過期的資料淘汰
volatile-random:任意選擇資料淘汰

在這裡插入圖片描述

第二類:檢測全庫資料(所有資料集server.db[i].dict )

allkeys-lru:挑選最近最少使用的資料淘汰
allkeLyRs-lfu::挑選最近使用次數最少的資料淘汰
allkeys-random:任意選擇資料淘汰,相當於隨機

第三類:放棄資料驅逐

no-enviction(驅逐):禁止驅逐資料(redis4.0中預設策略),會引發OOM(Out Of Memory)

注意:這些策略是配置到哪個屬性上?怎麼配置?如下所示

maxmemory-policy volatile-lru

資料淘汰策略配置依據

使用INFO命令輸出監控資訊,查詢快取 hit 和 miss 的次數,根據業務需求調優Redis配置

2 主從複製

2.1 主從複製簡介

2.1.1 高可用

首先我們要理解網際網路應用因為其獨有的特性我們演化出的三高架構

  • 高併發

    應用要提供某一業務要能支援很多客戶端同時訪問的能力,我們稱為併發,高併發意思就很明確了

  • 高效能

    效能帶給我們最直觀的感受就是:速度快,時間短

  • 高可用

可用性:一年中應用服務正常執行的時間佔全年時間的百分比

應用服務在全年宕機的時間加在一起就是全年應用服務不可用的時間,然後我們可以得到應用服務全年可用的時間

4小時27分15秒+11分36秒+2分16秒=4小時41分7秒=16867秒

1年=3652460*60=31536000秒

可用性=(31536000-16867)/31536000*100%=99.9465151%

業界可用性目標5個9,即99.999%,即伺服器年宕機時長低於315秒,約5.25分鐘

2.1.2 主從複製概念

知道了三高的概念之後,我們想:你的“Redis”是否高可用?那我們要來分析單機redis的風險與問題

問題1.機器故障

  • 現象:硬碟故障、系統崩潰
  • 本質:資料丟失,很可能對業務造成災難性打擊
  • 結論:基本上會放棄使用redis.

問題2.容量瓶頸

  • 現象:記憶體不足,從16G升級到64G,從64G升級到128G,無限升級記憶體
  • 本質:窮,硬體條件跟不上
  • 結論:放棄使用redis

結論:

為了避免單點Redis伺服器故障,準備多臺伺服器,互相連通。將資料複製多個副本儲存在不同的伺服器上,連線在一起,並保證資料是同步的。即使有其中一臺伺服器宕機,其他伺服器依然可以繼續提供服務,實現Redis的高可用,同時實現資料冗餘備份。

多臺伺服器連線方案:

在這裡插入圖片描述

  • 提供資料方:master

主伺服器,主節點,主庫主客戶端

  • 接收資料方:slave

從伺服器,從節點,從庫

從客戶端

  • 需要解決的問題:

資料同步(master的資料複製到slave中)

這裡我們可以來解釋主從複製的概念:

概念:主從複製即將master中的資料即時、有效的複製到slave中

特徵:一個master可以擁有多個slave,一個slave只對應一個master

職責:master和slave各自的職責不一樣

master:

寫資料

執行寫操作時,將出現變化的資料自動同步到slave

讀資料(可忽略)

slave:

讀資料

寫資料(禁止)

2.1.3 主從複製的作用

  • 讀寫分離:master寫、slave讀,提高伺服器的讀寫負載能力
  • 負載均衡:基於主從結構,配合讀寫分離,由slave分擔master負載,並根據需求的變化,改變slave的數 量,通過多個從節點分擔資料讀取負載,大大提高Redis伺服器併發量與資料吞吐量
  • 故障恢復:當master出現問題時,由slave提供服務,實現快速的故障恢復
  • 資料冗餘:實現資料熱備份,是持久化之外的一種資料冗餘方式
  • 高可用基石:基於主從複製,構建哨兵模式與叢集,實現Redis的高可用方案

2.2 主從複製工作流程

主從複製過程大體可以分為3個階段

  • 建立連線階段(即準備階段)
  • 資料同步階段
  • 命令傳播階段(反覆同步)

在這裡插入圖片描述

而命令的傳播其實有4種,分別如下:

在這裡插入圖片描述

2.2.1 主從複製的工作流程(三個階段)

2.2.1.1 階段一:建立連線

建立slave到master的連線,使master能夠識別slave,並儲存slave埠號

流程如下:

  1. 步驟1:設定master的地址和埠,儲存master資訊
  2. 步驟2:建立socket連線
  3. 步驟3:傳送ping命令(定時器任務)
  4. 步驟4:身份驗證
  5. 步驟5:傳送slave埠資訊

至此,主從連線成功!

當前狀態:

slave:儲存master的地址與埠

master:儲存slave的埠

總體:之間建立了連線的socket

在這裡插入圖片描述

master和slave互聯

接下來就要通過某種方式將master和slave連線到一起

方式一:客戶端傳送命令

slaveof masterip masterport

方式二:啟動伺服器引數

redis-server --slaveof masterip masterport

方式三:伺服器配置(主流方式

slaveof masterip masterport

slave系統資訊

master_link_down_since_seconds
masterhost & masterport

master系統資訊

uslave_listening_port(多個)

主從斷開連線

斷開slave與master的連線,slave斷開連線後,不會刪除已有資料,只是不再接受master傳送的資料

slaveof no one

授權訪問

master客戶端傳送命令設定密碼

requirepass password

master配置檔案設定密碼

config set requirepass password
config get requirepass

slave客戶端傳送命令設定密碼

auth password

slave配置檔案設定密碼

masterauth password

slave啟動伺服器設定密碼

redis-server –a password
2.2.1.2 階段二:資料同步
  • 在slave初次連線master後,複製master中的所有資料到slave
  • 將slave的資料庫狀態更新成master當前的資料庫狀態

同步過程如下:

  1. 步驟1:請求同步資料
  2. 步驟2:建立RDB同步資料
  3. 步驟3:恢復RDB同步資料
  4. 步驟4:請求部分同步資料
  5. 步驟5:恢復部分同步資料

至此,資料同步工作完成!

當前狀態:

slave:具有master端全部資料,包含RDB過程接收的資料

master:儲存slave當前資料同步的位置

總體:之間完成了資料克隆

在這裡插入圖片描述

資料同步階段master說明

1:如果master資料量巨大,資料同步階段應避開流量高峰期,避免造成master阻塞,影響業務正常執行

2:複製緩衝區大小設定不合理,會導致資料溢位。如進行全量複製週期太長,進行部分複製時發現數據已經存在丟失的情況,必須進行第二次全量複製,致使slave陷入死迴圈狀態。

repl-backlog-size ?mb
  1. master單機記憶體佔用主機記憶體的比例不應過大,建議使用50%-70%的記憶體,留下30%-50%的記憶體用於執 行bgsave命令和建立複製緩衝區

在這裡插入圖片描述

資料同步階段slave說明

  1. 為避免slave進行全量複製、部分複製時伺服器響應阻塞或資料不同步,建議關閉此期間的對外服務
   slave-serve-stale-data yes|no
  1. 資料同步階段,master傳送給slave資訊可以理解master是slave的一個客戶端,主動向slave傳送命令

  2. 多個slave同時對master請求資料同步,master傳送的RDB檔案增多,會對頻寬造成巨大沖擊,如果master頻寬不足,因此資料同步需要根據業務需求,適量錯峰

  3. slave過多時,建議調整拓撲結構,由一主多從結構變為樹狀結構,中間的節點既是master,也是 slave。注意使用樹狀結構時,由於層級深度,導致深度越高的slave與最頂層master間資料同步延遲 較大,資料一致性變差,應謹慎選擇

2.2.1.3 階段三:命令傳播
  • 當master資料庫狀態被修改後,導致主從伺服器資料庫狀態不一致,此時需要讓主從資料同步到一致的狀態,同步的動作稱為命令傳播
  • master將接收到的資料變更命令傳送給slave,slave接收命令後執行命令

命令傳播階段的部分複製

命令傳播階段出現了斷網現象:

網路閃斷閃連:忽略

短時間網路中斷:部分複製

長時間網路中斷:全量複製

這裡我們主要來看部分複製,部分複製的三個核心要素

  1. 伺服器的執行 id(run id)
  2. 主伺服器的複製積壓緩衝區
  3. 主從伺服器的複製偏移量
  • 伺服器執行ID(runid)
概念:伺服器執行ID是每一臺伺服器每次執行的身份識別碼,一臺伺服器多次執行可以生成多個執行id

組成:執行id由40位字元組成,是一個隨機的十六進位制字元
例如:fdc9ff13b9bbaab28db42b3d50f852bb5e3fcdce

作用:執行id被用於在伺服器間進行傳輸,識別身份
如果想兩次操作均對同一臺伺服器進行,必須每次操作攜帶對應的執行id,用於對方識別

實現方式:執行id在每臺伺服器啟動時自動生成的,master在首次連線slave時,會將自己的執行ID傳送給slave,
slave儲存此ID,通過info Server命令,可以檢視節點的runid
  • 複製緩衝區
概念:複製緩衝區,又名複製積壓緩衝區,是一個先進先出(FIFO)的佇列,用於儲存伺服器執行過的命令,每次傳播命令,master都會將傳播的命令記錄下來,並存儲在複製緩衝區
	複製緩衝區預設資料儲存空間大小是1M
	當入隊元素的數量大於佇列長度時,最先入隊的元素會被彈出,而新元素會被放入佇列
作用:用於儲存master收到的所有指令(僅影響資料變更的指令,例如set,select)

資料來源:當master接收到主客戶端的指令時,除了將指令執行,會將該指令儲存到緩衝區中

在這裡插入圖片描述

複製緩衝區內部工作原理:

組成

  • 偏移量

    概念:一個數字,描述複製緩衝區中的指令位元組位置

    分類:

    • master複製偏移量:記錄傳送給所有slave的指令位元組對應的位置(多個)
    • slave複製偏移量:記錄slave接收master傳送過來的指令位元組對應的位置(一個)

    作用:同步資訊,比對master與slave的差異,當slave斷線後,恢復資料使用

    資料來源:

    • master端:傳送一次記錄一次
    • slave端:接收一次記錄一次
  • 位元組值

工作原理

  • 通過offset區分不同的slave當前資料傳播的差異
  • master記錄已傳送的資訊對應的offset
  • slave記錄已接收的資訊對應的offset

在這裡插入圖片描述

2.2.2 流程更新(全量複製/部分複製)

我們再次的總結一下主從複製的三個階段的工作流程:

在這裡插入圖片描述

2.2.3 心跳機制

什麼是心跳機制?

進入命令傳播階段候,master與slave間需要進行資訊交換,使用心跳機制進行維護,實現雙方連線保持線上

master心跳:

  • 內部指令:PING
  • 週期:由repl-ping-slave-period決定,預設10秒
  • 作用:判斷slave是否線上
  • 查詢:INFO replication 獲取slave最後一次連線時間間隔,lag項維持在0或1視為正常

slave心跳任務

  • 內部指令:REPLCONF ACK {offset}
  • 週期:1秒
  • 作用1:彙報slave自己的複製偏移量,獲取最新的資料變更指令
  • 作用2:判斷master是否線上

心跳階段注意事項:

  • 當slave多數掉線,或延遲過高時,master為保障資料穩定性,將拒絕所有資訊同步
min-slaves-to-write 2
min-slaves-max-lag 8

slave數量少於2個,或者所有slave的延遲都大於等於8秒時,強制關閉master寫功能,停止資料同步

  • slave數量由slave傳送REPLCONF ACK命令做確認

  • slave延遲由slave傳送REPLCONF ACK命令做確認

至此:我們可以總結出完整的主從複製流程:

在這裡插入圖片描述

2.3 主從複製常見問題

2.3.1 頻繁的全量複製

  • 伴隨著系統的執行,master的資料量會越來越大,一旦master重啟,runid將發生變化,會導致全部slave的全量複製操作

內部優化調整方案:

1:master內部建立master_replid變數,使用runid相同的策略生成,長度41位,併發送給所有slave

2:在master關閉時執行命令shutdown save,進行RDB持久化,將runid與offset儲存到RDB檔案中

repl-id  repl-offset

通過redis-check-rdb命令可以檢視該資訊

3:master重啟後加載RDB檔案,恢復資料,重啟後,將RDB檔案中儲存的repl-id與repl-offset載入到記憶體中

master_repl_id=repl  master_repl_offset =repl-offset

通過info命令可以檢視該資訊

作用:本機儲存上次runid,重啟後恢復該值,使所有slave認為還是之前的master

  • 第二種出現頻繁全量複製的問題現象:網路環境不佳,出現網路中斷,slave不提供服務

問題原因:複製緩衝區過小,斷網後slave的offset越界,觸發全量複製

最終結果:slave反覆進行全量複製

解決方案:修改複製緩衝區大小

repl-backlog-size ?mb

建議設定如下:

1.測算從master到slave的重連平均時長second

2.獲取master平均每秒產生寫命令資料總量write_size_per_second

3.最優複製緩衝區空間 = 2 * second * write_size_per_second

2.3.2 頻繁的網路中斷

  • 問題現象:master的CPU佔用過高 或 slave頻繁斷開連線

問題原因

slave每1秒傳送REPLCONFACK命令到master

當slave接到了慢查詢時(keys * ,hgetall等),會大量佔用CPU效能

master每1秒呼叫複製定時函式replicationCron(),比對slave發現長時間沒有進行響應

最終結果:master各種資源(輸出緩衝區、頻寬、連線等)被嚴重佔用

解決方案:通過設定合理的超時時間,確認是否釋放slave

repl-timeout seconds

該引數定義了超時時間的閾值(預設60秒),超過該值,釋放slave

  • 問題現象:slave與master連線斷開

問題原因

master傳送ping指令頻度較低

master設定超時時間較短

ping指令在網路中存在丟包

解決方案:提高ping指令傳送的頻度

repl-ping-slave-period seconds

超時時間repl-time的時間至少是ping指令頻度的5到10倍,否則slave很容易判定超時

2.3.3 資料不一致

問題現象:多個slave獲取相同資料不同步

問題原因:網路資訊不同步,資料傳送有延遲

解決方案

優化主從間的網路環境,通常放置在同一個機房部署,如使用阿里雲等雲伺服器時要注意此現象

監控主從節點延遲(通過offset)判斷,如果slave延遲過大,暫時遮蔽程式對該slave的資料訪問
slave-serve-stale-data	yes|no

開啟後僅響應info、slaveof等少數命令(慎用,除非對資料一致性要求很高)

3 哨兵模式

3.1 哨兵簡介

3.1.1 哨兵概念

首先我們來看一個業務場景:如果redis的master宕機了,此時應該怎麼辦?

在這裡插入圖片描述

那此時我們可能需要從一堆的slave中重新選舉出一個新的master,那這個操作過程是什麼樣的呢?這裡面會有什麼問題出現呢?

在這裡插入圖片描述

要實現這些功能,我們就需要redis的哨兵,那哨兵是什麼呢?

哨兵

哨兵(sentinel) 是一個分散式系統,用於對主從結構中的每臺伺服器進行監控,當出現故障時通過投票機制選擇新的master並將所有slave連線到新的master。

在這裡插入圖片描述

3.1.2 哨兵作用

哨兵的作用:

  • 監控:監控master和slave

    不斷的檢查master和slave是否正常執行

    master存活檢測、master與slave執行情況檢測

  • 通知(提醒):當被監控的伺服器出現問題時,向其他(哨兵間,客戶端)傳送通知

  • 自動故障轉移:斷開master與slave連線,選取一個slave作為master,將其他slave連線新的master,並告知客戶端新的伺服器地址

注意:哨兵也是一臺redis伺服器,只是不提供資料相關服務,通常哨兵的數量配置為單數

3.2 啟用哨兵

配置哨兵

  • 配置一拖二的主從結構(利用之前的方式啟動即可)

  • 配置三個哨兵(配置相同,埠不同),參看sentinel.conf

1:設定哨兵監聽的主伺服器資訊, sentinel_number表示參與投票的哨兵數量

sentinel monitor master_name  master_host	master_port	 sentinel_number

2:設定判定伺服器宕機時長,該設定控制是否進行主從切換

sentinel down-after-milliseconds master_name	million_seconds

3:設定故障切換的最大超時時

sentinel failover-timeout master_name	million_seconds

4:設定主從切換後,同時進行資料同步的slave數量,數值越大,要求網路資源越高,數值越小,同步時間越長

sentinel parallel-syncs master_name sync_slave_number
  • 啟動哨兵
redis-sentinel filename

3.3 哨兵工作原理

哨兵在進行主從切換過程中經歷三個階段

  • 監控
  • 通知
  • 故障轉移

3.3.1 監控

用於同步各個節點的狀態資訊

在這裡插入圖片描述

  • 獲取各個sentinel的狀態(是否線上)

  • 獲取master的狀態

master屬性
	prunid
	prole:master
各個slave的詳細資訊	
  • 獲取所有slave的狀態(根據master中的slave資訊)
slave屬性
	prunid
	prole:slave
	pmaster_host、master_port
	poffset

其內部的工作原理具體如下:

在這裡插入圖片描述

3.3.2 通知

sentinel在通知階段要不斷的去獲取master/slave的資訊,然後在各個sentinel之間進行共享,具體的流程如下:

在這裡插入圖片描述

3.3.3 故障轉移

當master宕機後sentinel是如何知曉並判斷出master是真的宕機了呢?我們來看具體的操作流程

在這裡插入圖片描述

當sentinel認定master下線之後,此時需要決定更換master,那這件事由哪個sentinel來做呢?這時候sentinel之間要進行選舉,如下圖所示:

在這裡插入圖片描述

在選舉的時候每一個人手裡都有一票,而每一個人的又都想當這個處理事故的人,那怎麼辦?大家就開始搶,於是每個人都會發出一個指令,在內網裡邊告訴大家我要當選舉人,比如說現在的sentinel1和sentinel4發出這個選舉指令了,那麼sentinel2既能接到sentinel1的也能接到sentinel4的,接到了他們的申請以後呢,sentinel2他就會把他的一票投給其中一方,投給誰呢?誰先過來我投給誰,假設sentinel1先過來,所以這個票就給到了sentinel1。那麼給過去以後呢,現在sentinel1就拿到了一票,按照這樣的一種形式,最終會有一個選舉結果。對應的選舉最終得票多的,那自然就成為了處理事故的人。需要注意在這個過程中有可能會存在失敗的現象,就是一輪選舉完沒有選取,那就會接著進行第二輪第三輪直到完成選舉。

接下來就是由選舉勝出的sentinel去從slave中選一個新的master出來的工作,這個流程是什麼樣的呢?

首先它有一個在伺服器列表中挑選備選master的原則

  • 不線上的OUT

  • 響應慢的OUT

  • 與原master斷開時間久的OUT

  • 優先原則

    ​ 優先順序
    ​ offset
    ​ runid

選出新的master之後,傳送指令( sentinel )給其他的slave:

  • 向新的master傳送slaveof no one

  • 向其他slave傳送slaveof 新masterIP埠

總結:故障轉移階段

  1. 發現問題,主觀下線與客觀下線
  2. 競選負責人
  3. 優選新master
  4. 新master上任,其他slave切換master,原master作為slave故障恢復後連線

4 叢集cluster

現狀問題:業務發展過程中遇到的峰值瓶頸

  • redis提供的服務OPS可以達到10萬/秒,當前業務OPS已經達到10萬/秒
  • 記憶體單機容量達到256G,當前業務需求記憶體容量1T
  • 使用叢集的方式可以快速解決上述問題

4.1 叢集簡介

叢集就是使用網路將若干臺計算機聯通起來,並提供統一的管理方式,使其對外呈現單機的服務效果

叢集作用:

  • 分散單臺伺服器的訪問壓力,實現負載均衡
  • 分散單臺伺服器的儲存壓力,實現可擴充套件性
  • 降低單臺伺服器宕機帶來的業務災難

4.2 Cluster叢集結構設計

資料儲存設計:

  1. 通過演算法設計,計算出key應該儲存的位置

  2. 將所有的儲存空間計劃切割成16384份,每臺主機儲存一部分

    注意:每份代表的是一個儲存空間,不是一個key的儲存空間

  3. 將key按照計算出的結果放到對應的儲存空間

在這裡插入圖片描述

那redis的叢集是如何增強可擴充套件性的呢?譬如我們要增加一個叢集節點

在這裡插入圖片描述

當我們查詢資料時,叢集是如何操作的呢?

  • 各個資料庫相互通訊,儲存各個庫中槽的編號資料
  • 一次命中,直接返回
  • 一次未命中,告知具體位置

在這裡插入圖片描述

4.3 Cluster叢集結構搭建

首先要明確的幾個要點:

  • 配置伺服器(3主3從)
  • 建立通訊(Meet)
  • 分槽(Slot)
  • 搭建主從(master-slave)

Cluster配置

  • 是否啟用cluster,加入cluster節點
cluster-enabled yes|no
  • cluster配置檔名,該檔案屬於自動生成,僅用於快速查詢檔案並查詢檔案內容
cluster-config-file filename
  • 節點服務響應超時時間,用於判定該節點是否下線或切換為從節點
cluster-node-timeout milliseconds
  • master連線的slave最小數量
cluster-migration-barrier min_slave_number

Cluster節點操作命令

  • 檢視叢集節點資訊
cluster nodes
  • 更改slave指向新的master
cluster replicate master-id
  • 發現一個新節點,新增master
cluster meet ip:port
  • 忽略一個沒有solt的節點
cluster forget server_id
  • 手動故障轉移
cluster failover

叢集操作命令:

  • 建立叢集
redis-cli –-cluster create masterhost1:masterport1 masterhost2:masterport2  masterhost3:masterport3 [masterhostn:masterportn …] slavehost1:slaveport1  slavehost2:slaveport2 slavehost3:slaveport3 -–cluster-replicas n

注意:master與slave的數量要匹配,一個master對應n個slave,由最後的引數n決定

master與slave的匹配順序為第一個master與前n個slave分為一組,形成主從結構

  • 新增master到當前叢集中,連線時可以指定任意現有節點地址與埠
redis-cli --cluster add-node new-master-host:new-master-port now-host:now-port
  • 新增slave
redis-cli --cluster add-node new-slave-host:new-slave-port master-host:master-port --cluster-slave --cluster-master-id masterid
  • 刪除節點,如果刪除的節點是master,必須保障其中沒有槽slot
redis-cli --cluster del-node del-slave-host:del-slave-port del-slave-id
  • 重新分槽,分槽是從具有槽的master中劃分一部分給其他master,過程中不建立新的槽
redis-cli --cluster reshard new-master-host:new-master:port --cluster-from src-  master-id1, src-master-id2, src-master-idn --cluster-to target-master-id --  cluster-slots slots

注意:將需要參與分槽的所有masterid不分先後順序新增到引數中,使用,分隔

指定目標得到的槽的數量,所有的槽將平均從每個來源的master處獲取

  • 重新分配槽,從具有槽的master中分配指定數量的槽到另一個master中,常用於清空指定master中的槽
redis-cli --cluster reshard src-master-host:src-master-port --cluster-from src-  master-id --cluster-to target-master-id --cluster-slots slots --cluster-yes

5 企業級解決方案

5.1 快取預熱

場景:“宕機”

伺服器啟動後迅速宕機

問題排查

1.請求數量較高,大量的請求過來之後都需要去從快取中獲取資料,但是快取中又沒有,此時從資料庫中查詢資料然後將資料再存入快取,造成了短期內對redis的高強度操作從而導致問題

2.主從之間資料吞吐量較大,資料同步操作頻度較高

解決方案:

  • 前置準備工作:

1.日常例行統計資料訪問記錄,統計訪問頻度較高的熱點資料

2.利用LRU資料刪除策略,構建資料留存佇列例如:storm與kafka配合

  • 準備工作:

1.將統計結果中的資料分類,根據級別,redis優先載入級別較高的熱點資料

2.利用分散式多伺服器同時進行資料讀取,提速資料載入過程

3.熱點資料主從同時預熱

  • 實施:

4.使用指令碼程式固定觸發資料預熱過程

5.如果條件允許,使用了CDN(內容分發網路),效果會更好

總的來說:快取預熱就是系統啟動前,提前將相關的快取資料直接載入到快取系統。避免在使用者請求的時候,先查詢資料庫,然後再將資料快取的問題!使用者直接查詢事先被預熱的快取資料!

5.2 快取雪崩

場景:資料庫伺服器崩潰,一連串的場景會隨之兒來

1.系統平穩執行過程中,忽然資料庫連線量激增

2.應用伺服器無法及時處理請求

3.大量408,500錯誤頁面出現

4.客戶反覆重新整理頁面獲取資料

5.資料庫崩潰

6.應用伺服器崩潰

7.重啟應用伺服器無效

8.Redis伺服器崩潰

9.Redis叢集崩潰

10.重啟資料庫後再次被瞬間流量放倒

問題排查

1.在一個較短的時間內,快取中較多的key集中過期

2.此週期內請求訪問過期的資料,redis未命中,redis向資料庫獲取資料

3.資料庫同時接收到大量的請求無法及時處理

4.Redis大量請求被積壓,開始出現超時現象

5.資料庫流量激增,資料庫崩潰

6.重啟後仍然面對快取中無資料可用

7.Redis伺服器資源被嚴重佔用,Redis伺服器崩潰

8.Redis叢集呈現崩塌,叢集瓦解

9.應用伺服器無法及時得到資料響應請求,來自客戶端的請求數量越來越多,應用伺服器崩潰

10.應用伺服器,redis,資料庫全部重啟,效果不理想

總而言之就兩點:短時間範圍內,大量key集中過期

解決方案

  • 思路:

1.更多的頁面靜態化處理

2.構建多級快取架構

​ Nginx快取+redis快取+ehcache快取

3.檢測Mysql嚴重耗時業務進行優化

​ 對資料庫的瓶頸排查:例如超時查詢、耗時較高事務等

4.災難預警機制

​ 監控redis伺服器效能指標

​ CPU佔用、CPU使用率

​ 記憶體容量

​ 查詢平均響應時間

​ 執行緒數

5.限流、降級

短時間範圍內犧牲一些客戶體驗,限制一部分請求訪問,降低應用伺服器壓力,待業務低速運轉後再逐步放開訪問

  • 落地實踐:

1.LRU與LFU切換

2.資料有效期策略調整

​ 根據業務資料有效期進行分類錯峰,A類90分鐘,B類80分鐘,C類70分鐘

​ 過期時間使用固定時間+隨機值的形式,稀釋集中到期的key的數量

3.超熱資料使用永久key

4.定期維護(自動+人工)

​ 對即將過期資料做訪問量分析,確認是否延時,配合訪問量統計,做熱點資料的延時

5.加鎖:慎用!

總的來說:快取雪崩就是瞬間過期資料量太大,導致對資料庫伺服器造成壓力。如能夠有效避免過期時間集中,可以有效解決雪崩現象的 出現(約40%),配合其他策略一起使用,並監控伺服器的執行資料,根據執行記錄做快速調整。

5.3 快取擊穿

場景:還是資料庫伺服器崩潰,但是跟之前的場景有點不太一樣

1.系統平穩執行過程中

2.資料庫連線量瞬間激增

3.Redis伺服器無大量key過期

4.Redis記憶體平穩,無波動

5.Redis伺服器CPU正常

6.資料庫崩潰

問題排查:

1.Redis中某個key過期,該key訪問量巨大

2.多個數據請求從伺服器直接壓到Redis後,均未命中

3.Redis在短時間內發起了大量對資料庫中同一資料的訪問

總而言之就兩點:單個key高熱資料,key過期

解決方案

1.預先設定

​ 以電商為例,每個商家根據店鋪等級,指定若干款主打商品,在購物節期間,加大此類資訊key的過期時長 注意:購物節不僅僅指當天,以及後續若干天,訪問峰值呈現逐漸降低的趨勢

2.現場調整

​ 監控訪問量,對自然流量激增的資料延長過期時間或設定為永久性key

3.後臺重新整理資料

​ 啟動定時任務,高峰期來臨之前,重新整理資料有效期,確保不丟失

4.二級快取

​ 設定不同的失效時間,保障不會被同時淘汰就行

5.加鎖

​ 分散式鎖,防止被擊穿,但是要注意也是效能瓶頸,慎重!

總的來說:快取擊穿就是單個高熱資料過期的瞬間,資料訪問量較大,未命中redis後,發起了大量對同一資料的資料庫訪問,導致對數 據庫伺服器造成壓力。應對策略應該在業務資料分析與預防方面進行,配合執行監控測試與即時調整策略,畢竟單個key的過 期監控難度較高,配合雪崩處理策略即可。

5.4 快取穿透

場景:資料庫伺服器又崩潰了,跟之前的一樣嗎?

1.系統平穩執行過程中

2.應用伺服器流量隨時間增量較大

3.Redis伺服器命中率隨時間逐步降低

4.Redis記憶體平穩,記憶體無壓力

5.Redis伺服器CPU佔用激增

6.資料庫伺服器壓力激增

7.資料庫崩潰

問題排查:

1.Redis中大面積出現未命中

2.出現非正常URL訪問

問題分析

  • 獲取的資料在資料庫中也不存在,資料庫查詢未得到對應資料
  • Redis獲取到null資料未進行持久化,直接返回
  • 下次此類資料到達重複上述過程
  • 出現黑客攻擊伺服器

解決方案

1.快取null

​ 對查詢結果為null的資料進行快取(長期使用,定期清理),設定短時限,例如30-60秒,最高5分鐘

2.白名單策略

​ 提前預熱各種分類資料id對應的bitmaps,id作為bitmaps的offset,相當於設定了資料白名單。當載入正常資料時放行,載入異常資料時直接攔截(效率偏低)

​ 使用布隆過濾器(有關布隆過濾器的命中問題對當前狀況可以忽略)

2.實施監控

​ 實時監控redis命中率(業務正常範圍時,通常會有一個波動值)與null資料的佔比

​ 非活動時段波動:通常檢測3-5倍,超過5倍納入重點排查物件

​ 活動時段波動:通常檢測10-50倍,超過50倍納入重點排查物件

​ 根據倍數不同,啟動不同的排查流程。然後使用黑名單進行防控(運營)

4.key加密

​ 問題出現後,臨時啟動防災業務key,對key進行業務層傳輸加密服務,設定校驗程式,過來的key校驗

​ 例如每天隨機分配60個加密串,挑選2到3個,混淆到頁面資料id中,發現訪問key不滿足規則,駁回資料訪問

總的來說:快取擊穿是指訪問了不存在的資料,跳過了合法資料的redis資料快取階段,每次訪問資料庫,導致對資料庫伺服器造成壓力。通常此類資料的出現量是一個較低的值,當出現此類情況以毒攻毒,並及時報警。應對策略應該在臨時預案防範方面多做文章。

無論是黑名單還是白名單,都是對整體系統的壓力,警報解除後儘快移除。

5.5 效能指標監控

redis中的監控指標如下:

  • 效能指標:Performance

響應請求的平均時間:

latency

平均每秒處理請求總數

instantaneous_ops_per_sec

快取查詢命中率(通過查詢總次數與查詢得到非nil資料總次數計算而來)

hit_rate(calculated)
  • 記憶體指標:Memory

當前記憶體使用量

used_memory

記憶體碎片率(關係到是否進行碎片整理)

mem_fragmentation_ratio

為避免記憶體溢位刪除的key的總數量

evicted_keys

基於阻塞操作(BLPOP等)影響的客戶端數量

blocked_clients
  • 基本活動指標:Basic_activity

當前客戶端連線總數

connected_clients

當前連線slave總數

connected_slaves

最後一次主從資訊交換距現在的秒

master_last_io_seconds_ago

key的總數

keyspace
  • 永續性指標:Persistence

當前伺服器最後一次RDB持久化的時間

rdb_last_save_time

當前伺服器最後一次RDB持久化後資料變化總量

rdb_changes_since_last_save
  • 錯誤指標:Error

被拒絕連線的客戶端總數(基於達到最大連線值的因素)

rejected_connections

key未命中的總次數

keyspace_misses

主從斷開的秒數

master_link_down_since_seconds

要對redis的相關指標進行監控,我們可以採用一些用具:

  • CloudInsight Redis
  • Prometheus
  • Redis-stat
  • Redis-faina
  • RedisLive
  • zabbix

也有一些命令工具:

  • benchmark

測試當前伺服器的併發效能

redis-benchmark [-h ] [-p ] [-c ] [-n <requests]> [-k ]

範例1:50個連線,10000次請求對應的效能

redis-benchmark

範例2:100個連線,5000次請求對應的效能

redis-benchmark -c 100 -n 5000

在這裡插入圖片描述

  • redis-cli

    ​ monitor:啟動伺服器除錯資訊

monitor
slowlog:慢日誌

獲取慢查詢日誌

slowlog [operator]

​ get :獲取慢查詢日誌資訊

​ len :獲取慢查詢日誌條目數

​ reset :重置慢查詢日誌

相關配置

slowlog-log-slower-than 1000 #設定慢查詢的時間下線,單位:微妙
slowlog-max-len 100	#設定慢查詢命令對應的日誌顯示長度,單位:命令數