1. 程式人生 > >Redis主從復制與高可用方案

Redis主從復制與高可用方案

安裝配置 失敗 tle nap 腳本 登錄 上線 集群 masters

redis簡單介紹

Redis 是完全開源免費的,遵守BSD協議,是一個高性能的key-value數據庫。Redis與其他key – value緩存產品有以下三個特點:

  • 支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。
  • 不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
  • 支持數據的備份,即master-slave模式的數據備份。

    Redis的持久化

RDB:snapshotting

二進制格式;按事先定制的策略,周期性地將數據從內存同步至磁盤;數據文件默認為dump.rdb;
客戶端顯式使用SAVE或BGSAVE命令來手動啟動快照保存機制;

  • SAVE:同步,即在主線程中保存快照,此時會阻塞所有客戶端請求;
  • BGSAVE:異步,backgroud:後臺啟動快照線程,服務不受影響

RDB相關的配置

save <seconds> <changes>  觸發快照的策略

save 900 1   #第一級匹配
save 300 10   : 達不到第三個就匹配第二級
save 60 10000  : 60秒內有10000個鍵發生更改就觸發快照

#表示:三個策略滿足其中任意一個均會觸發SNAPSHOTTING操作;
900s內至少有一個key有變化,300s內至少有10個key有變化,
60s內至少有1W個key發生變化;

其他參數

  • stop-writes-on-bgsave-error yes : dump操作出現錯誤時,是否禁止新的寫入操作請求;
  • rdbcompression yes :壓縮存放,節約I/O
  • rdbchecksum yes ;校驗
  • dbfilename dump.rdb:指定rdb文件名
  • dir /var/lib/redis:rdb文件的存儲路徑

AOF:Append Only File, fsync

記錄每次寫操作至指定的文件尾部實現的持久化,當redis重啟時,可通過重新執行文件中的命令在內存中重建出數據庫,

BGREWRITEAOF:AOF文件重寫

不會讀取正在使用AOF文件,而是通過將內存中的數據以命令的方式保存至臨時文件中,完成之後替換原來的AOF文件;

AOF相關的配置

  • appendonly no :默認禁用
  • appendfilename “appendonly.aof” :
  • appendfsync :將aof文件的緩沖區數據同步到磁盤,防止故障導致數據丟失,同步頻繁會導致I/O負載過大,可以同步方式如下:
    • no:redis:不執行主動同步操作,而是OS進行;
    • everysec:每秒一次;
    • always:每語句一次;
  • no-appendfsync-on-rewrite no :是否在後臺執行aof重寫期間不調用fsync,默認為no,表示調用;
  • auto-aof-rewrite-percentage 100 :對aof文件變化量的控制
  • auto-aof-rewrite-min-size 64mb :對aof規定大小最小達到64MB才重寫

上述兩個條件同時滿足時,方會觸發重寫AOF;與上次aof文件大小相比,其增長量超過100%,且大小不少於64MB;

  • aof-load-truncated yes :裝載aof文件時如果有殘缺部分則自動修剪(清理掉)
  • 註意:持久機制本身不能取代備份;應該制訂備份策略,對redis庫定期備份;

兩種存儲方式最好不要同時啟用,RDB與AOF同時啟用特點如下

  • (1) BGSAVE和BGREWRITEAOF不會同時進行;
  • (2) Redis服務器啟動時用持久化的數據文件恢復數據,會優先使用AOF;

redis主從復制

redis主從復制的特點:

  • 一個Master可以有多個slave主機,支持鏈式復制;
  • Master以非阻塞方式同步數據至slave主機;

技術分享圖片

配置redis主從復制相對比較簡單:
在一臺節點上配置文件中定義自己是誰的從節點,並且啟用主節點密碼認證即可。
下面使用3臺主機配置一主兩從的結構,redis使用一主多從的結構時還可以實現像mysql MHA那樣的復制集群,當master節點宕機後,可以在兩個slave節點中根據優先級選舉新的master。因此這裏使用3個節點,這部分內容會在後面單獨說道。

復制的兩種方式

新的從節點或某較長時間未能與主節點進行同步的從節點重新與主節點通信,需要做“full synchronization”,此時其同步方式有兩種方式:

  • Disk-backend:主節點基於內存創建快照文件於磁盤中,而後將其發送給從節點;從節點收到快照進行恢復,快照恢復完後接著快照的那一刻隨後內容進行復制,主節點每寫一行,並直接將語句發送給從節點(跨網絡復制適合)
  • Diskless:主節占新創建快照後直接通過網絡套接字文件發送給從節點;為了實現並行復制,通常需要在復制啟動前延遲一個時間段;(占用網絡帶寬)

安裝配置redis一主多從

  • 各節點安裝redis
yum install redis -y
  • 配置master節點
bind 0.0.0.0     #綁定地址
requirepass gudaoyufu   #啟用密碼認證
#默認master節點修改這兩項就可以了,也可以進行其他設置
  • 配置各slave節點
bind 0.0.0.0    
slaveof 192.168.214.148 6379   #定義master信息
masterauth gudaoyufu  #認證

