前言
redis高併發:主從架構,一主多從,通常來講,不少項目其實就足夠了,單主用來寫入數據,單機幾萬QPS,多從用來查詢數據,多個從實例能夠提供每秒10萬的QPS。node
redis高併發的同時,還須要容納大量的數據:一主多從,每一個實例都容納了完整的數據,好比redis主就10G的內存量,其實你就最對只能容納10g的數據量。若是你的緩存要容納的數據量很大,達到了幾十g,甚至幾百g,或者是幾t,那你就須要redis集羣,並且用redis集羣以後,能夠提供可能每秒幾十萬的讀寫併發。小編這裏整理了一份詳細的Redis思惟導圖,須要的朋友能夠關注公衆號:麒麟改bug。 面試
redis高可用:若是你作主從架構部署,其實就是加上哨兵就能夠了,就能夠實現,任何一個實例宕機,自動會進行主備切換。redis
redis 實現高併發主要依靠主從架構,一主多從.算法
對於性能來講,單主用來寫入數據,單機幾萬QPS,多從用來查詢數據,多個從實例能夠提供每秒 10w 的 QPS。緩存
若是想要在實現高併發的同時,容納大量的數據,那麼就須要 redis 集羣。服務器
使用 redis cluster 模式,能夠提供每秒幾十萬的讀寫併發。網絡
redis 高可用,若是是作主從架構部署,那麼加上哨兵就能夠了,就能夠實現,任何一個實例宕機,能夠進行主備切換。架構
因此就有了幾個問題?併發
-
什麼是主從架構,主從如何備份?負載均衡
-
什麼是redis cluster模式?
-
什麼是哨兵集羣?
redis 主從架構
主從(master-slave)架構,一主多從,主負責寫,而且將數據複製到其它的 slave 節點,從節點負責讀。全部的讀請求所有走從節點。這樣也能夠很輕鬆實現水平擴容,支撐讀高併發。
Redis雖然讀取寫入的速度都特別快,可是也會產生讀壓力特別大的狀況,因此爲了緩解讀的壓力,因此進行讀寫分類,並對讀進行擴展。
優勢:
一、解決數據備份問題
二、作到讀寫分離,提升服務器性能
缺點:
一、每一個客戶端鏈接redis實例的時候都是指定了ip和端口號的,若是所鏈接的redis實例由於故障下線了,而主從模式也沒有提供必定的手段通知客戶端另外可鏈接的客戶端地址,於是須要手動更改客戶端配置從新鏈接
二、主從模式下,若是主節點因爲故障下線了,那麼從節點由於沒有主節點而同步中斷,於是須要人工進行故障轉移工做
三、沒法實現動態擴容
主從架構就涉及到一個數據從主節點同步到從節點的問題。涉及redis replication問題
redis replication 的核心機制
當啓動一個 slave node 的時候,它會發送一個 PSYNC 命令給 master node,若是這是第一次鏈接master node 那麼會觸發一次 full resynchronization 全量複製.全量複製的時候,master 會啓動一個後臺線程,開始生成一份 RDB 快照文件,同時還會將從客戶端新收到的全部寫命令緩存在內存中。最後將生成的RDB文件發送給slave,slave會先寫入本地磁盤,而後再從本地磁盤加載到內存中,接着 master 會將內存中緩存的寫命令發送到 slave,slave 也會同步這些數據。
若是是鏈接以後 master node 僅會複製給 slave 部分缺乏的數據。master 若是發現有多個slave node都來從新鏈接,僅僅會啓動一個rdb save操做,用一份數據服務全部slave node。
注:redis2.8 開始,就支持主從複製的斷點續傳,若是主從複製過程當中,斷掉了,那麼能夠接着上次複製的地方,繼續複製下去,而不是從頭開始複製一份。 master node 會在內存中維護一個 backlog,master 和 slave 都會保存一個 replica offset 還有一個 master run id,offset 就是保存在 backlog 中的。若是 master 和 slave 網絡鏈接斷掉了,slave 會讓 master 從上次 replica offset 開始繼續複製,若是沒有找到對應的 offset,那麼就會執行一次 resynchronization。
redis保證數據同步機制
master和slave都會維護一個offset
master會在自身不斷累加offset,slave也會在自身不斷累加offset slave每秒都會上報本身的offset給master,同時master也會保存每一個slave的offset,檢測offset來保證數據的一致性
backlog
master node有一個backlog,默認是1MB大小 master node給slave node複製數據時,也會將數據在backlog中同步寫一份 backlog主要是用來作全量複製中斷候的增量複製的
master run id
若是根據host+ip定位master node,是不靠譜的,若是master node重啓或者數據出現了變化,那麼slave node應該根據不一樣的run id區分,run id不一樣就作全量複製 若是須要不更改run id重啓redis,可使用redis-cli debug reload命令
psync
從節點使用psync從master node進行復制,psync runid offset。master node會根據自身的狀況返回響應信息,多是FULLRESYNC runid offset觸發全量複製,多是CONTINUE觸發增量複製
redis cluster 模式
redis 服務節點中任何兩個節點之間都是相互連通的。客戶端能夠與任何一個節點相鏈接,而後就能夠訪問集羣中的任何一個節點。對其進行存取和其餘操做。
通常集羣建議搭建三主三從架構,三主提供服務,三從提供備份功能。
每個節點都存有這個集羣全部主節點以及從節點的信息。
Redis集羣數據分片
在redis的每個節點上,都有這麼兩個東西,一個是插槽(slot)能夠理解爲是一個能夠存儲兩個數值的一個變量這個變量的取值範圍是:0-16383。還有一個就是cluster我我的把這個cluster理解爲是一個集羣管理的插件。當咱們的存取的key到達的時候,redis會根據crc16的算法得出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,經過這個值,去找到對應的插槽所對應的節點,而後直接自動跳轉到這個對應的節點上進行存取操做。
投票過程是集羣中全部master參與,若是半數以上master節點與master節點通訊超時(cluster-node-timeout),認爲當前master節點掛掉.
何時整個集羣不可用(cluster_state:fail)?
若是集羣任意master掛掉,且當前master沒有slave.集羣進入fail狀態,也能夠理解成集羣的slot映射[0-16383]不完整時進入fail狀態.
一個Redis實例具有了「數據存儲」和「路由重定向」,徹底去中心化的設計。這帶來的好處是部署很是簡單,直接部署Redis就行,不像Codis有那麼多的組件和依賴。但帶來的問題是很難對業務進行無痛的升級,若是哪天Redis集羣出了什麼嚴重的Bug,就只能回滾整個Redis集羣。
優勢:
一、有效的解決了redis在分佈式方面的需求
二、遇到單機內存,併發和流量瓶頸等問題時,可採用Cluster方案達到負載均衡的目的
三、可實現動態擴容
四、P2P模式,無中心化
五、經過Gossip協議同步節點信息
六、自動故障轉移、Slot遷移中數據可用
缺點:
一、架構比較新,最佳實踐較少
二、爲了性能提高,客戶端須要緩存路由表信息
三、節點發現、reshard操做不夠自動化
redis 哨兵
哨兵的功能:
- 集羣監控:負責監控 redis master 和 slave 進程是否正常工做。
- 消息通知:若是某個 redis 實例有故障,那麼哨兵負責發送消息做爲報警通知給管理員。
- 故障轉移:若是 master node 掛掉了,會自動轉移到 slave node 上。
- 配置中心:若是故障轉移發生了,通知 client 客戶端新的 master 地址。
哨兵用於實現 redis 集羣的高可用,自己也是分佈式的,做爲一個哨兵集羣去運行,互相協同工做。
故障轉移時,判斷一個 master node 是否宕機了,須要大部分的哨兵都贊成才行,涉及到了分佈式選舉的問題。
即便部分哨兵節點掛掉了,哨兵集羣仍是能正常工做的。
哨兵的核心知識
- 哨兵至少須要 3 個實例,來保證本身的健壯性。
- 哨兵 + redis 主從的部署架構,是不保證數據零丟失的,只能保證 redis 集羣的高可用性。
- 對於哨兵 + redis 主從這種複雜的部署架構,儘可能在測試環境和生產環境,都進行充足的測試和演練。
數據丟失問題的解決方案?
進行以下配置: min-slaves-to-write 1 min-slaves-max-lag 10
要求至少有 1 個 slave,數據複製和同步的延遲不能超過 10 秒。若是說一旦全部的 slave,數據複製和同步的延遲都超過了 10 秒鐘,那麼這個時候,master 就不會再接收任何請求了。
減小異步複製數據的丟失 有了 min-slaves-max-lag 這個配置,就能夠確保說,一旦 slave 複製數據和 ack 延時太長,就認爲可能 master 宕機後損失的數據太多了,那麼就拒絕寫請求,這樣能夠把 master 宕機時因爲部分數據未同步到 slave 致使的數據丟失下降的可控範圍內。 減小腦裂的數據丟失 若是一個 master 出現了腦裂,跟其餘 slave 丟了鏈接,那麼上面兩個配置能夠確保說,若是不能繼續給指定數量的 slave 發送數據,並且 slave 超過 10 秒沒有給本身 ack 消息,那麼就直接拒絕客戶端的寫請求。
怎麼保證redis是高併發以及高可用的?
1.sdown 和 odown 轉換機制
sdown 是主觀宕機,就一個哨兵若是本身以爲一個 master 宕機了,那麼就是主觀宕機。odown 是客觀宕機,若是 quorum 數量的哨兵都以爲一個 master 宕機了,那麼就是客觀宕機。
sdown 達成的條件很簡單,若是一個哨兵 ping 一個 master,超過了 is-master-down-after-milliseconds 指定的毫秒數以後,就主觀認爲 master 宕機了。sdown到odown轉換的條件很簡單,若是一個哨兵在指定時間內,收到了 quorum 數量的 其它哨兵也認爲那個 master 是 sdown 的,那麼就認爲是 odown 了,客觀認爲master宕機。
2.哨兵集羣的自動發現機制
哨兵互相之間的發現,是經過 redis 的 pub/sub 系統實現的,每一個哨兵都會往sentinel:hello這個 channel 裏發送一個消息,這時候全部其餘哨兵均可以消費到這個消息,並感知到其餘的哨兵的存在。 每隔兩秒鐘,每一個哨兵都會往本身監控的某個 master+slaves 對應的sentinel:hello channel 裏發送一個消息,內容是本身的 host、ip 和 runid 還有對這個 master 的監控配置。 每一個哨兵也會去監聽本身監控的每一個 master+slaves 對應的sentinel:hello channel,而後去感知到一樣在監聽這個 master+slaves 的其餘哨兵的存在。 每一個哨兵還會跟其餘哨兵交換對 master 的監控配置,互相進行監控配置的同步。
3.slave 配置的自動糾正
哨兵會負責自動糾正 slave 的一些配置,好比 slave 若是要成爲潛在的 master 候選人,哨兵會確保 slave 複製現有 master 的數據; 若是 slave 鏈接到了一個錯誤的 master 上,好比故障轉移以後,那麼哨兵會確保它們鏈接到正確的 master 上。
4.slave->master 選舉算法
若是一個 master 被認爲 odown 了,並且 majority 數量的哨兵都容許主備切換,那麼某個哨兵就會執行主備切換操做,此時首先要選舉一個 slave 來,會考慮 slave 的一些信息:
跟 master 斷開鏈接的時長 0slave 優先級 複製 offset run id
若是一個 slave 跟 master 斷開鏈接的時間已經超過了down-after-milliseconds的 10 倍,外加 master 宕機的時長,那麼 slave 就被認爲不適合選舉爲 master。
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下來會對 slave 進行排序:
按照 slave 優先級進行排序,slave priority 越低,優先級就越高。 若是 slave priority 相同,那麼看 replica offset,哪一個 slave 複製了越多的數據,offset 越靠後,優先級就越高。 若是上面兩個條件都相同,那麼選擇一個 run id 比較小的那個 slave。
5.quorum 和 majority
每次一個哨兵要作主備切換,首先須要 quorum 數量的哨兵認爲 odown,而後選舉出一個哨兵來作切換,這個哨兵還得獲得 majority 哨兵的受權,才能正式執行切換。 若是 quorum < majority,好比 5 個哨兵,majority 就是 3,quorum 設置爲2,那麼就 3 個哨兵受權就能夠執行切換。 可是若是 quorum >= majority,那麼必須 quorum 數量的哨兵都受權,好比 5 個哨兵,quorum 是 5,那麼必須 5 個哨兵都贊成受權,才能執行切換。
6.configuration epoch
哨兵會對一套 redis master+slaves 進行監控,有相應的監控的配置。 執行切換的那個哨兵,會從要切換到的新 master(salve->master)那裏獲得一個 configuration epoch,這就是一個 version 號,每次切換的 version 號都必須是惟一的。 若是第一個選舉出的哨兵切換失敗了,那麼其餘哨兵,會等待 failover-timeout 時間,而後接替繼續執行切換,此時會從新獲取一個新的 configuration epoch,做爲新的 version 號。
7.configuraiton 傳播
哨兵完成切換以後,會在本身本地更新生成最新的 master 配置,而後同步給其餘的哨兵,就是經過以前說的 pub/sub 消息機制。 這裏以前的 version 號就很重要了,由於各類消息都是經過一個 channel 去發佈和監聽的,因此一個哨兵完成一次新的切換以後,新的 master 配置是跟着新的 version 號的。其餘的哨兵都是根據版本號的大小來更新本身的 master 配置的。小編這邊整理了一些Redis分佈式鎖的資料以及2020最新的Java核心面試資料集錦,關注公衆號:麒麟改bug。
小編分享的內容到這裏就結束了!