程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SyBase數據庫 >> SyBase教程 >> Redis中sentinel集群的搭建和Jedis測試圖文教程[三]

Redis中sentinel集群的搭建和Jedis測試圖文教程[三]

編輯:SyBase教程

Redis中sentinel集群的搭建和Jedis測試圖文教程[三]


  在前兩篇Redis中sentinel集群的搭建和Jedis測試 圖文教程[一] 和Redis中sentinel集群的搭建和Jedis測試 圖文教程[二] 中分別簡述了Redis中sentinel集群的搭建和Java代碼的Jedis測試。
  
  這篇主要來簡單分析一下Redis-sentinel集群的原理,根據追蹤sentinel信息來完成Redis-sentinel集群測試中的詳細的原理分析。包括master-slave各個中的sentinel信息的分析,failover過程,master宕機後的leader選舉過程等等方面深層次詳細簡述了其各個原理。


一、Redis常見HA方案

  HA(High Available,高可用性群集)機集群系統簡稱,是保證業務連續性的有效解決方案,一般有兩個或兩個以上的節點,且分為活動節點及備用節點。通常把正在執
行業務的稱為活動節點,而作為活動節點的一個備份的則稱為備用節點。當活動節點出現問題,導致正在運行的業務(任務)不能正常運行時,備用節點此時就會偵測到,並立即接續活動節點來執行業務。從而實現業務的不中斷或短暫中斷。From 百度百科.
  Redis 一般以主/從方式部署(這裡討論的應用從實例主要用於備份,主實例提供讀寫)該方式要實現 HA 主要有如下幾種方案:
  1)keepalived:通過 keepalived 的虛擬 IP,提供主從的統一訪問,在主出現問題時, 通過 keepalived 運行腳本將從提升為主,待主恢復後先同步後自動變為主,該方案的好處是主從切換後,應用程序不需要知道(因為訪問的虛擬 IP 不變),壞處是引入 keepalived 增加部署復雜性,在有些情況下會導致數據丟失;
  2) zookeeper: 通過 zookeeper 來監控主從實例, 維護最新有效的 IP, 應用通過 zookeeper取得 IP,對 Redis 進行訪問,該方案需要編寫大量的監控代碼;
  3)sentinel:通過 Sentinel 監控主從實例,自動進行故障恢復,該方案有個缺陷:因為主從實例地址(IP&PORT)是不同的, 當故障發生進行主從切換後, 應用程序無法知道新地址,故 在 Jedis2.2.2 中 新 增 了 對 Sentinel 的 支 持 , 應 用 通 過redis.clients.jedis.JedisSentinelPool.getResource()取得的Jedis實例會及時更新到新的主實例地址。
  下面是該方案的部署邏輯圖。
這裡寫圖片描述

二、Redis-sentinel配置與部署

  詳情請見Redis中sentinel集群的搭建和Jedis測試 圖文教程[一]
  由於 sentinel 服務器已經在 redis 服務器的環境中(redis-sentinel),我們這裡就直接使用它們(在生產環境中,sentinel 服務器和 redis-server 服務器一般是分離的,部署在不同的pc-server 上面,同時 sentinel 的個數和 redis-server 個數也沒聯系,下面為了方便學習使用將3 台 sentinel 服務都放到了一台 pc 上)。
  注意: sentinel 配置文件只和默認的 master 有關系,和 slave 都沒有關系。我們上面的例子是用了 3 個 redis-server 和 3 個 redis-sentinel,其實 redis-sentinel的個數不一定要和 redis-sever 對應,1~n 個都可以。
  首先要清楚,sentinel是一個獨立於redis之外的進程,不對外提供key/value服務。在redis的安裝目錄下名稱叫 redis-sentinel 。 主要用來監控redis-server進程,進行master/slave管理,如果你的redis沒有運行在master/slave模式下,不需要設置sentinel。