從節點上配置這三項頁就可以,其他參數可以根據情況選擇調整即可。

修改後記得重啟服務,此時登錄到master節點查看信息:

[root@master ~]# redis-cli -h 127.0.0.1 -a gudaoyufu
127.0.0.1:6379> CLIENT LIST
id=5 addr=192.168.214.149:39804 fd=5 name= age=326 idle=1 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf
id=7 addr=127.0.0.1:35262 fd=6 name= age=4 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

#看到第一條記錄最後cmd=replconf就說明該節點是從節點

或者使用指令INFO replication指令查看信息:

127.0.0.1:6379> INFO replication
# Replication
role:master   #自己的角色
connected_slaves:1  #從節點數量
slave0:ip=192.168.214.149,port=6379,state=online,offset=995,lag=1   #從節點信息
master_repl_offset:995
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:994

接著將slave-2也配置好,與slave-1配置相同即可,配置好後重啟服務,查看master節點信息

127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.214.149,port=6379,state=online,offset=1793,lag=1
slave1:ip=192.168.214.150,port=6379,state=online,offset=1793,lag=1
master_repl_offset:1793
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1792

可以看到信息發送變化,兩個從節點已經上線,接下來可以進行簡單的驗證復制,在master節點設置一個key,看兩個slave節點復制情況:

master節點創建一個key

127.0.0.1:6379> SET mykey 111
OK
127.0.0.1:6379> get mykey
"111"

兩個slave節點查看:

[root@slave-1 ~]# redis-cli -h 127.0.0.1 -a gudaoyufu
127.0.0.1:6379> get mykey
"111"
#
[root@slave-2 ~]# redis-cli -h 127.0.0.1 -a gudaoyufu
127.0.0.1:6379> get mykey
"111"

slave節點定義也可以通過指令設置,設置後立即生效,並且會被保存至配置文件中,指令配置方式如下:

配置slave節點:

redis-cli> SLAVEOF <MASTER_IP> <MASTER_PORT>
redis-cli> CONFIG SET masterauth <PASSWORD>

redis主從復制相關配置

下面是redis主從復制場景的一些可調參數,需要根據實際環境調整

  • slave-serve-stale-data yes : 是否可以把不新鮮的數據服務與客戶端
  • slave-read-only yes : 從節點只讀,啟用slaveof定義後才生效
  • repl-diskless-sync no :是否同時向多個從節點同時發數據
  • repl-diskless-sync-delay 5 :發送的延遲時間
  • repl-ping-slave-period 10 探測從節點狀態
  • repl-timeout 60 探測節點超時時間
  • repl-disable-tcp-nodelay no : 啟用nodelay
  • repl-backlog-size 1mb
  • slave-priority 100 : 從節點優先級,復制集群中,主節點故障時,sentinel應用場景中的主節點選舉時使用的優先級;數字越小優先級越高,但0表示不參與選舉;
  • min-slaves-to-write 3:主節點僅允許其能夠通信的從節點數量大於等於此處的值時接受寫操作;
  • min-slaves-max-lag 10:從節點延遲時長超出此處指定的時長時,主節點會拒絕寫入操作;

redis sentinel 高可用復制集群

Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當用Redis做Master-slave的高可用方案時,如果master宕機,Redis自身並不能實現自動進行主備切換,sentinel可以監控復制節點的狀態,當主節點宕機後,它能根據選舉方式選出後端的一個從節點作為新的master,sentinel還能監控多個master-slave集群,發現master宕機後能進行自動切換。

同時,sentinel本身也存在單點問題,通常sentinel也是一個集群,因此,redis的復制集群通常是下面的結構

技術分享圖片

sentinel集群工作原理

sentinel集群通過給定的配置文件發現master,啟動時會監控master。通過向master發送info信息獲得該服務器下面的所有從服務器。

sentinel集群通過流言協議與其他sentinel通信,以此來發現監視同一個主服務器的其他sentinel;集群之間會互相創建命令連接用於通信。

sentinel集群使用ping命令來檢測實例的狀態,如果在指定的時間內(down-after-milliseconds)沒有回復或則返回錯誤的回復,sentinel會認為主節點宕機,但是並不會立即提升一個從節點為新的master,因為會存在誤判的情況,此時為主觀宕機
此時當sentinel集群中有一半以上的節點通告master為宕機狀態時,此時為客觀宕機,sentinel基於選舉協議選舉提升從節點為新的master,從節點之間根據優先級來決策誰會成為新的master,修復的節點重新上線後作為從節點工作。

配置sentinel 集群

下面使用上面的結構圖,配置sentinel集群,來監控上面已經配置好的復制集群,實現高可用復制集群。
由於沒有那麽多機器,這裏只使用6臺主機做兩個master-slave復制集群,把sentinel集群同時放在其中一組集群上與redis復制集群共存。sentinel集群同時監控兩個復制集群。

安裝redis安裝時自帶了sentinel功能,因此只要安裝了redis即可,在創建一個復制集群,並在第二個復制集群上創建sentinel集群共存。

安裝redis

[root@redis-master ~]# yum install redis -y
[root@redis-salve-1 ~]# yum install redis -y
[root@redis-salve-2 ~]# yum install redis -y

