1. 程式人生 > >Redis高可用叢集-哨兵模式(Redis-Sentinel)搭建配置教程【Windows環境】

Redis高可用叢集-哨兵模式(Redis-Sentinel)搭建配置教程【Windows環境】

No cross,no crown . 不經歷風雨,怎麼見彩虹。

Redis哨兵模式,用現在流行的話可以說就是一個“哨兵機器人”,給“哨兵機器人”進行相應的配置之後,這個”機器人”可以7*24小時工作,它能能夠自動幫助你做一些事情,如監控,提醒,自動處理故障等。

Redis-sentinel簡介

Redis-sentinel是Redis的作者antirez,因為Redis叢集的被各大公司使用,每個公司要寫自己的叢集管理工具,於是antirez花了幾個星期寫出了Redis-sentinel。

Redis 的 Sentinel 系統用於管理多個 Redis 伺服器(instance),Redis 的 Sentinel 為Redis提供了高可用性。使用哨兵模式建立一個可以不用人為干預而應對各種故障的Redis部署。

該系統執行以下三個任務:

  • 監控(Monitoring):Sentinel會不斷地檢查你的主伺服器和從伺服器是否允許正常。
  • 提醒(Notification):當被監控的某個Redis伺服器出現問題時,Sentinel可以通過API向管理員或者其他應用程式傳送通知。
  • 自動故障遷移(Automatic failover): (1)當一個主伺服器不能正常工作時,Sentinel會開始一次自動故障遷移操作,他會將失效主伺服器的其中一個從伺服器升級為新的主伺服器,並讓失效主伺服器的其他從伺服器改為複製新的主伺服器;
    (2)客戶端試圖連線失敗的主伺服器時,叢集也會向客服端返回新主伺服器的地址,是的叢集可以使用新主伺服器代替失效伺服器。
     

sentinel的分散式特性

Redis Sentinel 是一個分散式系統, 你可以在一個架構中執行多個 Sentinel 程序(progress), 這些程序使用流言協議(gossip protocols)來接收關於主伺服器是否下線的資訊, 並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從伺服器作為新的主伺服器。

單個sentinel程序來監控redis叢集是不可靠的,當sentinel程序宕掉後(sentinel本身也有單點問題,single-point-of-failure)整個集群系統將無法按照預期的方式執行。所以有必要將sentinel叢集,這樣有幾個好處:

  • 有一些sentinel程序宕掉了,依然可以進行redis叢集的主備切換;

    • 如果只有一個sentinel程序,如果這個程序執行出錯,或者是網路堵塞,那麼將無法實現redis叢集的主備切換(單點問題);

    • 如果有多個sentinel,redis的客戶端可以隨意地連線任意一個sentinel來獲得關於redis叢集中的資訊

一個健壯的部署至少需要三個哨兵例項。

三個哨兵例項應該放置在客戶使用獨立方式確認故障的計算機或虛擬機器中。例如不同的物理機或不同可用區域的虛擬機器。【本次講解是一個機器上進行搭建,和多級是一個道理】

Redis-sentinel搭建

  1. 環境
Windows10
Redis-x64-3.2.100


本次搭建說明:
master:127.0.0.1:6379 【初始化masterslave:127.0.0.1:6380  127.0.0.1:6381

sentinel:127.0.0.1:26379  127.0.0.1:26380  127.0.0.1:26381
  1. 安裝和基本配置
  1. Sentinel配置
    根據安裝和基本配置,已經有了主從配置 ,對應資料夾Redis6379~Redis6381。然後在每個資料夾下面新增 一個名為 sentinel.conf 的檔案。配置內容如下:
# 這個是Redis6379配置內容,其他檔案同理新增然後改一下埠即可,26380,和 26381。

#當前Sentinel服務執行的埠
port 26379  
# 哨兵監聽的主伺服器 
sentinel monitor mymaster 127.0.0.1 6379 2
# 3s內mymaster無響應,則認為mymaster宕機了
sentinel down-after-milliseconds mymaster 3000
#如果10秒後,mysater仍沒啟動過來,則啟動failover  
sentinel failover-timeout mymaster 10000  
# 執行故障轉移時, 最多有1個從伺服器同時對新的主伺服器進行同步
sentinel parallel-syncs mymaster 1

配置檔案只需要配置master的資訊就好啦,不用配置slave的資訊,因為slave能夠被自動檢測到(master節點中有關於slave的訊息)。

為了更清楚每一行配置的含義,對每個選項的含義進行簡單介紹:

sentinel monitor [master-group-name] [ip] [port] [quorum]

  • master-group-name:master名稱(可以自定義)
  • ip port : IP地址和埠號
  • quorun:票數,Sentinel需要協商同意master是否可到達的數量。

第一行配置指示 Sentinel 去監視一個名為 mymaster 的主伺服器, 這個主伺服器的 IP 地址為 127.0.0.1 , 埠號為 6379 , 而將這個主伺服器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。
票數在本文中:redis叢集中有3個sentinel例項,其中master掛掉啦,這裡設定票數為2,表示有2個sentinel認為master掛掉啦,才能被認為是正真的掛掉啦。

