天天看點

【Redis】主從複制(哨兵)

文章目錄

    • 一、簡介
    • 二、搭建redis叢集
      • 1、實作僞叢集
      • 2、複制三個redis.config檔案
      • 3、配置redis63xx.config檔案
    • 三、主從複制的複制原理
      • 1、開啟三個redis服務
      • 2、指令實作主從複制(臨時)
        • ① 設定6380和6381為6379的slave節點
        • ② 增量複制 測試
        • ③ 全量複制 測試
        • ④ slave寫操作 測試
      • 3、配置檔案實作主從複制(永久)
      • 4、複制原理
      • 5、全量同步與增量同步
    • 四、當機後的手動配置主機
      • 1、簡介
      • 2、搭建鍊式叢集
      • 3、測試主從複制
      • 4、master當機後手動配置master節點
    • 五、哨兵模式
      • 1、簡介
      • 2、搭建單哨兵模式
        • 第一步:建立 sentinel.conf檔案
        • 第二步:啟動redis叢集,配置号主從複制
        • 第三部:啟動哨兵
        • 第四步:關閉6379redis服務
        • 第五步:重新開機6379redis服務
        • 總結
      • 3、完整的sentinel.conf檔案
      • 4、搭建哨兵叢集
        • 第一步:編寫sentinel.conf配置檔案
        • 第二步:啟動三個redis-server服務
        • 第三步:啟動三個redis-sentinel服務
        • 第四步:檢視redis程序情況
        • 第五步:模仿master當機的情況
      • 5、sentinel(哨兵)監控的工作原理

一、簡介

和Mysql主從複制的原因一樣,Redis雖然讀取寫入的速度都特别快,但是也會産生讀壓力特别大的情況。為了分擔讀壓力,Redis支援主從複制,Redis的主從結構可以采用一主多從或者級聯結構,Redis主從複制可以根據是否是全量分為全量同步和增量同步。

【Redis】主從複制(哨兵)

我們可以認為redis的主從複制是對master主機資料的一種備份。因為在實際的生産生活中難免會出現當機的情況,面對這種情況,如果我們沒有使用主從複制,那麼将會導緻長時間内資料我們取出(redis當機)。

在redis的主從複制中,master主機是可以進行讀寫操作(以寫為主)的,slave主機隻能進行讀操作(以讀為主)。這是因為我們需要實作讀寫分離(在大并發的情況下提高性能)

二、搭建redis叢集

正常情況下,我們在搭建叢集的時候,是使用的不同的伺服器,但是在這裡我偷個懶,我在一個伺服器上通過不同的端口号啟動redis實作僞叢集。

1、實作僞叢集

我們測試的時候使用的是"一主兒從"的模式,我們需要建立一個master節點和兩個slave節點。

為例實作上述的僞叢集,我們需要複制三個redis.config啟動檔案,因為redis是依賴于redis.config的啟動檔案啟動的,隻要我們配置好redis.config中關于端口号的相關配置,就可以實作僞叢集。

2、複制三個redis.config檔案

[[email protected] ~]# cd /usr/local/bin/myconfig/
[[email protected] myconfig]# ls
redis6379.conf  redis6380.conf  redis6381.conf  redis.conf
[[email protected] myconfig]#
           

3、配置redis63xx.config檔案

在這裡我們就以redis6379.config為例,其他的檔案操作一樣。

配置端口

【Redis】主從複制(哨兵)

配置pid名稱

【Redis】主從複制(哨兵)

配置log檔案名

【Redis】主從複制(哨兵)

配置dump.rdb檔案名

【Redis】主從複制(哨兵)

三、主從複制的複制原理

1、開啟三個redis服務

通過上述的三個配置檔案打開三個redis服務,預設情況下,每一台伺服器都是主節點(我們可以通過

info replication

指令進行檢視)

【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)

2、指令實作主從複制(臨時)

我們可以使用指令的形式設定slave節點,但是這種方式的臨時的,當redis重新開機之後,重新開機的redis又都是master角色了。

① 設定6380和6381為6379的slave節點

slaveof address port

該指令的作用是設定目前節點是哪個節點的slave,address表示master的位址,port表示master的端口号。

【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)

② 增量複制 測試

//在master節點中寫入東西
127.0.0.1:6379> set name tiger
OK
127.0.0.1:6379> set age 18
OK


//在slave01中可以讀到
127.0.0.1:6380> get age
"18"
127.0.0.1:6380> get name
"tiger"


//在slave02中也可以讀到
127.0.0.1:6381> get age
"18"
127.0.0.1:6381> get name
"tiger"
           

