Redis學習之主從複製(二)

主從複製

在Redis複製的基礎上(不包括由Redis Cluster或Redis Sentinel做爲附加層提供的高可用性功能),有一個很是簡單的使用和配置leader follower(主從)複製:它容許從屬Redis實例準確主實例的副本。每次連接斷開時,slave將自動從新鏈接到master,而且不管master發生什麼狀況,它都會嘗試成爲它的精確副本。java

該系統使用三種主要機制:redis

  1. 當主實例和從屬實例鏈接良好時,主設備經過向從設備發送命令流來保持從設備更新,以便複製對主設備端發生的數據集的影響,緣由是:客戶端寫入,key已過時或驅逐,更改主數據集的任何其餘操做。
  2. 當主設備和從設備之間的鏈路中斷時,對於網絡問題或者因爲主設備或從設備中檢測到超時,從設備從新鏈接並嘗試繼續部分從新同步:這意味着它將嘗試僅獲取部件它在斷開鏈接時錯過的命令流。
  3. 當沒法進行部分從新同步時,slave將要求徹底從新同步。這將涉及一個更復雜的過程,其中主機須要建立其全部數據的快照,將其發送到從機,而後在數據集更改時繼續發送命令流。

Redis默認使用異步複製,即低延遲和高性能,是絕大多數Redis用例的天然複製模式。可是,Redisslave異步確認它們與master按期收到的數據量。所以主設備不會每次等待從設備處理命令,可是若是須要,它知道哪一個從設備已經處理了什麼命令。這容許具備可選的同步複製。算法

客戶端可使用WAIT命令請求某些數據的同步複製。可是,WAIT只能確保在其餘Redis實例中存在指定數量的已確認副本,但它不會將一組Redis實例轉換爲具備強一致性的CP系統:在故障轉移期間,確認的寫入仍然可能丟失,具體取決於關於Redis持久性的確切配置。然而,對於WAIT,在失敗事件以後丟失寫入的機率大大下降到某些難以觸發的故障模式。數據庫

您能夠查看Sentinel或Redis集羣文檔,以獲取有關高可用性和故障轉移的更多信息。本文檔的其他部分主要描述了Redis基本複製的基本特徵。安全

如下是有關Redis複製的一些很是重要的事實:bash

  • Redis使用異步複製,異步slave到master確認處理的數據量。
  • 主設備能夠有多個從設備。
  • Slaves可以接受來自其餘Slaves的鏈接。除了將多個從設備鏈接到同一主設備以外,從設備還能夠以相似級聯的結構鏈接到其餘從設備。從Redis 4.0開始,全部子slave將從master接收徹底相同的複製流。
  • Redis複製在主端是非阻塞的。這意味着當一個或多個從服務器執行初始同步或部分從新同步時,主服務器將繼續處理查詢。
  • 複製在從屬端也很大程度上是非阻塞的。當slave正在執行初始同步時,它可使用舊版本的數據集處理查詢,假設您在redis.conf中配置了Redis。不然,您能夠將Redis從屬配置爲在複製流關閉時向客戶端返回錯誤。可是,在初始同步以後,必須刪除舊數據集而且必須加載新數據集。slave將在此簡短窗口期間阻止傳入鏈接(對於很是大的數據集,可能長達數秒)。從Redis 4.0開始,能夠配置Redis,以便刪除舊數據集在不一樣的線程中發生,可是加載新的初始數據集仍然會在主線程中發生並阻塞slave。
  • 複製能夠用於可伸縮性,以便爲只讀查詢提供多個slave(例如,能夠將慢速O(N)操做卸載到slave),或者僅用於提升數據安全性和高可用性。
  • 可使用複製來避免讓主服務器花費巨大的開支將完整數據集寫入磁盤:典型的技術是配置主服務器redis.conf以免持久存儲到磁盤,而後鏈接配置爲save from time to time的從服務器,或者啓用AOF。可是,必須當心處理此設置,由於從新啓動的主服務器將以空數據集開始:若是從服務器嘗試與其同步,則從服務器也將被清空。

工做原理

每一個Redis主服務器都有一個replication ID:它是一個大的僞隨機字符串,用於標記數據集的給定敘述。每一個主服務器還會爲生成的每一個複製流字節遞增一個偏移量,以便將其發送到從屬服務器,方便使用修改數據集的新更改來更新從屬服務器的狀態。即便沒有實際鏈接的slave,複製偏移也會增長,以下:服務器

Replication ID, offset
複製代碼

用來標識主數據集的確切版本。網絡

命令./redis-cli -p 6379 -a 你的密碼 info server | grep run能夠查看具體的id:併發

當slave鏈接到master時,它們使用PSYNC命令發送它們的舊主replication ID以及它們到目前爲止處理的偏移量。這樣master只用發送所需的增量部分。可是,若是主緩衝區中沒有足夠的backlog,或者從屬設備指不知道歷史記錄(複製ID),則發生徹底從新同步:在這種狀況下,從屬設備將得到數據集的完整副本, 從頭開始。less

這是徹底同步在更多細節中的工做方式:

主服務器啓動後臺保存過程以生成RDB文件。同時它開始緩衝從客戶端收到的全部新寫命令。後臺保存完成後,主服務器將數據庫文件傳輸到從服務器,從服務器將其保存在磁盤上,而後將其加載到內存中。而後,主設備將全部緩衝的命令發送到從設備。這是做爲命令流完成的,而且與Redis協議自己的格式相同。

您能夠經過telnet本身嘗試。在服務器執行某些工做時鏈接到Redis端口併發出SYNC命令。您將看到批量傳輸,而後主服務器接收的每一個命令都將在telnet會話中從新發出。實際上,較新的Redis實例再也不使用SYNC舊協議,但其仍然存在向後兼容性:它不容許部分從新同步,所以如今用PSYNC代替。

如前所述,當主 - 從鏈路因爲某種緣由而關閉時,從設備可以自動從新鏈接。若是主設備接收到多個併發從屬同步請求,它將執行單個後臺保存以便爲全部這些請求提供服務。

全量複製

開銷

1)bgsave時間。

2)RDB文件網絡傳輸時間。

3)從節點清空數據時間。

4)從節點加載RDB的時間。

5)可能的AOF重寫時間。

部分複製

配置

配置基本Redis複製很簡單:只需將如下行添加到從屬配置文件:

slaveof 192.168.1.1 6379
複製代碼

固然,您須要將192.168.1.1 6379替換爲您的主IP地址(或主機名)和端口。或者,您能夠調用SLAVEOF命令,主控主機將啓動與slave的同步。

還有一些參數用於調整主機在內存中採起的replication backlog以執行部分從新同步。

可使用repl-diskless-sync配置參數啓用無盤複製。傳輸開始後,等待在第一個slave以後到達的更多slaves的延遲由repl-diskless-sync-delay 參數控制。

具體步驟

1)進入redis目錄,複製redis.conf文件爲redis-6380.conf

cp redis.conf redis-6380.conf
複製代碼

2)修改redis-6380.conf的端口號,保存的rdb文件名,日誌名等參數。

3)找到REPLICATION模塊,修改以下:

replicaof 127.0.0.1 6379

4)若是主節點redis設置了密碼,修改masterauth屬性:

在箭頭處填上密碼。

5)啓動從結點:

./redis-server ../redis-6380.conf
複製代碼

6)使用命令./redis-cli -p 6380 -a 你的密碼 info replication查看從節點狀態:

能夠發現role爲slave,而且master_link_status爲up,說明啓動成功。說明一下,上圖的slave_repl_offset就是所謂的偏移量。

嘗試使用redis-cli在主節點中寫入一個值:

./redis-cli -p 6379 -a 你的密碼
> set hello world
複製代碼

進入從節點,輸入get hello,能夠發現已經可以正確獲取值。

7)可使用命令slaveof no one取消從節點模式。

只讀slave

從Redis 2.6開始,slave支持默認啓用的只讀模式。此行爲由slave-read-onlyredis.conf文件中的選項控制,能夠在運行時使用CONFIG SET啓用和禁用。

只讀slave將拒絕全部寫入命令,所以因爲錯誤而寫入slave是不可能的。這並不意味着該功能旨在將從屬實例暴露給互聯網,或者更廣泛地意味着將不受信任的客戶端存在的網絡,由於管理命令喜歡DEBUGCONFIG仍然啓用。可是,經過使用該rename-command指令禁用redis.conf中的命令,能夠提升只讀實例的安全性。

您可能想知道爲何能夠恢復只讀設置並具備能夠經過寫入操做做爲目標的從屬實例。若是slave和master從新同步或者slave從新啓動,那麼這些寫操做將被丟棄,但有一些合法的用例可用於在可寫slave中存儲短暫數據。

例如,計算慢速設置或排序集合操做並將它們存儲到本地key中是屢次觀察可寫slave的用例。

可是請注意,版本4.0以前的可寫slave沒法設置到期時間。這意味着若是您使用EXPIRE或爲key設置最大TTL的其餘命令,key將泄漏,雖然您在使用讀取命令訪問key時可能再也看不到它,您將在key計數中看到它仍在使用內存。所以,一般混合可寫slave(之前的版本4.0)和帶有TTL的鍵會產生問題。

Redis 4.0 RC3及更高版本徹底解決了這個問題,如今可寫的從設備可以像主設備那樣用TTL刪除key,但用DB編號大於63的key除外(但默認狀況下Redis實例只有16個數據庫)。

另請注意,因爲Redis 4.0從屬寫入僅是本地的,而且不會傳播到附加到實例的子從屬。相反,子slave將始終接收與頂層master向中間slave發送的複製流相同的複製流。例如,在如下設置中:

A ---> B ---> C
複製代碼

即便B是可寫的,C也不會看到B寫入,而是具備與主實例相同的數據集A

開發中運維的常見問題

讀寫分離

1)讀寫分離:讀流量分攤到從節點,寫流量分攤到主節點。

2)可能遇到的問題

一、複製數據延遲。

二、讀到過時數據(3.2已解決)。

三、從節點故障。

規避全量複製

1)第一次全量複製

一、第一次不可避免。

二、小主節點、低峯。

2)節點運行ID不匹配

一、主節點重啓(運行ID變化)。

二、故障轉移,例如哨兵或集羣。

3)複製積壓緩衝區不足

一、網絡中斷,部分複製沒法知足。

二、增大複製緩衝區配置rel_backlog_size,網絡「加強」。

規避複製風暴

1)單節點複製風暴

問題:主節點重啓,多從節點複製。

解決:更換複製拓撲。

2)單機器複製風暴

問題:機器宕機後,大量全量複製。

解決:主節點分散多機器。

Redis Sentinel

Redis Sentinel爲Redis提供高可用性。實際上,這意味着使用Sentinel能夠建立一個Redis部署,能夠在沒有人爲干預的狀況下抵禦某些類型的故障。

Redis Sentinel還提供其餘附屬任務,如監控,通知,並充當客戶端的配置提供程序。

這是宏觀級別的Sentinel功能的完整列表(即大圖):

  • 監控。Sentinel會不斷檢查主實例和從屬實例是否按預期工做。
  • 通知。Sentinel能夠經過API通知系統管理員,另外一臺計算機程序,其中一個受監控的Redis實例出現問題。
  • 自動故障轉移。若是主服務器未按預期工做,Sentinel能夠啓動故障轉移過程,其中從服務器被提高爲主服務器,其餘服務器將從新配置爲新主服務器,而且使用Redis服務器的應用程序會通知有關新服務器的地址。鏈接。
  • 配置提供商。Sentinel充當客戶端服務發現的權限來源:客戶端鏈接到Sentinels,以便詢問負責給定服務的當前Redis主服務器的地址。若是發生故障轉移,Sentinels將報告新地址。

Sentinel的分佈式特性

Redis Sentinel是一個分佈式系統:

Sentinel自己設計爲在多個Sentinel進程協同工做的配置中運行。讓多個Sentinel進程協做的優點以下:

  1. 當多個Sentinels認爲給定主設備再也不可用時,將執行故障檢測。這下降了誤報的可能性。
  2. 即便並不是全部Sentinel進程都正常工做,Sentinel也能正常工做,從而使系統可以抵禦故障。畢竟,擁有故障轉移系統自己就是一個單一的故障點並非一件好事。

Sentinels,Redis實例(主服務器和從服務器)以及鏈接到Sentinel和Redis的客戶端的總和也是具備特定屬性的更大的分佈式系統。在本文檔中,將逐步介紹概念,從瞭解Sentinel的基本屬性所需的基本信息,到更復雜的信息(可選),以瞭解Sentinel的工做原理。

得到哨兵

Sentinel的當前版本稱爲Sentinel 2。它是使用更強大和更簡單的預測算法(本文檔中解釋)重寫初始Sentinel實現。

自Redis 2.8發佈Redis Sentinel的穩定版本。

不穩定的分支中進行了新的開發,一旦它們被認爲是穩定的,新的特徵有時會被反導到最新的穩定分支中。

Redis 2.6附帶的Redis Sentinel版本1已棄用,不該使用。

運行Sentinel

若是您正在使用redis-sentinel可執行文件(或者若是您的可執行文件具備該名稱的符號連接redis-server),則可使用如下命令行運行Sentinel:

redis-sentinel /path/to/sentinel.conf
複製代碼

或者,您能夠直接使用redis-server在Sentinel模式下啓動它的可執行文件:

redis-server /path/to/sentinel.conf --sentinel
複製代碼

兩種方式都是同樣的。

可是**,在運行Sentinel時必須**使用配置文件,由於系統將使用此文件以保存從新啓動時將從新加載的當前狀態。若是沒有給出配置文件或配置文件路徑不可寫,Sentinel將拒絕啓動。

默認狀況下,Sentinels會偵聽與TCP端口26379的鏈接,所以要使 Sentinels正常工做,必須打開服務器的端口26379 以接收來自其餘Sentinel實例的IP地址的鏈接。不然,Sentinels沒法通話,也沒法就該怎麼作達成一致,所以永遠不會執行故障轉移。

在部署以前要了解Sentinel的基本知識

  1. 您須要至少三個Sentinel實例才能實現強大的部署。
  2. 應將三個Sentinel實例放入被認爲不能以獨立方式啓動的計算機或虛擬機中。例如,在不一樣的可用區域上執行的不一樣物理服務器或虛擬機。
  3. Sentinel + Redis分佈式系統不保證在故障期間保留已確認的寫入,由於Redis使用異步複製。可是,有一些方法能夠部署Sentinel,使窗口丟失限制在某些時刻的寫入,同時還有其餘不太安全的方式來部署它。
  4. 您須要在客戶端得到Sentinel支持。流行的客戶端庫具備Sentinel支持,但不是所有。
  5. 若是您不在開發環境中實時進行測試,則沒有HA設置是安全的,在生產環境中,若是它們能夠工做,則更好。您可能有一個錯誤的配置,只有在爲時已晚(凌晨3點,當您的master節點中止工做)時纔會變得明顯。
  6. Sentinel,Docker或其餘形式的網絡地址轉換或端口映射應謹慎使用:Docker執行端口從新映射,中斷其餘Sentinel進程的Sentinel自動發現以及主服務器的從屬列表。有關詳細信息,請查看本文檔後面有關Sentinel和Docker的部分。

配置Sentinel