sentinel <選項的名字> <主伺服器的名字> <選項的值>

  • down-after-milliseconds 選項指定了 Sentinel 認為伺服器已經斷線所需的毫秒數。

如果伺服器在給定的毫秒數之內, 沒有返回 Sentinel 傳送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個伺服器標記為主觀下線(subjectively down,簡稱 SDOWN )。
不過只有一個 Sentinel 將伺服器標記為主觀下線並不一定會引起伺服器的自動故障遷移: 只有在足夠數量的 Sentinel 都將一個伺服器標記為主觀下線之後, 伺服器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ), 這時自動故障遷移才會執行。
將伺服器標記為客觀下線所需的 Sentinel 數量由對主伺服器的配置決定。
- parallel-syncs 選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。

5.其他配置
新增Redis啟動指令碼:startRedisServer.bat

@echo off
redis-server.exe redis.windows.conf
@pause

新增Redis-Sentinel啟動指令碼:startRedisSentinel.bat

@echo off
redis-server.exe sentinel.conf --sentinel 
@pause

在配置啟動startrRedis6379.cmd,其他同理!

@echo off
cd Redis6379
startRedisServer.bat

在配置啟動startrRedisSentinel26379.cmd,其他同理!

@echo off
cd Redis6379
startRedisSentinel.bat
at

配置完如圖:

  1. 啟動Sentinel例項

    哨兵啟動命令 redis-server.exe sentinel.conf –sentinel


第一步:點選startRedis.cmd ,啟動Redis叢集 第二步:點選startRedisSentinel.cmd ,啟動哨兵例項 檢視Sentinel啟動日誌,看到“` 生成哨兵ID(Sentinel ID),並自動識別主伺服器和從伺服器!
[114252] 03 Mar 13:32:57.896 # Sentinel ID is 89f521b40a803495472c0457b0396473c4bfb100
[114252] 03 Mar 13:32:57.896 # +monitor master mymaster 127.0.0.1 6379 quorum 2
[114252] 03 Mar 13:32:57.909 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:32:57.917 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
檢視主伺服器6379(Master)資訊:
F:\nosql_learn\Redis-Sentinel\Redis6379>redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=54148,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=54148,lag=1
master_repl_offset:54414
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:54413
127.0.0.1:6379>
檢視主伺服器6380(Slave)資訊:
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:80531
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>

Redis-Sentinel高可用場景演示

場景1:主伺服器master宕機

當主伺服器master宕機,那麼Sentinel會通過選舉(演算法)機制,從Salve中選出一個作為新Master。 大概原理是當選出一個Slave要作為Master的時候,會發送命令slaveofno one來取消選中的這個slave,使其成為Master。哨兵會發送給其他從伺服器Slave配置選中的這個為新主伺服器Master,並刪除監聽列表中出現故障的Master伺服器。 (1)關閉掉 6379主伺服器
127.0.0.1:6379> shutdown
not connected>

(2)檢視觀察選舉新的master的過程和顯示了failover的過程,整個日誌資訊還是比較完整的。最後選舉了6381為主伺服器!
[114252] 03 Mar 13:32:59.945 * +sentinel sentinel 926e67646440b200ee41bb224bacf9e0314e3b32 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:33:00.018 * +sentinel sentinel 7fc21e38de0408ccaa06111e44638e2693794e08 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.223 # +sdown master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.300 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
[114252] 03 Mar 13:53:19.300 # +new-epoch 1
[114252] 03 Mar 13:53:19.300 # +try-failover master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.306 # +vote-for-leader 89f521b40a803495472c0457b0396473c4bfb100 1
[114252] 03 Mar 13:53:19.319 # 7fc21e38de0408ccaa06111e44638e2693794e08 voted for 89f521b40a803495472c0457b0396473c4bfb100 1
[114252] 03 Mar 13:53:19.369 # +elected-leader master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.370 # +failover-state-select-slave master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.428 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.428 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:19.530 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.327 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.328 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:20.398 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.390 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.390 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.445 # +failover-end master mymaster 127.0.0.1 6379
[114252] 03 Mar 13:53:21.445 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
[114252] 03 Mar 13:53:21.447 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:21.449 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:23.193 # +sdown sentinel 926e67646440b200ee41bb224bacf9e0314e3b32 127.0.0.1 26379 @ mymaster 127.0.0.1 6381
[114252] 03 Mar 13:53:24.451 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381


(3)檢視6381伺服器資訊,角色為主,從伺服器6380!
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=33358,lag=1
master_repl_offset:33505
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:33504
127.0.0.1:6381>

場景2:之前故障的6379 master重新啟動

(1)啟動6379服務,發現6379成為6381的從伺服器!
F:\nosql_learn\Redis-Sentinel\Redis6379>redis-server.exe redis.windows.conf

[116640] 03 Mar 13:59:25.753 * The server is now ready to accept connections on port 6379
[116640] 03 Mar 13:59:48.315 * SLAVE OF 127.0.0.1:6381 enabled (user request from 'id=2 addr=127.0.0.1:61677 fd=7 name=sentinel-7fc21e38-cmd age=10 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0 omem=0 events=r cmd=exec')
[116640] 03 Mar 13:59:48.326 # CONFIG REWRITE executed with success.
[116640] 03 Mar 13:59:48.826 * Connecting to MASTER 127.0.0.1:6381
[116640] 03 Mar 13:59:48.851 * MASTER <-> SLAVE sync started
(2)檢視6381伺服器狀態資訊:原來的master自動切換成slave,不會自動恢復成master。
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=73183,lag=0
slave1:ip=127.0.0.1,port=6379,state=online,offset=73183,lag=0
master_repl_offset:73183
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:73182
127.0.0.1:6381>

場景3:從伺服器Slave宕機和重啟

(1)關閉6380從伺服器:
127.0.0.1:6380> shutdown
not connected>
(2)Sentinel日誌:
[113488] 03 Mar 14:06:50.143 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
(3)檢視住伺服器6381狀態資訊:
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6379,state=online,offset=111361,lag=1
master_repl_offset:111361
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:111360
127.0.0.1:6381>
(4)啟動從伺服器6380
Connecting to MASTER 127.0.0.1:6381
(5)檢視住伺服器6381狀態資訊:6380又回來了!
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6379,state=online,offset=141232,lag=0
slave1:ip=127.0.0.1,port=6380,state=online,offset=141232,lag=1
master_repl_offset:141232
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:141231
127.0.0.1:6381>

Redis-sentinel相關知識

  1. 主觀下線和客觀下線
  2. 每個 Sentinel 都需要定期執行的任務
  3. 自動發現 Sentinel 和從伺服器
    ….

Jedis客戶端使用Sentinel

;

import java.util.HashSet;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class RedisManagerUtil {

    private static JedisSentinelPool pool = null;
    // 自帶的哨兵模式 JedisSentinelPool, 並在一開始初始化連線池
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            // 控制一個pool可分配多少個jedis例項,通過pool.getResource()來獲取;
            // 如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。
            config.setMaxTotal(Integer.valueOf(1000));
            // 控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項。
            config.setMaxIdle(Integer.valueOf(20));
            // 表示當borrow(引入)一個jedis例項時,最大的等待時間,如果超過等待時間,則直接丟擲JedisConnectionException;
            config.setMinEvictableIdleTimeMillis(Integer.valueOf(-1));
            // 在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;
            config.setTestOnBorrow(Boolean.valueOf(true));

            // master名稱和配置檔案中配置的要一樣
            String master = "mymaster";
            //setinel客戶端提供了master自動發現功能
            Set<String> sentinels = new HashSet<String>();
            sentinels.add("127.0.0.1:26379");
            sentinels.add("127.0.0.1:26380");
            sentinels.add("127.0.0.1:26381");

            pool = new JedisSentinelPool(master, sentinels, config);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 構建redis連線池
     * 
     * @return JedisPool
     */
    public static JedisSentinelPool getPool() {
        return pool;
    }

    /**
     * 返還到連線池
     * 
     * @param pool
     * @param redis
     */
    public static void returnResource(JedisSentinelPool pool, Jedis redis) {
        if (redis != null) {
            try {
                pool.returnResource(redis);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 測試redis執行緒池是否正常
     * @param args
     */
    public static void main(String[] args) {
        JedisSentinelPool pool = RedisPoolAPIManager.getPool();
        Jedis redis = pool.getResource();
        System.out.println("redis = " + redis);

        if(redis != null){
            returnResource(pool,redis);
        }
    }
}

總結

Redis-Sentinel是Redis官方推薦的高可用性(HA) 解決方案,Redis-sentinel本身也是一個獨立執行的程序,它能監控多個master-slave叢集,發現master宕機後能進行自動切換。Sentinel可以監視任意多個主伺服器(複用),以及主伺服器屬下的從伺服器,並在被監視的主伺服器下線時,自動執行故障轉移操作。

為了防止sentinel的單點故障,可以對sentinel進行叢集化,建立多個sentinel。

如果你想使用本篇博文中配置的redis-Sentinel,可以在這裡Redis-Sentinel下載!

參考博文

本系列文章:


如果您覺得這篇博文對你有幫助,請點個贊,讓更多的人看到,謝謝!


如果帥氣(美麗)、睿智(聰穎),和我一樣簡單善良的你看到本篇博文中存在問題,請指出,我虛心接受你讓我成長的批評,謝謝閱讀!
祝你今天開心愉快!

歡迎訪問我的csdn部落格,我們一同成長!

不管做什麼,只要堅持下去就會看到不一樣!在路上,不卑不亢!