③ 全量複制 測試

我們先讓一個slave斷開與master的連接配接

127.0.0.1:6381> SHUTDOWN
not connected> exit
[[email protected] bin]#
           

重新開機slave,測試是否能擷取name

可以擷取到name,說明salve已經将資料持久化了。

[[email protected] bin]# redis-server myconfig/redis6381.conf
[[email protected] bin]# redis-cli -p 6381
127.0.0.1:6381>  get name		//是可以擷取到master中之前寫入的name的
"tiger"
           

在master中寫入gender,測試是否可以擷取gender

127.0.0.1:6379> set gender man
OK
127.0.0.1:6379>
           

擷取不到gender,因為此時6381不是master的slave。

127.0.0.1:6381> get gender
(nil)
           

從新連接配接slave與master,測試是否可以擷取gender

重新連接配接後,我們是可以擷取到在連接配接之前master寫入的全部内容,說明連接配接之後,slave會同步master的所有的資料。

127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> get gender
"man"
127.0.0.1:6381>
[[email protected] bin]#

           

④ slave寫操作 測試

我們嘗試在slave中進行寫操作,發現slave隻是一個隻讀的替換,是以沒有寫的權限。

//slave01中不能進行寫操作
127.0.0.1:6380> set gender man
(error) READONLY You can‘t write against a read only replica.

//slave0中也不能進行寫操作
127.0.0.1:6381> set gender man
(error) READONLY You can't write against a read only replica.
           

3、配置檔案實作主從複制(永久)

我們打開一個redisxxx.config檔案,找到如下的位置,然後設定master的主機IP和端口号(有密碼的設定上密碼)就可以實作永久化的主從複制配置。

replicaof < masterip> < masterport>

   < masterip>:表示要跟随的master的IP

   < masterport>:表示要跟随的master的端口号

masterauth < master-password>

   < master-password>:表示要跟随的master的密碼(沒有就不用設定)

456 ################################# REPLICATION #################################
 457
 458 # Master-Replica replication. Use replicaof to make a Redis instance a copy of
 459 # another Redis server. A few things to understand ASAP about Redis replication.
 460 #
 461 #   +------------------+      +---------------+
 462 #   |      Master      | ---> |    Replica    |
 463 #   | (receive writes) |      |  (exact copy) |
 464 #   +------------------+      +---------------+
 465 #
 466 # 1) Redis replication is asynchronous, but you can configure a master to
 467 #    stop accepting writes if it appears to be not connected with at least
 468 #    a given number of replicas.
 469 # 2) Redis replicas are able to perform a partial resynchronization with the
 470 #    master if the replication link is lost for a relatively small amount of
 471 #    time. You may want to configure the replication backlog size (see the next
 472 #    sections of this file) with a sensible value depending on your needs.
 473 # 3) Replication is automatic and does not need user intervention. After a
 474 #    network partition replicas automatically try to reconnect to masters
 475 #    and resynchronize with them.
 
 //這個地方就是配置該redis将是誰的slave
 477 # replicaof <masterip> <masterport>   

 479 # If the master is password protected (using the "requirepass" configuration
 480 # directive below) it is possible to tell the replica to authenticate before
 481 # starting the replication synchronization process, otherwise the master will
 482 # refuse the replica request.

 //如果要跟随的master有密碼,那麼可以在這裡設定
 484 # masterauth <master-password>		
           

個人認為這樣方式用的也不多,因為這樣方式會導緻哨兵模式的失靈。

4、複制原理

salve啟動連接配接到master後,會發一個sync(同步)指令。master接受到slave的同步指令後,啟動背景存盤程序,同時收集所有接收到的用于修改資料的指令,在背景程序執行完畢後,master将傳送整個資料檔案到slave,完成一次完全(全量)同步。

【Redis】主從複制(哨兵)

5、全量同步與增量同步

隻要slave重新連接配接master,那麼就會完成一次完全(全量)同步,在slave連接配接master期間的同步是增量同步。

全量複制:全量複制用于salve啟動第一次連接配接master主機時,同步master的全部資料。

增量複制:用于slave連接配接master後,持續同步master的新修改的資料。

四、當機後的手動配置主機

1、簡介

大家有沒有思考過一個問題,以上述的模式,當我們的master節點崩了之後,我們的叢集中就沒有的master-slave的關系,這個問題我們可以怎麼解決呢?