三、Redis-sentinel啟動和檢測

  分別啟動 redis-server 和redis-sentinel。
  
  1)啟動 redis-0 時 redis-0 的 sentinel 控制台
  這裡寫圖片描述
  
  2)啟動 redis-1 時 reids-1 的 sentinel 控制台
  這裡寫圖片描述
  
  啟動 redis-1 時 reids-0 的 sentinel 控制台
  這裡寫圖片描述
  
  3)啟動 redis-2 時 reids-2 的 sentinel 控制台
  這裡寫圖片描述
  
  啟動 redis-2 時 reids-0 的 sentinel 控制台
  這裡寫圖片描述
  
  啟動 redis-2 時 reids-1 的 sentinel 控制台
  這裡寫圖片描述 <喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KCjxwPqGhoaHNqLn9yc+1xL/Y1sbK5LP20MXPor/J0tS/tLP2o6zU2tLAtM7G9Lavt/7O8cqxo6y21NPDv9jWxsyoyuSz9sHLK3NlbnRpbmVsoaIrc2xhdmWhoi1zZG93biC1yNDFz6KjrMu1w/e497j2IHNlbnRpbmVsINauvOS9+NDQwcvNqNG2o6y2+MfS0rK84L/Ytb3ByyByZWRpcy1zZXJ2ZXIgtcTH6b/2oaMrc2VudGluZWwgse3KvtPQ0MK1xCBzZW50aW5lbCDKtcD9vNPI67W9vOC/2KGjzOHKvqO6yte0zrm5vaggc2VudGluZWwgu7e+s8qxo6yx2NDrytfPyMb0tq8gbWFzdGVyILv6xvehoyAgPGJyPgqhoaGhIDxicj4KoaGhoTSjqbLpv7TP4LnY0MXPoiAgPGJyPgqhoaGhyrnTwyAjIG5ldHN0YXQgLW50bHAg" grep redis 命令可以看到當前 redis 運行情況。
  這裡寫圖片描述
  
  通過 redis-cli 查看 redis-server 的狀態

/usr/local/webserver/redis/redis-cli -h 127.0.0.1 -p 6379 -a abcd123457 info Replication

  (上面的 -a 用來輸入密碼)
  這裡寫圖片描述

說明:info 指令
  該指令將會打印完整的服務信息,包括集群,我們只需要關注”Replication”部分(在上面的命令中,我們在 info 後面加上了 Replication 的限制,如果不加,這還會輸出 Server、Clients、Memory、Persistence、Stats、CPU 和 Keyspace 等信息),這部分信息將會告訴我們”當前 server 的角色”以及指向它的所有的 slave 信息。可以通過在任何一個 slave 上,使用”INFO”指令獲得當前 slave 所指向的 master 信息。下面是 slave1 的 Replication 信息。
  這裡寫圖片描述 
  
  同時,該指令不僅可以幫助我們獲得集群的情況,當然 sentinel 組件也是使用”INFO”做同樣的事情。下面是 slave2 的 sentinel 信息。
  這裡寫圖片描述 
  
  通過上面信息,可以清楚看到 redis 服務狀態和主從關系。 
 
  5)failover 測試
  當上述部署環境穩定後,我們直接關閉 redis-0,在等待”down-after-milliseconds”秒之後(30 秒),redis-0/redis-1/redis-2 的 sentinel 窗口會立即打印”+sdown”、”+odown”、”+failover”、”+selected-slave”、 “+promoted-slave”、 “+slave-reconf”等等一系列指令, 這些指令標明當 master失效後,sentinel 組件進行 failover 的過程。
  模擬 mater 宕機的情況。此時各 sentinel 控制台輸出如下信息。
  
  redis-0 上的 sentinel 信息.
  這裡寫圖片描述 

  redis-1 上的 sentinel 信息
  這裡寫圖片描述
  
  redis-2 上的 sentinel 信息
  這裡寫圖片描述

  從上面三個窗口的信息可以看出, 當 master 宕機後, 三個 sentinel(哨兵)進行了對 master進行了故障轉移。

