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主從複製的一些特點:
1.一個master可以有多個slave
2.除了多個slave連到相同的master外,slave也可以連接其他slave形成圖狀結構
3.主從複製不會阻塞master。也就是說當一個或多個slave與master進行初次同步數據時,master可以繼續處理client發來的請求。相反slave在初次同步數據時則會阻塞不能處理client的請求。
4.主從複製可以用來提高系統的可伸縮性,我們可以用多個slave 專門用於client的讀請求,比如sort操作可以使用slave來處理。也可以用來做簡單的數據冗餘
5.可以在master禁用數據持久化,只需要註釋掉master 配置文件中的所有save配置,然後只在slave上配置數據持久化。
6.可以用於讀寫分離和容災恢復。

新建sentinel.conf文件

# 這個是Redis6379配置內容,其他文件同理新增然後改一下端口即可,26380
#當前Sentinel服務運行的端口
protected-mode no
port 26381
# 哨兵監聽的主服務器 後面的1表示主機掛掉以後進行投票,只需要1票就可以從機變主機
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
# 設置哨兵sentinel 連接主從的密碼 注意必須爲主從設置一樣的驗證密碼,沒有的話不用設置
sentinel auth-pass mymaster 123456

在2個文件夾下面都放入此文件,只是端口不同分別啓動2個redis以及2個哨兵,

哨兵啓動命令爲redis-server.exe sentinel.conf --sentinel我們會發現報錯

Creating Server TCP listening socket *:26379: listen: UnKnown error

經過網上查詢得知是沒有配置bind參數的原因,增加bind參數後sentinel.conf文件如下

# 這個是Redis6379配置內容,其他文件同理新增然後改一下端口即可,26380 26381
#當前Sentinel服務運行的端口
port 26381
bind 127.0.0.1
# 哨兵監聽的主服務器 
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
 

 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掛掉啦,才能被認爲是正真的掛掉啦
 

分別啓動2個redis以及2個哨兵,哨兵啓動命令爲redis-server.exe sentinel.conf --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。
 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章