上面的主從複制的模式是一個,master有n個slave跟随。在這種模式下,當master節點當機時,我們如果要是想要重新實作redis叢集,顯得很麻煩(我們需要從新設定master和slave的從屬關系),尤其是slave的數量很多的時候。為例解決這種問題,我們需要使用另一種模式。

我們可以将redis叢集中的節點通過鍊式結構進行部署,即master後面跟随一個slave01,slave01後面跟随slave02,…

【Redis】主從複制(哨兵)

2、搭建鍊式叢集

① 啟動三台redis服務

略…

② 配置鍊式叢集

6380作為6379的slave

127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
           

6381作為6380的slave

127.0.0.1:6381> slaveof 127.0.0.1 6380
OK

           

③ 檢視叢集的從屬關系

6379作為master節點,下面有一個slave(6380)。

【Redis】主從複制(哨兵)

由下圖,我們可以發現,及時6381将6380作為其mast節點,但是6380的角色依然是salve,這是因為6380仍然是6379的slave節點。但是下圖顯示6380有一個slave節點(6381)

【Redis】主從複制(哨兵)

由下圖,我們知道6381是作為6380的slave存在的

【Redis】主從複制(哨兵)

3、測試主從複制

寫入同步測試

//master節點中存入name
127.0.0.1:6379> set name studioustiger
OK

//master的直接從節點中是同步了name的
127.0.0.1:6380> get name
"studioustiger"

// 6380的直接從節點中也是同步了name的
127.0.0.1:6381> get name
"studioustiger"
           

清空同步測試

127.0.0.1:6379> flushdb
OK

127.0.0.1:6380> get name
(nil)

127.0.0.1:6381> get name
(nil)
           

4、master當機後手動配置master節點

關閉 6379

127.0.0.1:6379> SHUTDOWN
not connected> exit
[[email protected] bin]#

           

檢視6380的 info,發現其依然是slave節點,我們知道slave節點是不能進行寫操作的。

127.0.0.1:6380> info replication
# Replication
role:slave						//還是6379的slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
           

如果master節點出現當機的情況,那麼我們可以可以使用

slaveof no one

指令使原本的slave節點成為master節點。使其可以進行寫操作。

127.0.0.1:6380> slaveof no one			//設定自己是master
OK
127.0.0.1:6380> info replication		
# Replication
role:master								//确實是6381的master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=1038,lag=1
master_failover_state:no-failover
master_replid:58d09dee46e027f7696ce81c475e816eb56d688e
master_replid2:2ff752995921edd75b47e257435dbe952aa81d7f
master_repl_offset:1038
second_repl_offset:1039
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1038
           

寫入測試

//在新的master節點中寫入資料
127.0.0.1:6380> set age 18
OK

//其從節點是可以同步的
127.0.0.1:6381> get age
"18"
           

五、哨兵模式

1、簡介

經曆過(四)中的手動配置,是不是就得很麻煩,而且上面的主從複制方法,我們并不會在實際的開發中去使用,上面的方式隻是讓我們更加的了解什麼是主從複制。因為隻有了解了上面的主從複制原理,那麼對于接下來的哨兵模式才會遊刃有餘。所謂的哨兵模式就是一個起到監控的作用,當我們的master節點或slave節點發生當機的情況的時候,我們需要通過某種機制實作監控的作用。

redis給我們提供了哨兵(sentinal)。sentinel是Redis官方推薦的高可用性(HA)解決方案。實際上這意味着你可以使用Sentinel模式建立一個可以不用人為幹預而應對各種故障的Redis部署。

【Redis】主從複制(哨兵)

上圖表現出的是三個redis伺服器搭建的一個redis叢集被一個哨兵所監控,當redis叢集中的某一個節點發生當機的情況,那麼哨兵将會檢查到,并且自動的選出新的節點。

上圖中的模式還是有些不足,比如說,當哨兵當機了那可咋辦,是以我們需要對上面的模式進行改進——搭建一個哨兵的叢集。如下圖:

【Redis】主從複制(哨兵)

哨兵的三大功能:

  1. 監控(Monitoring): 哨兵(sentinel) 會不斷地檢查你的Master和Slave是否運作正常。
  2. 提醒(Notification):當被監控的某個 Redis出現問題時, 哨兵(sentinel) 可以通過 API 向管理者或者其他應用程式發送通知。
  3. 自動故障遷移(Automatic failover):當一個Master不能正常工作時,哨兵(sentinel) 會開始一次自動故障遷移操作,它會将失效Master的其中一個Slave更新為新的Master, 并讓失效Master的其他Slave改為複制新的Master; 當用戶端試圖連接配接失效的Master時,叢集也會向用戶端傳回新Master的位址,使得叢集可以使用Master代替失效Master。