{從 redis-1 的 sentinel 控制台可以看出,進行了下面的操作。
a.+sdown mater mymaster 127.0.0.1 6379 (主觀認為 mater 失效);
b.+odown mater mymaster 127.0.0.1 6379 #quorum 2/2(已經有兩個哨兵認為 master 主觀失效,則認為 mater 客觀失效);
c.+new-epoch 1(准備進行新 mater 的選取);
d.+try-failover master mymaster 127.0.0.1 6379(嘗試熱備份切換,master 讓出位置);
e.+vote-for-leader 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票選舉 Leader);
f.127.0.0.1:16379 voted for 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票選舉Leader);
g.127.0.0.1:36379 voted for 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票選舉Leader);
h.+elected-leader master mymaster 127.0.0.1 6379(之前被選舉出來的 master);
i.+failover-state-select-slave master mymaster 127.0.0.1 6379(Leader 開始查找合適的slave);
j.+selected-slave slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379 (leader已經找到合適的 slave);
k.+failover-state-send-slaveof-noone slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(Leader 向 slave 發送“slaveof no one”指令,此時 slave 已經完成角色轉換,此 slave 即為 master);
l.+failover-state-wait-promotion slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(等待其他 sentinel 確認 slave);
m.+promoted-slave slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(確認成功);
n.+failover-state-reconf-slaves master mymaster 127.0.0.1 6379 (開始對slaves進行reconfig 操作);
o.+slave-reconf-sent slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379 (向指定的 slave 發送“slaveof”指令,告知此 slave 跟隨新的 master);
p. +slave-reconf-inprog slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379(此 slave 正在執行 slaveof + SYNC 過程,如過 slave 收到“+slave-reconf-sent”之後將會執行 slaveof 操作,循環 n);
q.+slave-reconf-done slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379(此 slave 同步完成,此後 leader 可以繼續下一個 slave 的 reconfig 操作);
r.+failover-end master mymaster 127.0.0.1 6379(故障轉移結束);
s.+switch-master mymaster 127.0.0.1 6379 127.0.0.1 63792(故障轉移成功後,各個sentinel 實例開始監控新的 master);
t.+slave slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 63792(下面幾步在給新的 master 加入 slave);
u.+slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 63792;
v.+sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 63792。

  當環境穩定後,我們發現,redis-2 被提升(“promoted”)為 master,且 redis-1 也通過”slave-reconf”過程之後跟隨了 redis-2。
如果此時 redis-0 服務器恢復正常, sentinel 會自動將 redis-0 作為 slave 加入到 redis-2 中。
  下面是 redis-0 的 sentinel 控制台輸出的信息。
  這裡寫圖片描述
  
  再次查看 redis-2(當前 master 的 info)
  這裡寫圖片描述

  提示:sentinel 實例需要全程處於啟動狀態,如果只啟動 server 而不啟動相應的 sentinel,仍然不能確保 server 能夠正確的被監控和管理。

四、Redis-sentinel原理分析

1)SDOWN 和 ODOWN 轉換過程
【名詞解釋】
  SDOWN:subjectively down,直接翻譯的為”主觀”失效,即當前 sentinel 實例認為某個redis 服務為”不可用”狀態。
  ODOWN:objectively down,直接翻譯為”客觀”失效,即多個 sentinel 實例都認為 master處於”SDOWN”狀態,那麼此時 master 將處於 ODOWN,ODOWN 可以簡單理解為 master已經被集群確定為”不可用”,將會開啟 failover。
  ( SDOWN 適合於 master 和 slave,但是 ODOWN 只會使用於 master;當 slave 失效超過”down-after-milliseconds”後,那麼所有 sentinel 實例都會將其標記為”SDOWN”。)

【轉換過程】
  a.每個 sentinel 實例在啟動後,都會和已知的 slaves/master 以及其他 sentinels 建立 TCP連接,並周期性發送 PING(默認為 1 秒);
  b.在交互中,如果 redis-server 無法在”down-after-milliseconds”時間內響應或者響應錯誤信息,都會被認為此 redis-server 處於 SDOWN 狀態;
  c.如果 b.中 SDOWN 的 server 為 master, 那麼此時 sentinel 實例將會向其他 sentinel 間歇性(一秒)發送”is-master-down-by-addr “指令並獲取響應信息, 如果足夠多的 sentinel 實例檢測到 master 處於 SDOWN,那麼此時當前 sentinel 實例標記 master 為 ODOWN…其他 sentinel實例做同樣的交互操作.配置項”sentinel monitor “,如果檢測到 master 處於 SDOWN 狀態的slave 個數達到,那麼此時此 sentinel 實例將會認為 master 處於 ODOWN;
  d.每個 sentinel 實例將會間歇性(10 秒)向 master 和 slaves 發送”INFO”指令,如果 master失效且沒有新 master 選出時,每 1 秒發送一次”INFO”;”INFO”的主要目的就是獲取並確認當前集群環境中 slaves 和 master 的存活情況;
  經過上述過程後,所有的 sentinel 對 master 失效達成一致後,開始 failover。

