jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
          http://www.tuicool.com/articles/mA7beiM


          最近在學(xué)習(xí) Redis 的高可用方案,就從 sentinel 開始。本篇文檔基本只是 redis sentinel 官方文檔 的摘要和總結(jié),感興趣的直接閱讀官方文檔是更好的選擇。

          基本原理

          Sentinel 的原理并不復(fù)雜:

          • 啟動(dòng) n 個(gè) sentinel 實(shí)例,這些 sentinel 實(shí)例會(huì)去監(jiān)控你指定的 redis master/slaves
          • 當(dāng) redis master 節(jié)點(diǎn)掛掉后, Sentinel 實(shí)例通過 ping 檢測(cè)失敗發(fā)現(xiàn)這種情況就認(rèn)為該節(jié)點(diǎn)進(jìn)入 SDOWN 狀態(tài),也就是檢測(cè)的 sentinel 實(shí)例主觀地(Subjectively)認(rèn)為該 redis master 節(jié)點(diǎn)掛掉。
          • 當(dāng)一定數(shù)目(Quorum 參數(shù)設(shè)定)的 Sentinel 實(shí)例都認(rèn)為該 master 掛掉的情況下,該節(jié)點(diǎn)將轉(zhuǎn)換進(jìn)入 ODOWN 狀態(tài),也就是客觀地(Objectively)掛掉的狀態(tài)。
          • 接下來 sentinel 實(shí)例之間發(fā)起選舉,選擇其中一個(gè) sentinel 實(shí)例發(fā)起 failover 過程:從 slave 中選擇一臺(tái)作為新的 master,讓其他 slave 從新的 master 復(fù)制數(shù)據(jù),并通過 Pub/Sub 發(fā)布事件。
          • 使用者客戶端從任意 Sentinel 實(shí)例獲取 redis 配置信息,并監(jiān)聽(可選) Sentinel 發(fā)出的事件: SDOWN, ODOWN 以及 failover 等,并做相應(yīng)主從切換,Sentinel 還扮演了服務(wù)發(fā)現(xiàn)的角色。
          • Sentinel 的 Leader 選舉采用的是 Raft 協(xié)議 。

          一張示意圖,正常情況下:

          當(dāng) M1 掛掉后:

          節(jié)點(diǎn) 2 被提升為 master,Sentinel 通知客戶端和 slaves 去使用新的 Master。

          搭建實(shí)驗(yàn)環(huán)境

          • 兩個(gè) redis,一個(gè)主一個(gè)從,分別監(jiān)聽在 6379 和 6380 端口
          $ redis-server $ redis-server --port 6380 
          • redis-cli -p 6380 連上 6380 端口的 redis,執(zhí)行 slaveof 127.0.0.1 6379將它設(shè)置為 6379 的 slave。
          • 啟動(dòng)三個(gè) sentinel 實(shí)例,分別監(jiān)聽在 5000 – 5002 端口,并且監(jiān)控 6379 的 redis master,首先是配置文件

          s1.conf:

          port 5000 sentinel monitor mymaster 127.0.0.1 6370 2 sentinel down-after-milliseconds mymaster 1000 sentinel failover-timeout mymaster 60000 

          其他兩個(gè)配置文件是 s2.conf 和 s3.conf 只是將 port 5000 修改為 5001 和 5002,就不再重復(fù)。 需要確保配置文件是可寫的,因?yàn)?Sentinel 會(huì)往配置文件里添加很多信息作為狀態(tài)持久化,這是為了重啟等情況下可以正確地恢復(fù) sentinel 的狀態(tài)。

          啟動(dòng):

          $ redis-sentinel s1.conf $ redis-sentinel s2.conf $ redis-sentinel s3.conf 

          配置說明:

          • port ,指定 sentinel 啟動(dòng)后監(jiān)聽的端口,sentinel 實(shí)例之間需要通過此端口通訊。
          • sentinel monitor [name] [ip] [port] [quorum] ,最重要的配置,指定要監(jiān)控的 redis master 的 IP 和端口,給這個(gè)監(jiān)控命名 name。Quorum 指定 至少 多少個(gè) sentinel 實(shí)例對(duì) redis master 掛掉的情況達(dá)成一致,只有達(dá)到這個(gè)數(shù)字后,Sentinel 才會(huì)去開始一次 failover 過程。
          • down-after-milliseconds,設(shè)定 Sentinel 發(fā)現(xiàn)一個(gè) redis 沒有響應(yīng) ping 到 Sentinel 認(rèn)為該 redis 實(shí)例不可訪問的時(shí)間。
          • failover-timeout,Sentinel 實(shí)例投票對(duì)于同一個(gè) master 發(fā)起 failover 過程的間隔時(shí)間,防止同時(shí)開始多次 failover。

          Sentinel 啟動(dòng)后會(huì)輸出類似的日志:

          17326:X 13 Oct 12:00:55.143 # +monitor master mymaster 127.0.0.1 6379 quorum 2 17326:X 13 Oct 12:00:55.143 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 

          表示開始監(jiān)控 mymaster 集群,并輸出集群的基本信息。

          以及 Sentinel 之間的感知日志,比如 s3 節(jié)點(diǎn)的輸出:

          18441:X 13 Oct 12:01:39.985 * +sentinel sentinel eab05ac9fc34d8af6d59155caa195e0df5e80d73 127.0.0.1 5000 @ mymaster 127.0.0.1 6379 18441:X 13 Oct 12:01:52.918 * +sentinel sentinel 4bf24767144aea7b4d44a7253621cdd64cea6634 127.0.0.1 5002 @ mymaster 127.0.0.1 6379 

          查看信息

          可以用 redis-cli 連上 sentinel 實(shí)例,查看信息:

          $ redis-cli -p 5000 127.0.0.1:5000> sentinel master mymaster  1) "name"  2) "mymaster"  3) "ip"  4) "127.0.0.1"  5) "port"  6) "6379"  7) "runid"  8) "4b97e168125b735e034d49c7b1f45925f43aded9"  9) "flags" 10) "master" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "729" 19) "last-ping-reply" 20) "729" 21) "down-after-milliseconds" 22) "1000" 23) "info-refresh" 24) "6258" 25) "role-reported" 26) "master" 27) "role-reported-time" 28) "11853370" 29) "config-epoch" 30) "0" 31) "num-slaves" 32) "1" 33) "num-other-sentinels" 34) "2" 35) "quorum" 36) "2" 37) "failover-timeout" 38) "60000" 39) "parallel-syncs" 40) "1" 

          sentinel master [name] 用于查看監(jiān)控的某個(gè) redis master 信息,包括配置和狀態(tài)等,其他命令還包括:

          • sentinel masters 查看所有監(jiān)控的 master 信息。
          • sentinel slaves [name] 查看監(jiān)控的某個(gè) redis 集群的所有 slave 節(jié)點(diǎn)信息。
          • sentinel sentinels [name] 查看所有 sentinel 實(shí)例信息。

          更重要的一個(gè)命令是根據(jù)名稱來查詢 redis 信息,客戶端會(huì)用到:

          127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster 1) "127.0.0.1" 2) "6379" 

          測(cè)試 Failover

          我們讓 6379 的 master 主動(dòng)休眠 30 秒來觀察 failover 過程:

          $ redis-cli -p 6379 DEBUG sleep 30 

          我們可以看到每個(gè) sentinel 進(jìn)程都監(jiān)控到 master 掛掉,從 sdown 狀態(tài)進(jìn)入 odown,然后選舉了一個(gè) leader 來進(jìn)行 failover,最終 6380 成為新的 master, sentinel 的日志輸出:

          18441:X 13 Oct 15:26:51.735 # +sdown master mymaster 127.0.0.1 6379 18441:X 13 Oct 15:26:51.899 # +new-epoch 1 18441:X 13 Oct 15:26:51.900 # +vote-for-leader eab05ac9fc34d8af6d59155caa195e0df5e80d73 1 18441:X 13 Oct 15:26:52.854 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2 18441:X 13 Oct 15:26:52.854 # Next failover delay: I will not start a failover before Thu Oct 13 15:28:52 2016 18441:X 13 Oct 15:26:53.034 # +config-update-from sentinel eab05ac9fc34d8af6d59155caa195e0df5e80d73 127.0.0.1 5000 @ mymaster 127.0.0.1 6379 18441:X 13 Oct 15:26:53.034 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380 18441:X 13 Oct 15:26:53.034 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380 18441:X 13 Oct 15:26:54.045 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380 18441:X 13 Oct 15:27:20.383 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380 

          日志的幾個(gè)主要事件:

          • +sdown master mymaster 127.0.0.1 6379 ,發(fā)現(xiàn) master 檢測(cè)失敗,主觀認(rèn)為該節(jié)點(diǎn)掛掉,進(jìn)入 sdown 狀態(tài)。
          • +odown master mymaster 127.0.0.1 6379 #quorum 3/2 ,有兩個(gè) sentinel 節(jié)點(diǎn)認(rèn)為 master 6379 掛掉,達(dá)到配置的 quorum 值 2,因此認(rèn)為 master 已經(jīng)客觀掛掉,進(jìn)入 odown 狀態(tài)。
          • +vote-for-leader eab05ac9fc34d8af6d59155caa195e0df5e80d73 準(zhǔn)備選舉一個(gè) sentinel leader 來開始 failover。
          • +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380 切換 master 節(jié)點(diǎn), failover 完成。
          • +config-update-from sentinel eab05ac9fc34d8af6d59155caa195e0df5e80d73 127.0.0.1 5000 @ mymaster 127.0.0.1 6379 更新 sentinel 配置。
          • 6379 休眠回來,作為 slave 掛載到 6380 后面,可見 sentinel 確實(shí)同時(shí)在監(jiān)控 slave 狀態(tài),并且掛掉的節(jié)點(diǎn)不會(huì)自動(dòng)移除,而是繼續(xù)監(jiān)控。

          此時(shí)查看 sentinel 配置文件,會(huì)發(fā)現(xiàn)增加了一些內(nèi)容:

          # Generated by CONFIG REWRITE dir "/Users/dennis/opensources/redis-sentinel" sentinel failover-timeout mymaster 60000 sentinel config-epoch mymaster 1 sentinel leader-epoch mymaster 1 sentinel known-slave mymaster 127.0.0.1 6379 sentinel known-sentinel mymaster 127.0.0.1 5001 8ba1e75cbf4c268be4a2950ee7389df746c6b0b4 sentinel known-sentinel mymaster 127.0.0.1 5002 4bf24767144aea7b4d44a7253621cdd64cea6634 sentinel current-epoch 1 

          可以看到 sentinel 將最新的集群狀態(tài)寫入了配置文件。

          運(yùn)維

          命令

          除了上面提到的一些查看信息的命令之外, sentinel 還支持下列命令來管理和檢測(cè) sentinel 配置:

          • SENTINEL reset <pattern> 強(qiáng)制重設(shè)所有監(jiān)控的 master 狀態(tài),清除已知的 slave 和 sentinel 實(shí)例信息,重新獲取并生成配置文件。
          • SENTINEL failover <master name> 強(qiáng)制發(fā)起一次某個(gè) master 的 failover,如果該 master 不可訪問的話。
          • SENTINEL ckquorum <master name> 檢測(cè) sentinel 配置是否合理, failover 的條件是否可能滿足,主要用來檢測(cè)你的 sentinel 配置是否正常。
          • SENTINEL flushconfig 強(qiáng)制 sentinel 重寫所有配置信息到配置文件。

          增加和移除監(jiān)控以及修改配置參數(shù):

          • SENTINEL MONITOR <name> <ip> <port> <quorum>
          • SENTINEL REMOVE <name>
          • SENTINEL SET <name> <option> <value>

          增加和移除 Sentinel

          增加新的 Sentinel 實(shí)例非常簡(jiǎn)單,修改好配置文件,啟動(dòng)即可,其他 Sentinel 會(huì)自動(dòng)發(fā)現(xiàn)該實(shí)例并加入集群。如果要批量啟動(dòng)一批 Sentinel 節(jié)點(diǎn),最好以 30 秒的間隔一個(gè)一個(gè)啟動(dòng)為好,這樣能確保整個(gè) Sentinel 集群的大多數(shù)能夠及時(shí)感知到新節(jié)點(diǎn),滿足當(dāng)時(shí)可能發(fā)生的選舉條件。

          移除一個(gè) sentinel 實(shí)例會(huì)相對(duì)麻煩一些,因?yàn)?sentinel 不會(huì)忘記已經(jīng)感知到的 sentinel 實(shí)例,所以最好按照下列步驟來處理:

          • 停止將要移除的 sentinel 進(jìn)程。
          • 給其余的 sentinel 進(jìn)程發(fā)送 SENTINEL RESET * 命令來重置狀態(tài),忘記將要移除的 sentinel,每個(gè)進(jìn)程之間間隔 30 秒。
          • 確保所有 sentinel 對(duì)于當(dāng)前存貨的 sentinel 數(shù)量達(dá)成一致,可以通過 SENTINEL MASTER [mastername] 命令來觀察,或者查看配置文件。

          客戶端實(shí)現(xiàn)

          客戶端從過去直接連接 redis ,變成:

          1. 先連接一個(gè) sentinel 實(shí)例
          2. 使用 SENTINEL get-master-addr-by-name master-name 獲取 redis 地址信息。
          3. 連接返回的 redis 地址信息,通過 ROLE 命令查詢是否是 master。如果是,連接進(jìn)入正常的服務(wù)環(huán)節(jié)。否則應(yīng)該斷開重新查詢。
          4. (可選)客戶端可以通過 SENTINEL sentinels [name] 來更新自己的 sentinel 實(shí)例列表。

          當(dāng) Sentinel 發(fā)起 failover 后,切換了新的 master,sentinel 會(huì)發(fā)送 CLIENT KILL TYPE normal 命令給客戶端,客戶端需要主動(dòng)斷開對(duì)老的master 的鏈接,然后重新查詢新的 master 地址,再重復(fù)走上面的流程。這樣的方式仍然相對(duì)不夠?qū)崟r(shí),可以通過 sentinel 提供的 Pub/Sub 來更快地監(jiān)聽到 failover 事件,加快重連。

          如果需要實(shí)現(xiàn)讀寫分離,讀走 slave,那可以走 SENTINEL slaves [name] 來查詢 slave 列表并連接。

          生產(chǎn)環(huán)境推薦

          對(duì)于一個(gè)最小集群,Redis 應(yīng)該是一個(gè) master 帶上兩個(gè) slave,并且開啟下列選項(xiàng):

          min-slaves-to-write 1 min-slaves-max-lag 10 

          這樣能保證寫入 master 的同時(shí)至少寫入一個(gè) slave,如果出現(xiàn)網(wǎng)絡(luò)分區(qū)阻隔并發(fā)生 failover 的時(shí)候,可以保證寫入的數(shù)據(jù)最終一致而不是丟失,寫入老的 master 會(huì)直接失敗,參考 Consistency under partitions 。

          Slave 可以適當(dāng)設(shè)置優(yōu)先級(jí),除了 0 之外(0 表示永遠(yuǎn)不提升為 master),越小的優(yōu)先級(jí),越有可能被提示為 master。如果 slave 分布在多個(gè)機(jī)房,可以考慮將和 master 同一個(gè)機(jī)房的 slave 的優(yōu)先級(jí)設(shè)置的更低以提升他被選為新的 master 的可能性。

          考慮到可用性和選舉的需要,Sentinel 進(jìn)程至少為 3 個(gè),推薦為 5 個(gè),如果有網(wǎng)絡(luò)分區(qū),應(yīng)當(dāng)適當(dāng)分布(比如 2 個(gè)在 A 機(jī)房, 2 個(gè)在 B 機(jī)房,一個(gè)在 C 機(jī)房)等。

          其他

          由于 Redis 是異步復(fù)制,所以 sentinel 其實(shí)無法達(dá)到強(qiáng)一致性,它承諾的是最終一致性:最后一次 failover 的 redis master 贏者通吃,其他slave 的數(shù)據(jù)將被丟棄,重新從新的 master 復(fù)制數(shù)據(jù)。此外還有前面提到的分區(qū)帶來的一致性問題。

          其次,Sentinel 的選舉算法依賴時(shí)間,因此要確保所有機(jī)器的時(shí)間同步,如果發(fā)現(xiàn)時(shí)間不一致,Sentinel 實(shí)現(xiàn)了一個(gè) TITL 模式來保護(hù)系統(tǒng)的可用性。

          posted on 2016-12-14 18:25 jinfeng_wang 閱讀(182) 評(píng)論(0)  編輯  收藏 所屬分類: 2016-REDIS
          主站蜘蛛池模板: 常德市| 卢龙县| 辛集市| 句容市| 会东县| 胶南市| 古浪县| 肥西县| 莫力| 诸暨市| 湖北省| 永胜县| 新绛县| 壶关县| 铁力市| 肇东市| 兰考县| 东阳市| 二连浩特市| 梁山县| 江山市| 同德县| 六枝特区| 桐柏县| 闽侯县| 宜川县| 十堰市| 玛纳斯县| 贡觉县| 新巴尔虎右旗| 布尔津县| 当阳市| 秦安县| 绥棱县| 鹤山市| 屏东市| 维西| 兰溪市| 吉林市| 怀仁县| 榆社县|