2、搭建單哨兵模式

搭建一個單哨兵模式還是比較簡單的,我們使用單哨兵模式可以更好的看清楚哨兵的作用。

第一步:建立 sentinel.conf檔案

建立 sentinel.conf檔案(

vim sentinel.conf

【Redis】主從複制(哨兵)

編寫sentinel.conf檔案

# 哨兵sentinel執行個體運作的端口 預設26379
port 26379

sentinel monitor mymaster 127.0.0.1 6379 1
           

第二步:啟動redis叢集,配置号主從複制

啟動redis叢集

略…

配置号主從複制

【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)
【Redis】主從複制(哨兵)

第三部:啟動哨兵

【Redis】主從複制(哨兵)

第四步:關閉6379redis服務

關閉6379redis服務

127.0.0.1:6379> SHUTDOWN
not connected> exit
[[email protected] bin]#
           

檢視 6380和6381的info

發現6380仍然是slave節點

【Redis】主從複制(哨兵)

發現6381成為master節點了

【Redis】主從複制(哨兵)

檢視sentinel節點的情況

原來是被sentinel節點監控到了,是以進行了重新選舉,産生了新的master節點

【Redis】主從複制(哨兵)

第五步:重新開機6379redis服務

此時,你好不好奇,如果原本的master節點恢複了,那麼原本的master節點将會以什麼樣的角色出現呢?我們來試一下

【Redis】主從複制(哨兵)

總結

當原本的master節點當機之後,那麼sentinel(哨兵)節點會監控到,并且會在剩餘的slave節點中選舉出新的master節點。當原本的master恢複之後,它隻能作為新的master節點的從節點存在。

sentinel是選舉master是通過相關的算法實作的,我們在這裡先不講。

3、完整的sentinel.conf檔案

# Example sentinel.conf
 
# 哨兵sentinel執行個體運作的端口 預設26379
port 26379
 
# 哨兵sentinel的工作目錄
dir /tmp
 
# 哨兵sentinel監控的redis主節點的 ip port 
# master-name  可以自己命名的主節點名字 隻能由字母A-z、數字0-9 、這三個字元".-_"組成。
# quorum 當這些quorum個數sentinel哨兵認為master主節點失聯 那麼這時 客觀上認為主節點失聯了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
  sentinel monitor mymaster 127.0.0.1 6379 2
 
# 當在Redis執行個體中開啟了requirepass foobared 授權密碼 這樣所有連接配接Redis執行個體的用戶端都要提供密碼
# 設定哨兵sentinel 連接配接主從的密碼 注意必須為主從設定一樣的驗證密碼
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之後 主節點沒有應答哨兵sentinel 此時 哨兵主觀上認為主節點下線 預設30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
 
# 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,
這個數字越小,完成failover所需的時間就越長,
但是如果這個數字越大,就意味着越 多的slave因為replication而不可用。
可以通過将這個值設為 1 來保證每次隻有一個slave 處于不能處理指令請求的狀态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
 
 
 
# 故障轉移的逾時時間 failover-timeout 可以用在以下這些方面: 
#1. 同一個sentinel對同一個master兩次failover之間的間隔時間。
#2. 當一個slave從一個錯誤的master那裡同步資料開始計算時間。直到slave被糾正為向正确的master那裡同步資料時。
#3.當想要取消一個正在進行的failover所需要的時間。  
#4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個逾時,slaves依然會被正确配置為指向master,但是就不按parallel-syncs所配置的規則來了
# 預設三分鐘
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置當某一事件發生時所需要執行的腳本,可以通過腳本來通知管理者,例如當系統運作不正常時發郵件通知相關人員。
#對于腳本的運作結果有以下規則:
#若腳本執行後傳回1,那麼該腳本稍後将會被再次執行,重複次數目前預設為10
#若腳本執行後傳回2,或者比2更高的一個傳回值,腳本将不會重複執行。
#如果腳本在執行過程中由于收到系統中斷信号被終止了,則同傳回值為1時的行為相同。
#一個腳本的最大執行時間為60s,如果超過這個時間,腳本将會被一個SIGKILL信号終止,之後重新執行。
 
