Redis哨兵(Sentinel)模式

## 一、主從複制高可用
當我們使用主從複制出現的問題
- 手動故障轉移
- 寫能力和存儲能力受限
- 主從複制 -master 當機故障處理
Redis哨兵(Sentinel)模式Redis哨兵(Sentinel)模式
主從切換技術的方法是:當主伺服器當機後,需要手動把一台從伺服器切換為主伺服器,這就需要人工幹預,費事費力,還會造成一段時間内服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。
~哨兵模式概述
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的指令,哨兵是一個獨立的程序,作為程序,它會獨立運作。其原理是哨兵通過發送指令,等待Redis伺服器響應,進而監控運作的多個Redis執行個體。
哨兵主要有兩個作用
- 通過發送指令,讓Redis伺服器傳回監控其運作狀态,包括主伺服器和從伺服器。
- 當哨兵監測到master當機,會自動将slave切換成master,然後通過釋出訂閱模式通知其他的從伺服器,修改配置檔案,讓它們切換主機。
然而一個哨兵程序對Redis伺服器進行監控,可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。
故障切換(failover)的過程。假設主伺服器當機,哨兵1先檢測到這個結果,系統并不會馬上進行failover過程,僅僅是哨兵1主觀的認為主伺服器不可用,這個現象成為主觀下線。當後面的哨兵也檢測到主伺服器不可用,并且數量達到一定值時,那麼哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行failover操作。切換成功後,就會通過釋出訂閱模式,讓各個哨兵把自己監控的從伺服器實作切換主機,這個過程稱為客觀下線。這樣對于用戶端而言,一切都是透明的。
## 二、架構說明
- 多個sentinel 發現并确認master有問題。
- 選舉出一個sentinel作為上司
- 選出一個slave作為master
- 通知其餘的slave成為新的master的slave
- 通知用戶端主從變化
- 等待老的master複活成新的master的slave
## 三、安裝配置
- 配置主從節點
- 主節點
啟動指令:redis-server redis-7000.conf
配置
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/opt/soft/redis/data/"
- Redis從節點
redis-server redis-7001.conf
redis-server redis-7002.conf
slave-1:
port 7002
daemonize yes
pidfile /var/run/redis-7002.pid
logfile "7002.log"
dir "/opt/soft/redis/data/"
slaveof 127.0.0.1 7000
slave-2:
port 7001
daemonize yes
pidfile /var/run/redis-7001.pid
logfile "7001.log"
dir "/opt/soft/redis/data/"
slaveof 127.0.0.1 7000
- 配置開啟sentinel監控主節點
- sentine 主要配置 編輯 sentinel.conf
port ${port}
dir "/opt/soft/redis/data/"
logfile "${port}.log"
// 配置監聽的主伺服器,這裡sentinel monitor代表監控,mymaster代表伺服器的名稱,可以自定義,192.168.11.128代表監控的主伺服器,6379代表端口,2代表隻有兩個或兩個以上的哨兵認為主伺服器不可用的時候,才會進行failover操作。
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-millseseconds mymaster 30000 //判斷主節點時間
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
啟動
redis-sentinel sentinel.conf
可以使用 ps -ef|grep redis-sentinel 指令檢視程序、
## 四、實作原理
- 故障轉移 --- java實作
/**
* 測試Redis哨兵模式
* @author liu
*/
public class TestSentinels {
@SuppressWarnings("resource")
@Test
public void testSentinel() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
// 哨兵資訊
Set<String> sentinels = new HashSet<>(Arrays.asList("127.0.0.1:26379","1127.0.0.1:26379","127.0.0.1:26379"));
// 建立連接配接池
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456");
// 擷取用戶端
Jedis jedis = pool.getResource();
// 執行兩個指令
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println(value);
}
}
如果我們把主伺服器停掉,在經過一段時間的報錯後,redis叢集會恢複
- 主觀下線和客觀下線
-
- 主觀下線:目前sentintel節點認為某個redis節點不可用。
- 客觀下線:所有sentinel節點認為某個redis節點不可用。
- 三個定時任務
- 每10秒每個sentinel對master 和 slave執行info
- 發現slave節點 - 确認主從關系
- 每2秒每個sentinel通過master節點對channel交換資訊(釋出訂閱)
- 通過_sentinel_:hello頻道互動 - 互動對節點的“看法”和自身資訊
- 每1秒每個sentinel 對其他sentinel和redis執行ping
- 上司者選舉
- 隻需要一個sentinel節點完成故障轉移
- 通過sentinel is - master -down -by-addr 指令都希望成為上司者
-1. 每個主觀下線都Sentitle 節點向其他Sentinel節點發送指令,要求将它設定為上司者 -2. 收到指令對Sentinel節點如果沒有同一通過其他Sentinel節點發送的指令,那麼就将同一該請求,否則拒絕 -3. 如果該Sentinel節點發現直接的票數已經超過Sentinel集合半數且超過quorum,那麼它将成為上司者 -4. 如果此過程由多個Sentinel節點成為上司者,那麼将來等待一段時間重新進行選舉
- 故障轉移(Sentinel上司者節點完成)
- 1.從slave節點中選出一個 “合适點”節點作為master節點
- 2.對上面對slave節點執行slaveof no one 指令讓其成為master節點。
- 3.向剩餘的slave節點發送指令,讓它們成為新的maater節點的slave節點,複制規避和parallel-syncs參數有關
- 4.更新對原來master節點配置為slave,并保持着對其 “關注”,當其恢複後指令他去複制新對master節點
- 選擇 “合适的” slave節點
- 1.選擇slave-priority(slave節點優先級)最高對slave節點,如果存在傳回,不存在繼續
- 2.選擇複制偏移量最大的slave節點,複制最完整,存在傳回,不存在繼續
- 3.選擇runId最小的slave節點
## 五、需要說明的問題
- 盡可能在不同實體機上和同一個網絡部署Redis sentinel的所有節點
- Redis sentinel中的sentinel節點個數應該大于等于3且最好是奇數。(節點數多可以保證高可用)
- Redis sentinel中的資料節點和普通資料節點沒有差別。每個sentinel節點在本質上還是一個Redis執行個體,隻不過和Redis資料節點不同的是,其主要作用是監控Redis資料節點
- 用戶端初始化時連接配接的是sentinel節點集合,不再是具體的Redis節點,但sentinel隻是配置中心不是代理。
個人部落格:
http://blog.yanxiaolong.cn/