Redis5.0 主從模式和高可用 搭建和測試報告

netcore開發發表於2020-12-22

Redis 單機模式很簡單,相關測試水文看這裡

Redis5 壓力測試結果反饋報告

必須的,今天接著寫水文,寫一寫現在redis 支援的三種叢集,主從模式,哨兵模式,Cluster模式,今天先搞主從模式

主從模式

 主從模式是最簡單的叢集模式,其實就是複製基本只能解決讀寫分離問題,主機伺服器一旦當機基本完蛋,不具備高可用

基本上redis的效能瓶勁主要在於網路IO和記憶體主頻上面,單機版Redis在不考慮高可用的情況下基本滿足80%的專案需要,因為單機版Redis可以實現10W/S的請求,除非快取K-V值過大,通過讀寫分離快取網路卡的壓力,否則這個併發處理能力可以應對大部分專案。

幾乎所有的主從模式都是從伺服器只提供只讀不寫的功能,否則會出現資料不一致的情況,現在無論那種資料庫都不支援雙向同步。

屁話少說,上配置程式碼,主伺服器不需要配置,只需簡單一句程式碼配置從伺服器即可,宣告主伺服器是誰,餘下的redis會自行交流。

slaveof 192.168.3.143 6379

一主多從

主伺服器:192.168.3.143
從伺服器:192.168.3.144
從伺服器:192.168.3.145

從伺服器 redis.conf 配置檔案加入
slaveof 192.168.3.143 6379

  

一主多從(鏈式結構),所謂鏈式結構就是可以從伺服器同步從伺服器

主伺服器:192.168.3.143
從伺服器:192.168.3.144
從伺服器:192.168.3.145

從伺服器 redis.conf 配置檔案加入
slaveof 192.168.3.143 6379
從伺服器:192.168.3.147 
從伺服器 redis.conf 配置檔案加入
slaveof 192.168.3.144 6379

嘗試一下程式上來實現讀寫分離,Net Core 使用StackExchange.Redis 進行訪問Redis叢集,其它元件自己研究吧

//宣告伺服器地址,StackExchange會自己認別那個是主從關係
ConfigurationOptions option = new ConfigurationOptions();
option.EndPoints.Add("192.168.3.143", 6379);
option.EndPoints.Add("192.168.3.144", 6379);
option.EndPoints.Add("192.168.3.145", 6379);
option.EndPoints.Add("192.168.3.147", 6379);
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(option);

IDatabase db = redis.GetDatabase();
db.StringSet("test", "testvalue", flags: CommandFlags.DemandMaster);//CommandFlags.DemandMaster 標明主伺服器寫入
string value = db.StringGet("test", flags: CommandFlags.DemandReplica);//CommandFlags.DemandReplica 標明從伺服器讀取
Console.WriteLine(value);

程式碼行得通,己經分別從主/從伺服器讀取到資料,接下來將是要測試,主伺服器倒下來了,會是怎麼樣?如圖:成功報錯,恭喜某程式猿喜提系統異常一次

 

接下三張圖片將展示依次關閉從伺服器:192.168.3.147,192.168.3.145 ,192.168.3.144  最後一張圖將意味著己關閉所有從伺服器,所有從伺服器己關閉,程式執行成功報錯

   

接著測試一下,StackExchange.Redis 框架問題,而對三個從伺服器是否能分流從不同的從伺服器取值,從而減輕從伺服器的壓力

  

從監控的圖片來,三張從伺服器的圖示顯示,StackExchange.Redis的確平均的分流的請求的流量。

哨兵模式

 哨兵模式基本就是主從模式的升級版,主要解決高可用問題,實現自動容錯和恢復

簡單理解就是主從模式一旦主機伺服器當機需要人工處理,這樣一來你或者運維,得有一個睡不著,Redis引進哨兵模式的作用就是監控Redis服務是否正常運作,主伺服器出現故障將自動將從伺服器轉換為主伺服器。

理想狀態下的配置架構如下:哨兵監控主從伺服器,哨兵之間相互監控,組成哨兵組推薦三個哨兵以上並且最好獨立部署,唯一能節省成本的好訊息就是他們可以監控多個主伺服器。

工作原理:

  1. 每個哨兵都會監控主/從伺服器及其它哨兵。
  2. 當有一個哨兵檢查主伺服器下線(沒有規定時間回覆ping請求),會將主伺服器標識為主觀下線
  3. 當主伺服器被標為主觀下線,其它哨兵會馬上檢查主服務線上狀態。
  4. 當足夠的哨兵(超過配置數量)將它標識為主觀下線,主伺服器會變成客觀下線,如果數量不夠則主觀下線狀態會除移。
  5. 主伺服器客觀下線之後哨兵會從“從伺服器”中選中一臺伺服器當主伺服器。
  6. 哨兵將修改其它從伺服器以及被修復舊主伺服器的配置,將統一修改為從伺服器並且修改它們的主伺服器地址。

注意:每個哨兵配置不一樣,每個哨兵根據自己的配置超時時間來判斷主伺服器是否主觀下線只有符合就標為主觀下線,每個哨兵根據自己設定的“肯定數量”來判斷主伺服器是否客觀下線,只要有一個哨兵的配置達到客觀下線該哨兵就會執行故障遷移操作。