2) Sentinel 與 slaves”自動發現”機制
  在 sentinel 的配置文件中(local-sentinel.conf),都指定了 port,此 port 就是 sentinel 實例偵聽其他 sentinel 實例建立鏈接的端口.在集群穩定後,最終會每個 sentinel 實例之間都會建立一個 tcp 鏈接,此鏈接中發送”PING”以及類似於”is-master-down-by-addr”指令集,可用用來檢測其他 sentinel 實例的有效性以及”ODOWN”和”failover”過程中信息的交互。
  在 sentinel 之間建立連接之前,sentinel 將會盡力和配置文件中指定的 master 建立連接。sentinel 與 master 的連接中的通信主要是基於 pub/sub 來發布和接收信息,發布的信息內容包括當前 sentinel 實例的偵聽端口。

3)Leader 選舉
  其實在 sentinels 故障轉移中,仍然需要一個“Leader”來調度整個過程:master 的選舉以及 slave 的重配置和同步。當集群中有多個 sentinel 實例時,如何選舉其中一個 sentinel 為leader 呢?
  
  redis2.8.7的選舉有兩個條件,首先是要下面的條件過濾掉一些節點

使用如下條件篩選備選node:
1、slave節點狀態處於S_DOWN,O_DOWN,DISCONNECTED的除外
2、最近一次ping應答時間不超過5倍ping的間隔(假如ping的間隔為1秒,則最近一次應答延遲不應超過5秒,redis sentinel默認為1秒)
3、info_refresh應答不超過3倍info_refresh的間隔(原理同2,redis sentinel默認為10秒)
4、slave節點與master節點失去聯系的時間不能超過( (now - master->s_down_since_time) + (master->down_after_period * 10))。總體意思是說,slave節點與master同步太不及時的(比如新啟動的節點),不應該參與被選舉。
5、Slave priority不等於0(這個是在配置文件中指定,默認配置為100)。 從備選node中,按照如下順序選擇新的master
1、較低的slave_priority(這個是在配置文件中指定,默認配置為100)
2、較大的replication offset(每個slave在與master同步後offset自動增加)
3、較小的runid(每個redis實例,都會有一個runid,通常是一個40位的隨機字符串,在redis啟動時設置,重復概率非常小)
4、如果以上條件都不足以區別出唯一的節點,則會看哪個slave節點處理之前master發送的command多,就選誰。

我們期望有足夠多的sentinel實例, 這樣能夠確保當leader失效時, 能夠選舉某個sentinel為 leader,以便進行 failover。如果 leader 無法產生,比如較少的 sentinels 實例有效,那麼failover 過程將無法繼續。

4)failover 過程
  在 Leader 觸發 failover 之前,首先 wait 數秒(隨即 0~5),以便讓其他 sentinel 實例准備和調整,如果一切正常,那麼 leader 就需要開始將一個 salve 提升為 master,此 slave 必須為狀態良好(不能處於 SDOWN/ODOWN 狀態)且權重值最低(redis.conf 中)的, 當 master 身份被確認後,開始 failover。

五、Redis-sentinel學習總結

  1)redis 的水平擴展。 前文所實現的是 redis 的主從 HA 集群 (從服務器做備份而存在) ,試想當緩存到了一個級別一台服務器已經不能滿足了,就想到了 redis 的分布式,將緩存放到分配到多台服務器中。Redis 官方也提供了 redis cluster 來實現分布式,但目還沒有正式版發布(redis 3.0貌似提供了支持,還沒來得及研究)。Java 可以通過 jedis 的 ShardedJedis 來做分片 。
  2)redis 的監控。一個東西運行的是否正常、穩定和性能情況,這就涉及到了對它的監控。目前 redis 的監控工具有:redmon、redis-live 等。本文暫不做監控,讀者可參考其他資料學習使用。
  3)集群時的讀寫分離。主用來寫,從用來讀。在 redis 的 HA 集群中,主從服務器是變化的,這就導致在程序中,不容易獲得當前哪台服務是主,哪幾台服務是從。我們可以自己通過代碼實現獲得從服務器的 jedis 實例,具體可以參見Redis中sentinel集群的搭建和Jedis測試 圖文教程[二] 從而達到讀寫分離。
  4)“緩存數據同步”也是所有緩存工具的一個必須思考的問題。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved