redis 優化系列(四)哨兵機制
一、Redis主從復制的問題:
Redis 復制有一個缺點,當主機 Master 宕機以后,我們需要人工操作來解決切換,比如使用 slaveof no one 。實際上主從復制并沒有實現,高可用, 高可用側重備份機器, 利用集群中系統的冗余,當系統中某臺機器發生損壞的時候,其他后備的機器可以迅速的接替它來啟動服務。
如下圖所示:
一旦主節點宕機,寫服務無法使用,就需要手動去切換,重新選取主節點,手動設置主從關系。
那么如何解決呢?如果我們有一個監控程序能夠監控各個機器的狀態及時作出調整,將手動的操作變成自動的。redis的Sentinel(哨兵)的出現就是為了解決這個問題。
二、哨兵機制的原理及實現
Redis Sentinel(哨兵) 是一個分布式集群架構,其中包含若干個 Sentinel 節點和 Redis 數據節點,每個 Sentinel 節點會對數據節點和其余 Sentinel 節點進行監控,當它發現節點不可達時,會對節點做下線標識。如果被標識的是主節點,它還會和其他 Sentinel 節點進行“協商”,當大多數 Sentinel 節點都認為主節點不可達時,它們會選舉出一個 Sentinel 節點來完成自動故障轉移的工作,同時會將這個變化實時通知給 Redis 應用方。整個過程完全是自動的,不需要人工來介入,所以這套方案很有效地解決了 Redis 的高可用問題。
注:哨兵(Sentinel) 其實也是一個redis只不過它不是用來存儲數據的,而哨兵不止一臺,會有多臺(最好或者必須 部署多臺哨兵)。哨兵是一個獨立進程,作為進程,它會獨立運行。
一句話解釋:哨兵是用來監控redis master主節點的狀態的工具,并做出相應反映。比如說 當前redis的主節點掛掉了,哨兵會自動從redis 從節點中選舉出一臺繼續作為主節點,來繼續提供redis主從集群服務。
如下圖所示:
注意:由上圖可知,client客戶端并不是直接連接的redis主機,而是連接的哨兵(哨兵是一個集群,有多臺哨兵),然后哨兵監控主節點的redis狀態(不是實時監控,而是定時監控),然后哨兵會返回主機的相關服務信息
**
**
2.1 基本的故障轉移流程:
1)主節點出現故障,此時兩個從節點與主節點失去連接,主從復制失敗。
2)每個 Sentinel 節點通過定期監控發現主節點出現了故障
3)多個 Sentinel 節點對主節點的故障達成一致會選舉出其中一個節點作為領導者負責故障轉移。
4)Sentinel 領導者節點執行了故障轉移,整個過程基本是跟我們手動調整一致的,只不過是自動化完成的。
5)故障轉移后整個 Redis Sentinel 的結構,重新選舉了新的redis master 主節點。
**
**
2.2 Redis Sentinel 具有以下幾個功能:
①、監控:Sentinel 節點會定期檢測 Redis 數據節點、其余 Sentinel 節點是否可達。(一個哨兵可以監控多套主從結構,主節點)**
**
②、通知:Sentinel 節點會將故障轉移的結果通知給應用方。
③、主節點故障轉移:實現從節點晉升為主節點并維護后續正確的主從關系。
④、配置提供者:在 Redis Sentinel 結構中,客戶端在初始化的時候連接的是 Sentinel 節點集合,從中獲取主節點信息。
同時Redis Sentinel 包含了若個 Sentinel 節點(一般起步至少是3臺),這樣做也帶來了兩個好處:
①、對于節點的故障判斷是由多個 Sentinel 節點共同完成,這樣可以有效地防止誤判。
②、Sentinel 節點集合是由若干個 Sentinel 節點組成的,這樣即使個別 Sentinel 節點不可用,整個 Sentinel 節點集合依然是健壯的。
但是 Sentinel 節點本身就是獨立的 Redis 節點,只不過它們有一些特殊,它們不存儲數據,只支持部分命令。
三、案例:配置哨兵
環境:
1臺master主節點 redis-master(ip:172.10.0.2)
2臺slave從節點 redis-slave(ip:172.10.0.3)、redis-slave2(ip:172.10.0.4)
3臺哨兵服務節點 redis-sentinel1(ip:172.10.0.9)、redis-sentinel2(ip:172.10.0.10)、redis-sentinel3(ip:172.10.0.11)
架構環境列表如下:
容器名稱 容器IP地址 映射端口號 服務運行模式
redis-sentinel1 172.10.0.9 22530->26379 sentinel
redis-sentinel2 172.10.0.10 22531->26379 sentinel
redis-sentinel3 172.10.0.11 22532->26379 sentinel
redis-master 172.10.0.2 6380->6379 Master
redis-slave 172.10.0.3 6381->6379 Slave
redis-slave2 172.10.0.4 6382->6379 Slave
3.1 由于前面幾篇博文我們已經創建了一主一從,所以這里在創建一臺redis從節點,變成1主2從的架構
#創建一臺redis從節點``docker run -itd --name redis-slave2 --net mynetwork -p 6382:6379 --ip 172.10.0.4 redis` `#進入該容器并修改redis配置文件,指定主節點配置``docker ``exec` `-it redis-slave2 ``bash` `#修改配置文件(這里就不演示了。。可看該系列博文的第一篇)
3.2 創建三臺哨兵服務節點,并分別進入三臺哨兵服務節點容器里面
#創建三臺哨兵服務節點``docker run -itd --name redis-sentinel1 --net mynetwork -p 22530:26379 --ip 172.10.0.9 redis``docker run -itd --name redis-sentinel2 --net mynetwork -p 22531:26379 --ip 172.10.0.10 redis``docker run -itd --name redis-sentinel3 --net mynetwork -p 22532:26379 --ip 172.10.0.11 redis` `#分別進入三臺哨兵服務節點容器里面``docker ``exec` `-it redis-sentinel1 ``bash``docker ``exec` `-it redis-sentinel2 ``bash``docker ``exec` `-it redis-sentinel3 ``bash
3.3 分別修改三臺哨兵配置文件(redis-sentinel.conf)
vi` `/etc/redis-sentinel``.conf` `#1、為了省事方便。。我們做如下這2項修改。。``將 ``# bind 127.0.0.1 192.168.1.1 修改為 bind 0.0.0.0``將 ``# protected-mode no 修改為 protected-mode no 也就是取消前面的#號` `#2、修改哨兵服務要監控的主節點redis的ip地址``將 sentinel monitor mymaster 127.0.0.1 6379 2 修改為 sentinel monitor mymaster 172.10.0.2 6379 2` `#3、保存修改后的文件``#4、redis-sentinel2和redis-sentinel3容器里面的哨兵配置文件redis-sentinel.conf的修改也是這樣修改。。
3.4 分別進入三臺哨兵服務節點容器里面啟動三臺哨兵服務
#redis-sentinel1容器里面執行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &` `#redis-sentinel2容器里面執行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &` `#redis-sentinel3容器里面執行以下命令``redis-sentinel ``/etc/redis-sentinel``.conf &
3.5 為了驗證是否配置成功,可以查看哨兵日志(查看任意一臺哨兵里面的日志即可,因為3臺哨兵服務節點配置都是一模一樣的)
vi` `/var/log/redis/sentinel``.log
3.6 進入redis主節點這臺服務容器里面,并kill掉這臺服務的進程,使之掛掉。讓哨兵服務自動從N臺從redis服務節點中選取其中一臺從服務節點成為新的主(master)節點
①、進入主節點服務容器里面
docker ``exec` `-it redis-master ``bash
②、查看redis端口占用詳情
netstat` `-apn |``grep` `6379
③、kill掉該進程,然后再次查看端口占用情況,如果結果中沒有相關端口對應的相關進程則kill成功,具體看以下截圖
kill` `31` `netstat` `-apn |``grep` `6379
至此。。我們就把主節點的redis給kill掉了,然后稍等幾秒鐘(或幾十秒鐘,具體看配置文件中的配置),查看一下哨兵在這幾臺從redis節點中選取了那一臺從節點使之變成了主節點
3.7 再次查看哨兵日志,看一下哨兵選取了那臺從節點變成了主節點
vi` `/var/log/redis/sentinel``.log
從以上圖片中可以看到哨兵選舉了172.10.0.3這臺ip地址的從節點作為redis主從架構中的主節點,也就是使這臺沒有掛掉的從節點從slave晉升成為了master。ps:172.10.0.3這臺ip地址對應的容器名字:redis-slave
3.8 進入redis-slave這臺服務容器查看redis相關服務信息驗證一下是否已成為主節點
ok。。從以上截圖中可以看到該節點確實已經成為了主節點,并且 offset 偏移量也不是從0開始的。。也就是意味著主從復制數據并不是從頭開始的。。至此哨兵搭建使用成功。。
四、Sentinel 的核心配置
①、sentinel monitor mymaster 127.0.0.1 7000 2
監控的主節點的名字、IP 和端口,最后一個2的意思是有幾臺 Sentinel 發現有問題,就會發生故障轉移,例如 配置為2,代表至少有2臺 Sentinel 節點認為主節點不可達,那么這個不可達的判定才是客觀的。對于設置的越小,那么達到下線的條件越寬松,反之越嚴格。一般建議將其設置為 Sentinel 節點的一半加1
②、sentinel down-after-millseconds mymaster 30000
這個是超時的時間(單位:毫秒)。打個比方,當你去 ping 一個機器的時候,多長時間后仍 ping 不通,那么就認為它是有問題的
③、sentinel parallel-syncs mymaster 1
當 Sentinel 節點集合對主節點故障判定達成一致時,Sentinel 領導者節點會做故障轉移操作,選出新的主節點,原來的從節點會向新的主節點發起復制操作,parallel-syncs 就是用來限制在一次故障轉移之后,每次向新的主節點發起復制操作的從節點個數,指出 Sentinel 屬于并發還是串行。1代表每次只能復制一個,可以減輕 Master 的壓力
④、sentinel auth-pass
如果 Sentinel 監控的主節點配置了密碼,sentinel auth-pass 配置通過添加主節點的密碼,防止 Sentinel 節點對主節點無法監控
⑤、sentinel failover-timeout mymaster 180000
表示故障轉移的時間
五、Sentinel常用命令
sentinel支持的合法命令如下:
①、sentinel masters 顯示被監控的所有master以及它們的狀態
②、sentinel master
③、sentinel slaves
④、sentinel get-master-addr-by-name
⑤、sentinel failover
⑥、sentinel failover-timeout mymaster 10000 這個參數設置集群 從 判斷節點掛掉,到執行failover操作(即重新選舉master節點)的時間
⑦、sentinel remove
六、應用端調用
Master可能會因為某些情況宕機了,如果在客戶端是固定一個地址去訪問,肯定是不合理的,所以客戶端請求是請求哨兵,從哨兵獲取主機地址的信息,或者是從機的信息。可以簡單實現一個例子
1、隨機選擇一個哨兵連接,獲取主機、從機信息
2、模擬客戶端定時訪問,實現簡單輪訓效果,輪詢從節點
3、連接失敗重試訪問
代碼簡單模擬實現(php代碼舉例)
class` `Round``{`` ``static` `$lastIndex` `= 0;` ` ``public` `function` `select(``$list``)`` ``{`` ``$currentIndex` `= self::``$lastIndex``; ``//當前的index`` ``$value` `= ``$list``[``$currentIndex``];`` ` ` ``if``(``$currentIndex` `+ 1 > ``count``(``$list``) - 1)`` ``{`` ``self::``$lastIndex` `= 0;`` ``}`` ``else`` ``{`` ``self::``$lastIndex``++;`` ``}`` ` ` ``return` `$value``;`` ``}``}` `/********華麗的分割線*********/` `$sentinelConf` `= [`` ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22530],`` ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22531],`` ``[``'ip'``=>``'47.98.147.49'``,``'port'``=>22532]``];` `//隨機訪問``$sentinelInfo` `= ``$sentinelConf``[``array_rand``(``$sentinelConf``)];` `$redis` `= ``new` `Redis();``$redis``->connect(``$sentinelInfo``[``'ip'``], ``$sentinelInfo``[``'port'``]);``$slavesInfo` `= ``$redis``->rawCommand(``'SENTINEL'``, ``'slaves'``, ``'mymaster'``);` `$slaves` `= [];` `foreach` `(``$slavesInfo` `as` `$val``)``{`` ``$slaves``[] = [``'ip'``=>``$val``[3], ``'port'``=>``$val``[5]];``}` `//加載到緩存當中,可以記錄這次訪問的時間跟上次的訪問時間` `//模擬客戶端訪問(這里用了swoole的定時操作)``swoole_timer_tick(600,``function` `() ``use``(``$slaves``) {`` ` ` ``//輪詢`` ``$slave``=(``new` `Round``())->select(``$slaves``);`` ``try`` ``{`` ``$redis` `= ``new` `Redis();`` ``$redis``->connect(``$slave``[``'ip'``], ``$slave``[``'port'``]);`` ``var_dump(``$slave``, ``$redis``->get(``'wzyl'``));`` ``}`` ``catch` `(\RedisException ``$e``)`` ``{` ` ``}` `});` `//阻塞在這里
總結redis主從、哨兵、集群的概念:
【redis主從】:
是備份關系, 我們操作主庫,數據也會同步到從庫。 如果主庫機器壞了,從庫可以上。就好比你 D盤的片丟了,但是你移動硬盤里邊備份有。
【redis哨兵】:
哨兵保證的是HA(高可用),保證特殊情況故障自動切換,哨兵盯著你的“redis主從集群”,如果主庫死了,它會告訴你新的老大是誰。
哨兵:主要針對redis主從中的某一個單節點故障后,無法自動恢復的解決方案。(哨兵 保證redis主從的高可用)
【redis集群】:
集群保證的是高并發,因為多了一些兄弟幫忙一起扛。同時集群會導致數據的分散,整個redis集群會分成一堆數據槽,即不同的key會放到不不同的槽中。
集群主要針對單節點容量、高并發問題、線性可擴展性的解決方案。
集群:是為了解決redis主從復制中 單機內存上限和并發問題,假如你現在的服務器內存為256GB,當達到這個內存時redis就沒辦法再提供服務,同時數據量能達到這個地步寫數據量也會很大,容易造成緩沖區溢出,造成從節點無限的進行全量復制導致主從無法正常工作。
Redis 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。