分散式快取-Redis叢集
一、單點Redis弊端
1、資料丟失問題:Redis是記憶體儲存,伺服器重啟可能會丟失資料
2、併發能力問題:單節點Redis併發能力雖然不錯,但也無法滿足如618這樣的高併發場景
3、故障恢復問題:如果Redis宕機,則服務不可用,需要一種自動的故障恢復手段
4、儲存能力問題:Redis基於記憶體,單節點能儲存的資料量難以滿足海量資料需求
解決方案:
1、資料丟失問題:資料持久化
2、併發能力問題:搭建主從叢集,實現讀寫分離
3、故障恢復問題:利用Redis哨兵,實現健康監測和故障自動恢復
4、儲存能力問題:搭建分片叢集,利用插槽機制實現動態擴容
二、Redis的持久化
Redis持久化方式有RDB和AOF兩種。
1、RDB
1、概念
RDB全稱Redis Database Backup file(Redis資料備份檔案),也被叫做Redis資料快照。簡單來說就是把記憶體中的所有資料都記錄到磁碟中。當Redis例項故障重啟後,從磁碟讀取快照檔案,恢復資料。 快照檔案稱為RDB檔案,預設是儲存在當前執行目錄。
2、RDB執行時機
1、使用命令save手動執行
2、Redis停機時執行一次
3、在Redis配置檔案中配置RDB執行條件
3、RDB執行原理
bgsave開始時會fork主程序得到子程序,子程序共享主程序的記憶體資料。完成fork後讀取記憶體資料並寫入 RDB 檔案。
fork採用的是copy-on-write技術:
- 當主程序執行讀操作時,訪問共享記憶體;
- 當主程序執行寫操作時,則會拷貝一份資料,執行寫操作。
4、總結
1、RDB方式bgsave的基本流程?
- fork主程序得到一個子程序,共享記憶體空間
- 子程序讀取記憶體資料並寫入新的RDB檔案
- 用新RDB檔案替換舊的RDB檔案。
2、RDB會在什麼時候執行?save 60 1000代表什麼含義?
- 預設是服務停止時。
- 代表60秒內至少執行1000次修改則觸發RDB
3、RDB的缺點?
- RDB執行間隔時間長,兩次RDB之間寫入資料有丟失的風險
- fork子程序、壓縮、寫出RDB檔案都比較耗時
2、AOF
1、概念
AOF全稱為Append Only File(追加檔案)。Redis處理的每一個寫命令都會記錄在AOF檔案,可以看做是命令日誌檔案。
2、AOF配置
AOF預設是關閉的,需要修改redis.conf配置檔案來開啟AOF:
AOF的命令記錄的頻率也可以通過redis.conf檔案來配:
因為是記錄命令,AOF檔案會比RDB檔案大的多。而且AOF會記錄對同一個key的多次寫操作,但只有最後一次寫操作才有意義。通過執行bgrewriteaof命令,可以讓AOF檔案執行重寫功能,用最少的命令達到相同效果。
Redis也會在觸發閾值時自動去重寫AOF檔案。閾值也可以在redis.conf中配置:
3、RDB和AOF的異同
RDB和AOF各有自己的優缺點,如果對資料安全性要求較高,在實際開發中往往會結合兩者來使用。
三、Redis主從
1、搭建主從架構
單節點Redis的併發能力是有上限的,要進一步提高Redis的併發能力,就需要搭建主從叢集,實現讀寫分離。
2、主從原理
1、全量同步
主從第一次同步是全量同步:
master如何判斷slave是不是第一次來同步資料?這裡會用到兩個很重要的概念:
- Replication Id:簡稱replid,是資料集的標記,id一致則說明是同一資料集。每一個master都有唯一的replid,slave則會繼承master節點的replid
- offset:偏移量,隨著記錄在repl_baklog中的資料增多而逐漸增大。slave完成同步時也會記錄當前同步的offset。
- 如果slave的offset小於master的offset,說明slave資料落後於master,需要更新。
因此slave做資料同步,必須向master宣告自己的replication id 和offset,master才可以判斷到底需要同步哪些資料
2、總結
簡述全量同步的流程?
- slave節點請求增量同步
- master節點判斷replid,發現不一致,拒絕增量同步
- master將完整記憶體資料生成RDB,傳送RDB到slave
- slave清空本地資料,載入master的RDB
- master將RDB期間的命令記錄在repl_baklog,並持續將log中的命令傳送給slave
- slave執行接收到的命令,保持與master之間的同步
3、增量同步
主從第一次是全量同步,slave重啟後同步,則是增量同步。
repl_baklog大小有上限,寫滿後會覆蓋最早的資料。如果slave斷開時間過久,導致尚未備份的資料被覆蓋,則無法基於log做增量同步,只能再次全量同步。
可以從以下幾個方面來優化Redis主從就叢集:
- 在master中配置repl-diskless-sync yes啟用無磁碟複製,避免全量同步時的磁碟IO。
- Redis單節點上的記憶體佔用不要太大,減少RDB導致的過多磁碟IO
- 適當提高repl_baklog的大小,發現slave宕機時儘快實現故障恢復,儘可能避免全量同步
- 限制一個master上的slave節點數量,如果實在是太多slave,則可以採用主-從-從鏈式結構,減少master壓力
4、總結
簡述全量同步和增量同步區別?
- 全量同步:master將完整記憶體資料生成RDB,傳送RDB到slave。後續命令則記錄在repl_baklog,逐個傳送給slave。
- 增量同步:slave提交自己的offset到master,master獲取repl_baklog中從offset之後的命令給slave
什麼時候執行全量同步?
- slave節點第一次連線master節點時
- slave節點斷開時間太久,repl_baklog中的offset已經被覆蓋時
什麼時候執行增量同步?
- slave節點斷開又恢復,並且在repl_baklog中能找到offset時
思考:slave節點宕機恢復後可以找master節點同步資料,那master節點宕機怎麼辦?
四、Redis哨兵
1、哨兵的作用及原理
1、哨兵的作用
Redis提供了哨兵(Sentinel)機制來實現主從叢集的自動故障恢復。哨兵的結構和作用如下:
- 監控:Sentinel 會不斷檢查您的master和slave是否按預期工作
- 自動故障恢復:如果master故障,Sentinel會將一個slave提升為master。當故障例項恢復後也以新的master為主
- 通知:Sentinel充當Redis客戶端的服務發現來源,當叢集發生故障轉移時,會將最新資訊推送給Redis的客戶端
2、服務狀態監控
Sentinel基於心跳機制監測服務狀態,每隔1秒向叢集的每個例項傳送ping命令:
- 主觀下線:如果某sentinel節點發現某例項未在規定時間響應,則認為該例項主觀下線。
- 客觀下線:若超過指定數量(quorum)的sentinel都認為該例項主觀下線,則該例項客觀下線。quorum值最好超過Sentinel例項數量的一半。
3、選舉新的master
一旦發現master故障,sentinel需要在salve中選擇一個作為新的master,選擇依據是這樣的:
- 首先會判斷slave節點與master節點斷開時間長短,如果超過指定值(down-after-milliseconds * 10)則會排除該slave節點
- 然後判斷slave節點的slave-priority值,越小優先順序越高,如果是0則永不參與選舉
- 如果slave-prority一樣,則判斷slave節點的offset值,越大說明資料越新,優先順序越高
- 最後是判斷slave節點的執行id大小,越小優先順序越高。
4、如何實現故障轉移
當選中了其中一個slave為新的master後(例如slave1),故障的轉移的步驟如下:
- sentinel給備選的slave1節點發送slaveof no one命令,讓該節點成為master
- sentinel給所有其它slave傳送slaveof 192.168.150.101 7002 命令,讓這些slave成為新master的從節點,開始從新的master上同步資料。
- 最後,sentinel將故障節點標記為slave,當故障節點恢復後會自動成為新的master的slave節點
2、總結
Sentinel的三個作用是什麼?
- 監控
- 故障轉移
- 通知
Sentinel如何判斷一個redis例項是否健康?
- 每隔1秒傳送一次ping命令,如果超過一定時間沒有相向則認為是主觀下線
- 如果大多數sentinel都認為例項主觀下線,則判定服務下線
故障轉移步驟有哪些?
- 首先選定一個slave作為新的master,執行slaveof no one
- 然後讓所有節點都執行slaveof 新master
- 修改故障節點配置,新增slaveof 新master