#通知型腳本:當sentinel有任何警告級别的事件發生時(比如說redis執行個體的主觀失效和客觀失效等等),将會去調用這個腳本,
這時這個腳本應該通過郵件,SMS等方式去通知系統管理者關于系統不正常運作的資訊。調用該腳本時,将傳給腳本兩個參數,
一個是事件的類型,
一個是事件的描述。
如果sentinel.conf配置檔案中配置了這個腳本路徑,那麼必須保證這個腳本存在于這個路徑,并且是可執行的,否則sentinel無法正常啟動成功。
#通知腳本
# sentinel notification-script <master-name> <script-path>
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 用戶端重新配置主節點參數腳本
# 當一個master由于failover而發生改變時,這個腳本将會被調用,通知相關的用戶端關于master位址已經發生改變的資訊。
# 以下參數将會在調用腳本時傳給腳本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>總是“failover”,
# <role>是“leader”或者“observer”中的一個。 
# 參數 from-ip, from-port, to-ip, to-port是用來和舊的master和新的master(即舊的slave)通信的
# 這個腳本應該是通用的,能被多次調用,不是針對性的。
# sentinel client-reconfig-script <master-name> <script-path>
 sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
 
           

4、搭建哨兵叢集

通常情況下,我們會有一個哨兵叢集,其目的是為了方式單個哨兵當機之後,無法選舉出新的節點,導緻redis服務無法正常的執行。

我們在進行搭建sentinel叢集是通常會選擇奇數個sentinel節點,這是因為當master節點當機之後,sentinel節點需要進行選舉,如果我們搭建的是偶數個節點的叢集,那麼選舉的時候可能會出現重票的情況。

正常情況下我們的redis叢集不應該是在一台計算機上搭建的,但是我在這偷懶了,我們使用的是同一台虛拟機的不同的端口實作了僞叢集。接下來我們将實作三個redis-server和三個redis-sentinel的redis叢集。

第一步:編寫sentinel.conf配置檔案

sentinel1.conf:

# 哨兵sentinel執行個體運作的端口 預設26379
port 26379

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

port:表示目前的sentinel服務開啟時使用的端口号(預設為26379)。

< master-name>:表示redis叢集中的master名字(自定義)。

< ip>:表示redis叢集中的master的IP。

< redis-port>:表示redis叢集中的master服務所占用的端口号。

< quorum>:表示當master節點當機之後,需要幾個sentinel節點确認才可以重新選舉master。

sentinel2.conf:

# 哨兵sentinel執行個體運作的端口 預設26379
port 26380

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

sentinel3.conf:

# 哨兵sentinel執行個體運作的端口 預設26379
port 26381

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

第二步:啟動三個redis-server服務

略…

值得注意的是,我們不需要使用手動配置master-slave,當發現叢集中不存在master節點的時候,sentinel會自動進行選舉。

第三步:啟動三個redis-sentinel服務

啟動第一個sentinel

【Redis】主從複制(哨兵)

啟動第二個sentinel

【Redis】主從複制(哨兵)

啟動第三個sentinel

【Redis】主從複制(哨兵)

第四步:檢視redis程序情況

ps -ef | grep redis

【Redis】主從複制(哨兵)

第五步:模仿master當機的情況

目前6381是master節點

【Redis】主從複制(哨兵)

關閉master節點

【Redis】主從複制(哨兵)

此時發現,6380成為了新的master節點

【Redis】主從複制(哨兵)

當6381恢複之後,我們看一下master和slave的情況。發現6381隻能作為6380的slave節點存在。

【Redis】主從複制(哨兵)

5、sentinel(哨兵)監控的工作原理

哨兵 (sentinel) 是一個分布式系統,你可以在一個架構中運作多個哨兵(sentinel) 程序,這些程序使用流言協定 (gossipprotocols) 來接收關于Master是否下線的資訊,并使用投票協定 (agreement protocols) 來決定是否執行自動故障遷移,以及選擇哪個 Slave 作為新的 Master 。

每個哨兵 (sentinel) 會向其它哨兵 (sentinel)、master、slave定時發送消息,以确認對方是否”活”着,如果發現對方在指定時間(可配置)内未回應,則暫時認為對方已挂(所謂的”主觀認為當機” Subjective Down,簡稱 sdown).

若“哨兵群”中的多數 sentinel ,都報告某一 master 沒響應(也就是為什麼我們要設定 quorum 為 2 的原因),系統才認為該master"徹底死亡"(即:客觀上的真正 down 機, Objective Down ,簡稱 odown ),通過一定的 vote 算法(從 slave 中選取 master 的算法),從剩下的 slave 節點中,選一台提升為 master ,然後自動修改相關配置。

今天的心情很複雜,五味雜陳。迷茫與不安并行,願每一個年輕人為自己的選擇負責到底 …

【Redis】主從複制(哨兵)

繼續閱讀