Redis源代碼分發包含一個名爲sentinel.conf的文件 ,它是一個能夠用來配置Sentinel的自我記錄的示例配置文件,可是典型的最小配置文件以下所示:

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
複製代碼

您只須要指定要監視的主服務器,爲每一個單獨的主服務器(可能有任意數量的從服務器)提供不一樣的名稱。無需指定可被自動發現的slaves。Sentinel將自動更新配置有關slaves的其餘信息(以便在從新啓動時保留信息)。每次在故障轉移期間將slave升級爲master而且每次發現新的Sentinel時,也會重寫該配置。

上面的示例配置基本上監視兩組Redis實例,每組實例由主設備和未定義數量的從設備組成。一組實例被調用mymaster,另外一組被調用resque

sentinel monitor語句參數的含義以下:

sentinel monitor <master-group-name> <ip> <port> <quorum>
複製代碼

爲清楚起見,讓咱們逐行檢查配置選項的含義:

第一行用於告訴Redis監視一個名爲mymaster的主服務器,它位於地址127.0.0.1和端口6379,鏈接數爲2。一切都很明顯,可是quorum參數:

  • quorum是認爲master不可達的哨兵的數量,爲了真正把slave標誌爲失敗,並最終啓動關閉做業。
  • 可是**,quorum僅用於檢測故障**。爲了實際執行故障轉移,其中一個Sentinels須要被選爲故障轉移的領導者並被受權繼續進行。其由大多數Sentinel進程的投票而來。

所以,例如,若是您有5個Sentinel進程,而且給定主服務器的quorum設置爲值2,則會發生如下狀況:

  • 若是兩個Sentinels同時認定主服務器沒法訪問,則其中一個將嘗試啓動故障轉移。
  • 若是至少總共有三個Sentinel可達,則故障轉移將被受權並實際開始。

實際上,這意味着在故障期間,若是大多數Sentinel進程沒法通話(在少數分區中也沒有故障轉移),Sentinel永遠不會啓動故障轉移

其餘Sentinel選項

其餘選項幾乎老是如下列形式:

sentinel <option_name> <master_name> <option_value>
複製代碼

並用於如下目的:

  • down-after-milliseconds 是對於Sentinel開始認爲它已關閉而且實例不能到達的(不管是不回覆咱們的PING仍是回覆錯誤)以毫秒爲單位的時間。
  • parallel-syncs設置可在同一故障轉移後從新配置以使用新主服務器的從服務器數。數字越小,故障轉移過程完成所需的時間就越多,可是若是從屬服務器配置爲提供舊數據,則可能不但願全部從屬服務器同時與主服務器從新同步。雖然複製過程對於從屬設備大部分是非阻塞的,可是有一段時間它中止從主設備加載批量數據。您可能但願經過將此選項設置爲值1來確保一次只能訪問一個slave。

其餘選項在本文檔的其他部分中進行了描述,並記錄在sentinel.confRedis發行版附帶的示例文件中。

可使用該SENTINEL SET命令在運行時修改全部配置參數。有關詳細信息,請參閱「 **在運行時從新配置Sentinel」**部分。

示例Sentinel部署

如今您已瞭解Sentinel的基本信息,您可能想知道應該在哪裏放置Sentinel進程,須要多少Sentinel進程等等。本節介紹幾個示例部署。

  • Masters稱爲M1,M2,M3,...,Mn。
  • Slaves稱爲R1,R2,R3,...,Rn(R表明複製品)。
  • Sentinels稱爲S1,S2,S3,...,Sn。
  • Clients稱爲C1,C2,C3,...,Cn。
  • 當實例因爲Sentinel操做而更改角色時,咱們將其放在方括號內,所以[M1]表示因爲Sentinel干預而如今成爲主實例的實例。

請注意,咱們永遠不會顯示僅使用兩個Sentinels的設置,由於Sentinels老是須要與大多數人交談才能啓動故障轉移。

例1:只有兩個哨兵,不要這樣作

+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+