從伺服器選舉原理:

  1. 首先發現客觀下線的哨兵會發起一個選舉請求,根據Raft演算法,一般會成為領頭哨頭。
  2. 根據與主伺服器的斷開的時間判斷
  3. 根據從伺服器配置檔案的權重(slave-priority)選舉為主伺服器
  4. 複製偏移,從主節點收到更多的新資料的節點會被選擇
  5. 在所有條件相同的情況,選擇runid最小的為主伺服器

配置:只需要配置主資料庫即可,哨兵會自動發現所有從資料庫並進行監控,哨兵之間可以相互發現,只要確保埠放行就可以了,簡單版配置簡單到只有一句話

sentinel monitor <master-group-name> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2 //示例
//監控一個叫做mymaster的主節點,地址是 127.0.0.1 埠號是6379,判斷客觀下線需要2個哨兵“肯定”
//當然還有一些其它較為重要的配置,可以手動設定
sentinel down-after-milliseconds mymaster 60000 //設定檢查超時時間,超過這個時間將認定為主觀下線,預設30秒

下面進一些場景測試以驗證觀點,雖然支援採用預設配置的方式來進行啟動,我們還是使用配置檔案的方式進行啟動

//主伺服器
bind 0.0.0.0
port 6379
daemonize yes

//從伺服器
bind 0.0.0.0
port 6379
daemonize yes
slaveof 192.168.3.40 6379

測試場景一:簡單版測試,一主一從一哨兵,主伺服器故障,能否自動將從伺服器轉換為主伺服器

sentinel monitor mymaster 192.168.3.40 6379 1
sentinel down-after-milliseconds mymaster 5000//內網配置五秒就足夠了
daemonize yes

成功執行

編寫檢查程式碼

    class Program
    {
        static void Main(string[] args)
        {
            //宣告伺服器地址,StackExchange會自己認別那個是主從關係
            ConfigurationOptions option = new ConfigurationOptions();
            option.EndPoints.Add("192.168.3.40", 6379);
            option.EndPoints.Add("192.168.3.167", 6379);
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(option);

            IDatabase db = redis.GetDatabase();
            db.StringSet("test", "testvalue");
            DateTime exStartTime = DateTime.Now;
            DateTime exEndTime;
            bool isEX = false;
            while (true)
            {
                try
                {
                    var value = db.StringGet("test");
                    Console.WriteLine(value);
                    if (!value.HasValue && isEX!)
                        Console.WriteLine(value);
                    if (isEX && value.HasValue == true)
                    {
                        exEndTime = DateTime.Now;
                        Console.WriteLine($"連線成功,獲取的值是:{value}");
                        break;
                    }
                }
                catch (Exception e)
                {
                    if (isEX == false)
                    {
                        Console.WriteLine($"連線失敗!{e.Message}");
                        exStartTime = DateTime.Now;
                        isEX = true;
                    }
                }
            }
            Console.WriteLine($"連線異常時間{exStartTime},故障遷移成功時間{exEndTime},花費{(exEndTime - exStartTime).TotalSeconds}秒");
        }
    }

悄悄開啟ESXI 把虛擬機器的網線拔掉

果然成功報錯,並且進行故障轉移

這個時候,重新把網路設定回來,並且檢視兩個redis.conf的配置檔案內容,發現配置己被改動,192.168.3.40 己由主伺服器轉變成從伺服器,哨兵的配置也相應作了改變

  

測試場景二:一主三從一哨兵

//主伺服器(192.168.3.40)
bind 0.0.0.0
port 6379
daemonize yes

//從伺服器(192.168.3.167)
bind 0.0.0.0
port 6379
daemonize yes
slaveof 192.168.3.40 6379

//從伺服器(192.168.3.168)
bind 0.0.0.0
port 6379
daemonize yes
slaveof 192.168.3.40 6379

//從伺服器(192.168.3.169)
bind 0.0.0.0
port 6379
daemonize yes
slaveof 192.168.3.40 6379

哨兵的配置依舊不變

//哨兵伺服器(192.168.3.171)
sentinel monitor mymaster 192.168.3.40 6379 1
sentinel down-after-milliseconds mymaster 5000//內網配置五秒就足夠了
daemonize yes

 一頓操作猛如虎,斷掉網路

成功切換,看看這四臺伺服器的配置都發現了什麼變化吧

   

測試場景三:一主三從三哨兵

主從伺服器的配置不變,哨兵的配置稍有變化,哨兵的伺服器由一臺增加到三臺,分別是192.168.3.171,192.168.3.172,192.168.3.170,哨兵能相互發現和相互監控

sentinel monitor mymaster 192.168.3.40 6379 2 //裁仲伺服器由1臺變成2臺
sentinel down-after-milliseconds mymaster 5000//內網配置五秒就足夠了
daemonize yes

好了,準備就緒,故技重演,斷網

檢視一下四臺Redis伺服器配置發生什麼變化

   

檢視一下,三臺哨兵的配置發生什麼變化

  

就測到這裡吧,下班了,明天大夥要是有興趣,再搗鼓一下,Cluster模式,就是分散式叢集,不知道有沒有人看這些水文

 

相關文章