配置主從復制

bind 0.0.0.0     
requirepass gudaoyufu.com

啟動主節點redis:service redis start

啟動兩個從節點使用指令配置從節點為slave

[root@redis-salve-1 ~]# systemctl start redis
[root@redis-slave-2 ~]# systemctl start redis

salve節點配置:

[root@redis-salve-1 ~]# redis-cli
127.0.0.1:6379> slaveof 192.168.214.141 6379
OK
127.0.0.1:6379> config set masterauth gudaoyufu.com
OK

#

[root@redis-slave-2 ~]# redis-cli
127.0.0.1:6379> slaveof 192.168.214.141 6379
OK
127.0.0.1:6379> config set masterauth gudaoyufu.com
OK

主節點查看

[root@redis-master ~]# redis-cli -h 127.0.0.1 -a gudaoyufu.com
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.214.143,port=6379,state=online,offset=827,lag=1
slave1:ip=192.168.214.147,port=6379,state=online,offset=827,lag=1
master_repl_offset:841
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:840

調整兩個復制集群slave的優先級
兩個集群中選一個slave節點調低優先級

slave-priority 90
#重啟
systemctl restart redis

配置sentinel監控集群

[root@redis-master ~]# vim /etc/redis-sentinel.conf

bind 0.0.0.0
port 26379

sentinel monitor mymaster-1 192.168.214.141 6379 2
sentinel monitor mymaster-2 192.168.214.148 6379 2

sentinel auth-pass  mymaster-1 gudaoyufu.com
sentinel auth-pass  mymaster-2 gudaoyufu

sentinel down-after-milliseconds mymaster-1 30000
sentinel down-after-milliseconds mymaster-2 30000

sentinel parallel-syncs mymaster-1 1
sentinel parallel-syncs mymaster-2 1

sentinel failover-timeout mymaster-1 180000
sentinel failover-timeout mymaster-2 180000

logfile /var/log/redis/sentinel.log

將上面的配置文件配置好後各自復制一份到其他兩個節點,註意:復制配置文件一定要在啟動redis-sentinel服務之前,因為啟動服務後配置文件中會生成id號,服務個節點的id相同會造成無法選舉新的master節點

配置文件復制後啟動各節點redis-sentinel服務。

service  redis-sentinel start
systemctl  start redis-sentinel
(我使用的系統版本不一樣,所以指令不同)

在redis-sentinel.conf文件中分別定義兩個復制集群的master信息。

參數作用

  • sentinel monitor < master-name > < ip > < redis-port > < quorum >
  • sentinel auth-pass < master-name > < password >
    • < quorum >表示sentinel集群的quorum機制,即至少有quorum個sentinel節點同時判定主節點故障時,才認為其真的故障;
  • sentinel down-after-milliseconds < master-name > < milliseconds > :監控到指定的集群的主節點異常狀態持續多久方才將標記為“故障”;
  • sentinel parallel-syncs < master-name > < numslaves > : 指在failover過程中,能夠被sentinel並行配置的從節點的數量;
  • sentinel failover-timeout < master-name > < milliseconds > :sentinel必須在此指定的時長內完成故障轉移操作,否則,將視為故障轉移操作失敗;
  • sentinel notification-script < master-name > < script-path > :通知腳本,此腳本被自動傳遞多個參數;

測試故障轉移

停掉mymaster-2的主節點 (192.168.214.148 ),查看mymaster-2的主節點有沒有發生改變:

[root@redis-master ~]# redis-cli -p 26379
127.0.0.1:26379> SENTINEL masters
1)  1) "name"
    2) "mymaster-1"
    3) "ip"
    4) "192.168.214.141"
    5) "port"
    6) "6379"
    7) "runid"
    8) "c068ea99d1f60e1eb5822d6eecbde47a45661509"
    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) "151"
   19) "last-ping-reply"
   20) "151"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "770"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "793908"
   29) "config-epoch"
   30) "0"
   31) "num-slaves"
   32) "2"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
2)  1) "name"
    2) "mymaster-2"
    3) "ip"
    4) "192.168.214.149"
    5) "port"
    6) "6379"
    7) "runid"
    8) "60ba5b8b5cc52fbb691179ec43b8582a161ed7e8"
    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) "7"
   19) "last-ping-reply"
   20) "7"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "5101"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "35884"
   29) "config-epoch"
   30) "1"
   31) "num-slaves"
   32) "2"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"

從上的一堆信息中可以看到已經改變了

2) "mymaster-2"
3) "ip"
4) "192.168.214.149"   #新的master
#註意:slave節點的值越小,優先級越高

至此,兩個redis的高可用復制集群已經完成了,還有一些參數根據環境調整即可

SENTINEL常用指令

redis-cli -h SENTINEL_HOST -p SENTINEL_PORT
redis-cli>
SENTINEL masters
SENTINEL slaves < MASTER_NAME >
SENTINEL failover < MASTER_NAME >
SENTINEL get-master-addr-by-name < MASTER_NAME >

原文鏈接:http://gudaoyufu.com/?p=1230

Redis主從復制與高可用方案