Configuration: quorum = 1
複製代碼
  • 在此設置中,若是主M1發生故障,R1將被提高,由於兩個Sentinels能夠就故障達成協議(顯然將quorum設置爲1),而且還能夠受權故障轉移,由於大多數是兩個。因此顯然它能夠表面上工做,但請檢查下一點,看看爲何這個設置被打破。
  • 若是M1運行的框中止工做,S1也中止工做。在另外一個框S2中運行的Sentinel將沒法受權故障轉移,所以系統將沒法使用。

請注意,爲了執行不一樣的故障轉移,須要多數,而後將最新配置傳播到全部Sentinels。另請注意,在沒有任何協議的狀況下,在上述設置的單個方面進行故障轉移的能力將很是危險:

+----+           +------+
| M1 |----//-----| [M1] |
| S1 |           | S2   |
+----+           +------+
複製代碼

在上面的配置中,咱們以徹底對稱的方式建立了兩個主服務器(假設S2能夠在未經受權的狀況下進行故障轉移)。客戶端能夠無限期地向雙方寫入,而且沒法理解分區什麼時候恢復正確的配置,以防止永久性的裂腦狀況

因此請始終在三個不一樣的盒子中至少部署三個Sentinels

示例2:具備三個框的基本設置

這是一個很是簡單的設置,其優勢是易於調整以得到額外的安全性。它基於三個框,每一個框都運行Redis進程和Sentinel進程。

+----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2
複製代碼

若是主M1發生故障,S2和S3將贊成故障,而且可以受權故障轉移,使客戶可以繼續。

在每一個Sentinel設置中,Redis被異步複製,老是存在丟失一些寫入的風險,由於給定的已確認寫入可能沒法到達被提高爲主設備的從設備。可是在上面的設置中,因爲客戶端使用舊主服務器進行分區,所以風險較高,以下圖所示:

+----+
         | M1 |
         | S1 | <- C1 (writes will be lost)
         +----+
            |
            /
            /
+------+    |    +----+
| [M2] |----+----| R3 |
| S2   |         | S3 |
+------+         +----+
複製代碼

在這種狀況下,網絡分區隔離了舊的主M1,所以從屬R2被提高爲主。可是,與舊主服務器位於同一分區的客戶端(如C1)可能會繼續將數據寫入舊主服務器。這個數據將永遠丟失,由於當分區將癒合時,主機將被從新配置爲新主機的從機,丟棄其數據集。

使用如下Redis複製功能能夠緩解此問題,若是主服務器檢測到再也不可以將其寫入傳輸到指定數量的從服務器,則容許中止接受寫入。

min-slaves-to-write 1
min-slaves-max-lag 10
複製代碼

使用上述配置(請參閱redis.confRedis發行版中的自注釋示例以獲取更多信息)Redis實例做爲主服務器時,若是沒法寫入至少1個從服務器,將中止接受寫入。因爲複製是異步的,所以沒法實際寫入意味着從屬設備已斷開鏈接,或者未向咱們發送超過指定max-lag秒數的異步確認。

使用此配置,上例中的舊Redis主M1將在10秒後變爲不可用。當分區恢復時,Sentinel配置將收斂到新的配置,客戶端C1將可以獲取有效配置並繼續使用新主設備。

可是沒有免費的午飯。經過這種改進,若是兩個從屬設備關閉,主設備將中止接受寫入。這是一個折衷。

具體步驟

1)將三個redis(一主二從)啓動。

2)配置sentinel.conf文件:

一、去掉protected-mode no的註釋,即讓它生效

二、將daemonize改爲yes

三、修改logfile爲26379.log

四、寫入redis密碼:sentinel auth-pass mymaster 你的密碼(注意這裏須要將其配置在sentinel monitor mymaster 你的服務器ip 6379 2語句之下,否則會報「No such master with specified name.」的錯誤。

五、修改dir

3)進入src目錄,使用命令./redis-sentinel ../sentinel.conf進行啓動。

4)使用命令:

