文章目錄
-
- 一、簡介
- 二、搭建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的主從複制是對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為例,其他的檔案操作一樣。
配置端口
配置pid名稱
配置log檔案名
配置dump.rdb檔案名
三、主從複制的複制原理
1、開啟三個redis服務
通過上述的三個配置檔案打開三個redis服務,預設情況下,每一台伺服器都是主節點(我們可以通過
info replication
指令進行檢視)
2、指令實作主從複制(臨時)
我們可以使用指令的形式設定slave節點,但是這種方式的臨時的,當redis重新開機之後,重新開機的redis又都是master角色了。
① 設定6380和6381為6379的slave節點
slaveof address port
該指令的作用是設定目前節點是哪個節點的slave,address表示master的位址,port表示master的端口号。
② 增量複制 測試
//在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,完成一次完全(全量)同步。
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,…
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)。
由下圖,我們可以發現,及時6381将6380作為其mast節點,但是6380的角色依然是salve,這是因為6380仍然是6379的slave節點。但是下圖顯示6380有一個slave節點(6381)
由下圖,我們知道6381是作為6380的slave存在的
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叢集中的某一個節點發生當機的情況,那麼哨兵将會檢查到,并且自動的選出新的節點。
上圖中的模式還是有些不足,比如說,當哨兵當機了那可咋辦,是以我們需要對上面的模式進行改進——搭建一個哨兵的叢集。如下圖:
哨兵的三大功能:
- 監控(Monitoring): 哨兵(sentinel) 會不斷地檢查你的Master和Slave是否運作正常。
- 提醒(Notification):當被監控的某個 Redis出現問題時, 哨兵(sentinel) 可以通過 API 向管理者或者其他應用程式發送通知。
- 自動故障遷移(Automatic failover):當一個Master不能正常工作時,哨兵(sentinel) 會開始一次自動故障遷移操作,它會将失效Master的其中一個Slave更新為新的Master, 并讓失效Master的其他Slave改為複制新的Master; 當用戶端試圖連接配接失效的Master時,叢集也會向用戶端傳回新Master的位址,使得叢集可以使用Master代替失效Master。
2、搭建單哨兵模式
搭建一個單哨兵模式還是比較簡單的,我們使用單哨兵模式可以更好的看清楚哨兵的作用。
第一步:建立 sentinel.conf檔案
建立 sentinel.conf檔案(
vim sentinel.conf
)
編寫sentinel.conf檔案
# 哨兵sentinel執行個體運作的端口 預設26379
port 26379
sentinel monitor mymaster 127.0.0.1 6379 1
第二步:啟動redis叢集,配置号主從複制
啟動redis叢集
略…
配置号主從複制
第三部:啟動哨兵
第四步:關閉6379redis服務
關閉6379redis服務
127.0.0.1:6379> SHUTDOWN
not connected> exit
[[email protected] bin]#
檢視 6380和6381的info
發現6380仍然是slave節點
發現6381成為master節點了
檢視sentinel節點的情況
原來是被sentinel節點監控到了,是以進行了重新選舉,産生了新的master節點
第五步:重新開機6379redis服務
此時,你好不好奇,如果原本的master節點恢複了,那麼原本的master節點将會以什麼樣的角色出現呢?我們來試一下
總結
當原本的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
啟動第二個sentinel
啟動第三個sentinel
第四步:檢視redis程序情況
ps -ef | grep redis
第五步:模仿master當機的情況
目前6381是master節點
關閉master節點
此時發現,6380成為了新的master節點
當6381恢複之後,我們看一下master和slave的情況。發現6381隻能作為6380的slave節點存在。
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 ,然後自動修改相關配置。
今天的心情很複雜,五味雜陳。迷茫與不安并行,願每一個年輕人為自己的選擇負責到底 …