3------叢集篇
主從同步
當主節點(Master)掛掉的時候,運維讓從節點(slave)過來接管,服務就可以繼續,否則主節點需要經過資料恢復和重啟的過程。
CAP原理
分散式儲存的理論基石
- C:Consistent,一致性
- A:Availability,可用性
- P:Partition tolerance,分割槽容忍性
分散式系統的節點往往都是分佈在不同的機器上進行網路隔離的,網路分割槽。
網路分割槽:兩個節點之間不能通訊
網路分割槽發生時,一致性和可用性兩難全
最終一致
Redis的主從資料是非同步同步的,所以分散式系統並不滿足一致性,但是滿足可用性
但是滿足最終一致性,因為網路恢復後,從節點會採用各種策略努力追趕恢復的。
Redis同步支援主從同步和從從同步
增量同步
主節點將修改主節點狀態的指令 寫入 下圖環狀的buffer陣列當中,迴圈一直覆蓋寫。
從節點一直從上面讀指令,達到和主節點一致的狀態、、、並且返回自己複製到哪兒了
但是遇到網路問題,那麼指令就會被覆蓋掉
這個時候就需要快照同步。
快照同步
在主節點上來一次bgsave,將當前記憶體的資料全部快照到磁碟檔案中
然後,再將快照檔案傳送給從節點。從節點來一個全量載入
載入之前先要將當前記憶體的資料清空,載入完畢後通知主節點繼續進行增量同步
但是!!!!這個時候,主節點的buffer還是在一直複製的,如果快照時間過長或者buffer的太小,那麼就會造成快照死迴圈。
增加從節點
當從節點剛剛加到叢集中,必須來一次快照同步,才能進行增量同步
無盤複製
主要指快照同步
主節點直接通過套接字將快照內容傳送到從節點
主節點會一邊遍歷記憶體,一邊將序列化的內容傳送到從節點,從節點將收到的內容載入到磁碟,最後再進行一次載入。
wait指令
Redis的複製是非同步的,wait指令可以讓非同步複製變身同步複製,確保系統的強一致性
set key value
wait 1 0
兩個引數:第一個引數從節點的數量;第二個引數是時間t。
等待wait指令之前的所有寫操作同步到N個從節點,最多等待時間t,等待從節點同步。如果t=0,表示無限等待直到N個從節點同步完成。
假設此時出現了網路分割槽,wait指令第二個引數為0,那麼redis伺服器就失去了可用性
Sentinel
哨兵系統,主節點壞了,自動將從節點升級為主節點,不用手動
Sentinel負責持續監控主從節點的健康,當主節點掛了,自動選擇一個最優的從節點切換為主節點。
客戶端連線叢集,會首先連線Sentinel,通過Sentinel來查詢主節點的地址,然後再連線主節點進行資料互動。
當主節點故障了,客戶端會重新想Senatinel要地址,Sentinel會將最新的主節點告訴客戶端。
當主節點恢復之後,自動稱為從節點。
訊息丟失
Sentinel無法保證資料不丟失,但是儘量保證資訊少丟失
限制主從延遲不要太大
# 保證至少一個從節點正常複製 min-slave-to-write 1 #什麼是正常複製,那就是每過10s收到從節點的反饋 min-slaves-max-lag 10
Sentinel基本用法
客戶端通過Sentinel來發現從節點的地址,然後再通過地址建立相應的連線。
Sentinel預設埠為26379
客戶端如何知道地址發生改變?
------建立連線的時候進行主節點地址變更判斷
連線池建立新連線時,會去查詢主節點地址,然後跟記憶體中的主節點地址進行比對,如果變更了,就斷開所有連線,重新使用新地址進行連線。如果舊的主節點掛掉了,那麼所有正在使用的連線都會關閉,然後在重連時就會用上新地址
Codis分而治之
單個Redis記憶體不宜過大,記憶體太大導致rdb檔案過大,進一步導致主從同步時全量同步時間過長,在例項重啟恢復時也會消耗很長的資料載入時間。
Codis:將眾多小記憶體的Redis例項整合起來,將分佈在多臺機器上的眾多CPU核心的計算能力聚集在一起,完成海量資料儲存和高併發讀寫操作
當客戶端向Codis傳送指令時,Codis負責將指令轉發到後面的Redis例項來致性,並且將結果返回給客戶端。
Codis是一個轉發代理中介軟體,可以啟動多個Codis例項,供客戶端使用,每個Codis節點都是對等的。
還可以起到容災功能
Codis分片原理
Codis負責將特定的key轉發到特定的Redis例項中
Codis預設將所有的key劃分為1024個槽位,將key進行hash,然後得到槽位。然後到相應的redis例項當中查詢
不同的Codis例項之間槽位關係如何同步?
利用zookeeper,儲存Codis例項和槽位之間的通訊,多個Codis之間同步。
擴容
Codis本來只有一個Redis例項,接下來新加了一個,那麼就會將一半的槽位分給新的節點。
利用SLOTSSCAN指令掃描一個槽下的所有key,然後挨個遷移。
遷移的時候,Codis的槽有可能還在接收新的key-----------------------那麼,COdis接收到位於正在遷移槽位中的key後,會立即強制對當前的單個key進行遷移,遷移完成後,再將請求轉發到新的Redis例項中
自動均衡
Codis會檢視每個Redis對應的槽位,然後自動均衡負載
Codis的代價
- 不支援事務
- 遷移會變得困難
- 網路開銷變大,畢竟多走了一個網路節點
Codis的優點
簡單
mget指令的操作過程
架構變遷
畢竟不是官方的,老是隨著官方的redis改變
Codis尷尬
不是親生的
Codis後臺管理
一個很友好的後臺web介面
Cluster
redis Cluster去中心化的叢集方案
叢集由三個Redis節點組成,每個節點負責整個叢集的一部分資料,每個節點負責的資料多少可能不一樣。二進位制協議通訊
將資料劃分為16384個槽位,每個節點負責其中一部分槽位。
客戶端來連線叢集,會得到一份叢集的槽位配置資訊,然後通過這個配置資訊去查詢完事了。
客戶端需要快取槽位的資訊,可能客戶端和伺服器儲存槽位的資訊不一致的情況,這個時候還需要校準。
Redis Cluster的每個節點會將叢集的配置資訊持久化到配置檔案中,所以必須保證配置檔案時可寫的,而且儘量不要依靠人工修改配置檔案
槽位定位方法
將key進行hash,然後將雜湊值與槽位進行雜湊
Redis Cluster允許將使用者強制把某個key掛在特定的槽位上
跳轉
當節點發現客戶端的請求中的槽位並不歸屬自己管,就會給客戶端傳送一個帶跳轉地址的資訊,讓客戶端去連線這個節點獲取資料
遷移
從源節點獲取內容---存區目標節點------從源節點中刪除
整個轉移過程中,轉移是一步一步的,假如單個key過大,那會引起卡頓的。
客戶端首先會訪問舊節點,找到了還好,找不到舊節點會重定向;----客戶端向新節點詢問下Asking,然後再致性原先的操作指令。Asking指令避免重定向迴圈。
容錯
每個節點設定幾個從節點,當主節點發生故障時,叢集就會自動升級從節點;同時允許若干個主節點發生故障
網路抖動
有時候,有些節點突然失聯,突然又連線上了,Redis Cluster給一個失聯的時間,超過這個時間就表示失聯了;主從切換。
cluster-node-timeout
可能下線和確定下線
Redis cluster是去中心化的,一個節點認為某個節點失聯了,並不管用,只有大多數節點都認定某個節點失聯了,叢集才認識該節點需要進行主從切換來容錯。
比如:某個節點發現某個節點失聯了(PFail),它會將這條資訊向整個叢集廣播,其它節點就可以收到這點的失戀資訊。如果收到了某個節點失聯的數量已經達到了叢集的大多數,就可以標記這個節點失聯。Fail
Cluster基本用法
匯入redis-py-cluster模組才可以使用
cluster不支援事務:Cluster的mget方法比redis要慢很多,被拆分成了多個get指令;Cluster的rename方法不再是原子的,它需要將資料從源節點轉移到目標節點。
槽位遷移感知
客戶端儲存了槽位和節點的對映關係表,它需要及時得到更新。
moved指令:客戶端請求了錯誤的節點,節點指揮客戶端重定向到正確的節點上。並且重新整理客戶端的配置資訊
asking指令:再遷移時傳送的指令。
不過上述的兩個指令都是重試指令,需要限制重試的次數。高於這個次數就報錯
叢集變更感知
當服務節點變更時,客戶端應該立即得到通知以實時重新整理自己的節點關係表。那麼客戶端是如何知道的
- 目標節點掛掉了,客戶端丟擲ConnectionError指令,緊接著隨機挑一個節點來重試,然後提供moved指令進行重試
- 運維手動修改叢集資訊,將主節點切換到其它節點,並將舊的主節點移除出叢集,這時打在舊節點上的指令會受到ClusterDown錯誤,然後客戶端關閉所有的連線,清空槽位對映關係表,重新嘗試初始化節點資訊