./redis-cli -p 26379
>info
複製代碼

獲得結果以下:

5)複製sentinel.conf爲sentinel-26380.conf與sentinel-26381.conf,修改端口等信息,重複上述步驟。而且須要將myid註釋,最終,sentinels的數目將等於3。

Java客戶端

1)Sentinel地址集合。

2)masterName。

3)不是代理模式。

RedisUtils

package com.lamarsan.sentinel.util;

import redis.clients.jedis.*;
import redis.clients.jedis.exceptions.JedisConnectionException;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

/**
 * className: RedisUtil
 * description: TODO
 *
 * @author hasee
 * @version 1.0
 * @date 2018/12/26 10:57
 */
public class RedisUtil {
    private static final Logger myLogger = Logger.getLogger("com.lamarsan.sentinel.util");

    private static JedisSentinelPool pool = null;

    static {
        try {
            Set<String> sentinels = new HashSet<String>();
            sentinels.add("你的ip:26380");
            sentinels.add("你的ip.140:26379");
            sentinels.add("你的ip:26381");
            String masterName = "mymaster";
            String password = "123456";
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMinIdle(8);
            config.setMaxTotal(100);
            config.setMaxIdle(100);
            config.setMaxWaitMillis(10000);
            pool = new JedisSentinelPool(masterName, sentinels, config, password);
            try {
                pool.getResource();
            } catch (JedisConnectionException e) {
                myLogger.info(e.getMessage());
                e.printStackTrace();
            }
        } catch (Exception e) {
            myLogger.info(e.getMessage());
            e.printStackTrace();
        }
    }

    private static void returnResource(JedisSentinelPool pool, Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    /**
     * <p>經過key獲取儲存在redis中的value</p>
     * <p>並釋放鏈接</p>
     *
     * @param key
     * @return 成功返回value 失敗返回null
     */
    public static String get(String key) {
        Jedis jedis = null;
        String value = null;
        try {
            jedis = pool.getResource();
            value = jedis.get(key);
        } catch (Exception e) {
            if (jedis != null) {
                jedis.close();
            }
            e.printStackTrace();
        } finally {
            returnResource(pool, jedis);
        }
        return value;
    }

    /**
     * <p>向redis存入key和value,並釋放鏈接資源</p>
     * <p>若是key已經存在 則覆蓋</p>
     *
     * @param key
     * @param value
     * @return 成功 返回OK 失敗返回 0
     */
    public static String set(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.set(key, value);
        } catch (Exception e) {
            if (jedis != null) {
                jedis.close();
            }
            e.printStackTrace();
            return "0";
        } finally {
            returnResource(pool, jedis);
        }
    }
    
    .....
}

複製代碼

main

package com.lamarsan.sentinel;

import com.lamarsan.sentinel.util.RedisUtil;

/**
 * className: Test
 * description: TODO
 *
 * @author hasee
 * @version 1.0
 * @date 2019/9/13 15:54
 */
public class Test {
    public static void main(String[] args) throws InterruptedException {
        RedisUtil.setnx("hello", "world");
        while (true) {
            Thread.sleep(10000);
            String result = RedisUtil.get("hello");
            System.out.println(result);
        }
    }
}
複製代碼

結果

三個定時任務

1)每10秒每一個sentinel對master和slave執行info

一、發現slave結點。

二、確認主從關係。

2)每2秒每一個sentinel經過master結點的channel交換信息(pub/sub)

一、經過_sentinel_:hello頻道交互。

二、交互對節點的」見解「和自身信息。

3)每1秒每一個sentinel對其餘sentinel和redis執行ping。

節點運維

1)機器下線:例如過保等狀況。

2)機器性能不足:例如CPU、內存、硬盤、網絡等。

3)節點自身故障:例如服務不穩定等。

主節點

sentinel failover <masterName>

從節點

臨時下線仍是永久下線,例如是否作一些清理工做,也要考慮讀寫分離的狀況。

相關文章
相關標籤/搜索