Redis——Sentinel
Sentinel——主從複製高可用方案
在使用主從複製時,我們面臨以下問題:
-
手動故障轉移
在發生上圖中的master當機之後,我們必須手動替換主節點,就像下圖:
-
寫能力和儲存能力受限(採用讀寫分離時)
因此,Redis為我們提供了Sentinel架構:
Sentinel是一個管理redis例項的工具,它可以實現對redis的監控、通知、自動故障轉移。sentinel不斷地檢測redis例項是否可以正常工作,通過API向其他程式報告redis的狀態,如果redis master不能工作,則會自動啟動故障轉移程式,將其中的一個slave提升為master,其他的slave重新設定新的master伺服器。
- Sentinel作用:
- Master狀態檢測
- 如果Master異常,則會進行Master-Slave切換,將其中一個Slave作為Master,將之前的Master作為Slave
- Master-Slave切換後,master_redis.conf、slave_redis.conf和sentinel.conf的內容都會發生改變,即master_redis.conf中會多一行slaveof的配置,sentinel.conf的監控目標會隨之調換
- sentinel實現原理
-
sentinel建立兩個連線master的 非同步網路連線
- 命令連線:向master傳送命令,並接受回覆(預設十秒一次通過INFO來獲取master資訊)
- 訂閱連線:訂閱master的sentinel:hello頻道(依賴於Redis的訂閱釋出,因為我們以前說過Redis是不能儲存過期釋出訊息的,所以,slave節點可能錯過master的訊息,所以需要sentinel來接受這些資訊提供給slave,同時其他sentinel也可以獲取最新資訊)
-
sentinel建立兩個連線slave的 非同步網路連線(當發現新的slave出現時)
- 命令連線:向slave傳送命令,並接受回覆(預設十秒一次通過INFO來獲取slave資訊)
- 訂閱連線:訂閱slave的頻道
-
建立連向其他sentinel的命令連線(用於資訊交換:主觀/客觀下線檢測)
- sentinels字典:為master建立,用於儲存自身以及其他監視該master的sentinel節點資訊
不需要訂閱連線的原因:sentinel訂閱了master和slave的頻道,會接受到新sentinel的資訊
- sentinels字典:為master建立,用於儲存自身以及其他監視該master的sentinel節點資訊
-
下線檢測:
- sentinel預設每秒一次向建立了命令連線的所有節點(包括sentinel)傳送PING命令,用於檢測是否線上
- 主觀下線:當master超過down-after-milliseconds設定的時間仍然返回無效回覆時,這時候sentinel將master標記為主觀下線
- 客觀下線:在標記為主觀下線後,改sentinel會想其他監視該master的節點通過命令連線進行詢問,當贊同的數量達到我們設定的數量時,認為該master客觀下線。
上面的總結一下可以認為是sentinel的三個定時任務:
- 每10秒每個sentinel對master和slave執行INFO(故障轉移時改為1秒)
- 發現slave節點
- 確認主從關係
- 每2秒每個sentinel通過節點的channel向所有主從節點傳送命令
- 交換對master節點的看法和自身資訊(更新sentinels字典以及master節點例項結構)
- 每1秒每個sentinel對其他的sentinel和節點執行ping(心跳檢測)
- 下線檢測(主觀下線判斷)
-
- 故障轉移
在判斷master客觀下線後,選舉出的sentinel將進行故障轉移- 多個sentinel發現並確認master有問題
- 選舉出一個sentinel作為領導
- 選舉出一個slave作為master
- 通知其餘slave成為新的master的slave
- 通知客戶端主從變化
- 等待老的master復活成為新master的slave
- 領導者選舉
- 每個做主觀下線的sentinel節點向其他sentinel節點傳送sentinel is-master-down-by-addr 命令,要求成為領導者
- 收到命令的sentinel節點如果沒有同意過其他sentinel節點的請求,將同意該請求,否則拒絕
- 當票數超過sentinel節點半數且超過quorum,將成為領導者
- 若此過程有多個sentinel節點成為領導者,將等待一會重新選舉
- sentinel備份策略
可以參考以前的文章《Redis——持久化》 - 部署sentinel主從配置
我們這裡是採用了三臺物理機,一共五個節點,一主四從,三個sentinel節點。- 主節點主要配置
#開放外網訪問
bind 0.0.0.0
#下面我們設定了密碼,所以開啟安全模式
protected-mode yes
#開放埠
port 6379
#設定為守護執行緒
daemonize yes
#pid檔案
pidfile "/var/run/redis_6379.pid"
#日誌檔案
logfile "6379.log"
#rdb檔案
dbfilename "dump-6379.rdb"
#檔案路徑
dir "/var/redis/6379"
#主節點訪問密碼(主節點也要設定是因為故障切換後主節點有可能變為從節點)
masterauth "password"
requirepass "password"
- 從節點配置
#開放外網訪問
bind 0.0.0.0
#下面我們設定了密碼,所以開啟安全模式
protected-mode yes
#開放埠
port 6380
#設定為守護執行緒
daemonize yes
#pid檔案
pidfile "/var/run/redis_6380.pid"
#日誌檔案
logfile "6379.log"
#rdb檔案
dbfilename "dump-6380.rdb"
#檔案路徑
dir "/var/redis/6380"
#主節點訪問密碼
masterauth "password"
#該節點密碼
requirepass "password"
#設定主節點 我用的公網ip
slaveof 120.1.1.1 6379
#設定從節點只讀
slave-read-only yes
其他從節點類似
- 哨兵節點配置
bind 0.0.0.0
port 26379
#要監控的主節點名稱、ip、port ,2表示將這個主伺服器判斷為失效至少需要 2 個 Sentinel 同意
sentinel monitor mymaster 120.1.11.11 6379 2
# Sentinel 認為伺服器已經斷線所需的毫秒數。
sentinel down-after-milliseconds mymaster 60000
# failover過期時間,當failover(選出新的master)開始後,在此時間內仍然沒有觸發任何failover操作,當前sentinel 將會認為此次failoer失敗
sentinel failover-timeout mymaster 180000
#指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。
sentinel parallel-syncs mymaster 1
其他哨兵節點類似,只是埠不同。
- 哨兵模式測試
編寫一個工具類,用來獲取jedis例項
public class RedisUtil {
/*redis-sentinel節點地址*/
private static final String SENTINEL_1 = "ip:26379";
private static final String SENTINEL_2 = "ip1.31:26380";
private static final String SENTINEL_3 = "ip:26381";
//sentinel節點地址集合
private static final Set<String> SENTINELS = new HashSet<String>() {
{
add(SENTINEL_1);
add(SENTINEL_2);
add(SENTINEL_3);
}
};
//masterName
private static final String MASTER_NAME = "mymaster";
// 訪問密碼
private static String AUTH = "password";
private static String HOST = "ip";
/**
* 可用連線例項的最大數目,預設值為8; 如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。
*/
private static int MAX_ACTIVE = 1024;
// 控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。
private static int MAX_IDLE = 200;
// 等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。如果超過等待時間,則直接丟擲JedisConnectionException;
private static int MAX_WAIT = 10000;
private static int TIMEOUT = 10000;
// 在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;
private static boolean TEST_ON_BORROW = true;
/*sentinelPool*/
private static JedisSentinelPool SENTINEL_POLL = null;
/**
* 初始化Redis-Sentinel連線池.
*/
static {
try {
// maxActive ==> maxTotal
// maxWait ==> maxWaitMillis
JedisPoolConfig CONFIG = new JedisPoolConfig();
CONFIG.setMaxTotal(MAX_ACTIVE);
CONFIG.setMaxIdle(MAX_IDLE);
CONFIG.setMaxWaitMillis(MAX_WAIT);
CONFIG.setTestOnBorrow(TEST_ON_BORROW);
SENTINEL_POLL = new JedisSentinelPool(MASTER_NAME, SENTINELS, AUTH);
System.out.println(SENTINEL_POLL.getCurrentHostMaster());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取Jedis例項.
*/
public static synchronized Jedis getJedis() {
Jedis jedis = null;
int count = 0;
do {
try {
jedis = SENTINEL_POLL.getResource();
} catch (Exception e) {
e.printStackTrace();
}
count++;
} while (jedis == null && count < 10);
return jedis;
}
/**
* 釋放jedis資源
*/
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
}
測試客戶端
public class RedisClient {
public static void main(String[] args) {
Jedis jedis = RedisUtil.getJedis();
jedis.set("4", "1");
jedis.set("5", "2");
jedis.set("6", "3");
System.out.println(jedis.get("4"));
System.out.println(jedis.get("5"));
System.out.println(jedis.get("6"));
RedisUtil.returnResource(jedis);
}
}
可以看到,可以成功使用了,我們再來測試一下故障轉移是否可用
我們手動關閉主節點,可以看到主節點已經關閉
再來執行一下程式,
發現主節點已經自動切換為其他的節點,最後我們再啟動剛才關閉的主節點,發現他已經成為新主節點的從節點
相關文章
- Redis SentinelRedis
- Redis哨兵sentinelRedis
- Redis sentinel搭建Redis
- redis sentinel 配置Redis
- 【Redis】Sentinel 哨兵模式Redis模式
- Redis高可用 SentinelRedis
- 《Redis官方文件》sentinelRedis
- redis高可用之redis-SentinelRedis
- Redis 哨兵高可用(Sentinel)Redis
- redis sentinel配置啟動Redis
- redis sentinel哨兵 例項Redis
- Redis Sentinel實現原理Redis
- 聊聊Redis sentinel 機制Redis
- Redis Sentinel哨兵模式部署Redis模式
- Redis sentinel主從切換Redis
- 【Redis】Sentinel 高可用架構Redis架構
- Redis Sentinel高可用架構Redis架構
- Redis服務之高可用元件sentinelRedis元件
- Redis Sentinel哨兵模式原理及配置Redis模式
- 玩轉Redis叢集之SentinelRedis
- 分散式Redis深度歷險-Sentinel分散式Redis
- redis的sentinel模式故障演練Redis模式
- redis sentinel 叢集監控 配置Redis
- Redis docker 主從模式與哨兵sentinelRedisDocker模式
- Redis之Sentinel高可用安裝部署Redis
- Redis Sentinel 高可用實現說明Redis
- Redis學習筆記(十六) Sentinel(哨兵)(下)Redis筆記
- Redis Sentinel:叢集Failover解決方案RedisAI
- Redis Sentinel機制與用法說明【轉】Redis
- Redis | 第12章 Sentinel 哨兵模式《Redis設計與實現》Redis模式
- Redis基礎知識(學習筆記19--Redis Sentinel)Redis筆記
- redis sentinel哨兵模式安裝部署和切換Redis模式
- Redis-3.2.1 sentinel安裝和配置小記Redis
- windows redis sentinel listen: Unknown error解決方案WindowsRedisError
- Redis Sentinel-深入淺出原理和實戰Redis
- Redis Sentinel高可用配置及C#訪問RedisC#
- Redis 複製、Sentinel的搭建和原理說明Redis
- Redis安裝之叢集-哨兵模式(sentinel)模式Redis模式