1. 程式人生 > 資料庫 >Redis主從複製搭建和哨兵模式

Redis主從複製搭建和哨兵模式

Redis主從複製原理是什麼?


 1.設定了一個從伺服器,在連線時它傳送了一個SYNC命令,不管它是第一次連線還是再次連線都沒有關係

2.然後主伺服器開始後臺儲存,並且開始快取新連線進來的修改資料的命令。當後臺儲存完成後,主伺服器把資料檔案傳送到從伺服器,
從伺服器將其儲存在磁碟上,然後載入到記憶體中。然後主伺服器把剛才快取的命令傳送到從伺服器。這是作為命令流來完成的,並且
和Redis協議本身格式相同

3.在Redis伺服器工作時連線到Redis埠,傳送SYNC命令,會看到一個批量的傳輸,並且主伺服器接收的每一個命令都會通過telnet會話重新發送一遍

4.當主從伺服器之間的連線由於某些原因斷開時,從伺服器可以自動進行重連線。當有多個從伺服器同時請求同步時,主伺服器只進行一個後臺儲存

5.當連線斷開又重新連上之後,一般都會進行一個完整的重新同步,但是從Redis2.8開始,只重新同步一部分也可以

 

主從複製的作用

1. 資料冗餘:主從複製實現了資料的熱備份,是持久化之外的一種資料冗餘方式

2. 故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗餘

3. 負載均衡:在主從複製的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis資料時應用連線主節點,讀Redis資料時應用連線從節點),分擔伺服器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis伺服器的併發量

4. 讀寫分離:可以用於實現讀寫分離,主庫寫、從庫讀,讀寫分離不僅可以提高伺服器的負載能力,同時可根據需求的變化,改變從庫的數量

5. 高可用基石:除了上述作用以外,主從複製還是哨兵和叢集能夠實施的基礎,因此說主從複製是Redis高可用的基礎

 

伺服器環境說明

作業系統:Centos 7

主伺服器:172.30.93.122

從伺服器:172.30.93.123

從伺服器:172.30.93.124

Redis版本:5.0.9

 

安裝Redis

三臺伺服器安裝都一樣,配置檔案有一些不同如下:

[root@Redis-Node1 ~]# yum -y install tcl gcc gcc-c++  make zlib zlib-devel
[root@Redis-Node1 ~]# wget https://download.redis.io/releases/redis-5.0.9.tar.gz
[root@Redis-Node1 ~]# tar zxvf redis-5.0.9.tar.gz -C /usr/local/ && rm -rf redis-5.0.9.tar.gz 
[root@Redis-Node1 ~]# cd /usr/local/redis-5.0.9/
[root@Redis-Node1 /usr/local/redis-5.0.9]# make && make install PREFIX=/usr/local/redis
[root@Redis-Node1 /usr/local/redis-5.0.9]# cp -rf redis.conf /usr/local/redis
[root@Redis-Node1 /usr/local/redis-5.0.9]# cd /usr/local/redis
[root@Redis-Node1 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.122
daemonize yes
protected-mode no
port 6379 logfile /usr/local/redis/logs/redis.log dir /usr/local/redis/data [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# mkdir logs data [root@Redis-Node1 /usr/local/redis]# vim /etc/systemd/system/redis.service [Unit] Description=redis-server After=network.target [Service] Type=forking ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf PrivateTmp=true [Install] WantedBy=multi-user.target [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# systemctl daemon-reload [root@Redis-Node1 /usr/local/redis]# ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis [root@Redis-Node1 /usr/local/redis]# vim /etc/sysctl.conf net.core.somaxconn = 1024 vm.overcommit_memory = 1 [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# sysctl -p [root@Redis-Node1 /usr/local/redis]# vim /etc/rc.local echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# source /etc/rc.local [root@Redis-Node1 /usr/local/redis]# systemctl start redis.service

唯一不同的就是從伺服器的配置檔案需要修改一下內容,設定主節點的IP和埠

從伺服器:172.30.93.123配置檔案內容:

[root@Redis-Node2 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.123
daemonize yes
protected-mode no
port 6379
logfile /usr/local/redis/logs/redis.log
dir /usr/local/redis/data
replicaof 172.30.93.122 6379

[root@Redis-Node2 /usr/local/redis]#

從伺服器:172.30.93.124配置檔案內容:

[root@Redis-Node3 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.124
daemonize yes
protected-mode no
port 6379
logfile /usr/local/redis/logs/redis.log
dir /usr/local/redis/data
replicaof 172.30.93.122 6379

[root@Redis-Node3 /usr/local/redis]#

 

檢查節點同步

主節點:

[root@Redis-Node1 /usr/local/redis]# redis -h 172.30.93.122 -p 6379
172.30.93.122:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.93.123,port=6379,state=online,offset=16982,lag=0
slave1:ip=172.30.93.124,port=6379,state=online,offset=16982,lag=0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:16982
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:16982
172.30.93.122:6379> set ops dev
OK
172.30.93.122:6379> 

啟動節點之後檢視到已經有其他資料庫的資訊,有兩個slave連線到master,並且建立資料看slave是否同步

從節點:

[root@Redis-Node2 /usr/local/redis]# redis -h 172.30.93.123 -p 6379
172.30.93.123:6379> INFO replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:17316
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:17316
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:17316
172.30.93.123:6379> 
172.30.93.123:6379> get ops
"dev"
172.30.93.123:6379> 

從節點

[root@Redis-Node3 /usr/local/redis]# redis -h 172.30.93.124 -p 6379
172.30.93.124:6379> INFO replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:17708
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:17708
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:17708
172.30.93.124:6379> get ops
"dev"
172.30.93.124:6379> 

可以看到兩個從節點都是slave狀態,並且資料已經同步資料庫裡。主從同步成功

 

主從同步中需要注意幾個問題

1. 在上面的全量同步過程中,master會將資料儲存在rdb檔案中然後傳送給slave伺服器,但是如果master上的磁碟空間有效怎麼辦呢?那麼此時全部同步對於master來說將是一份十分有壓力的操作了。此時可以通過無盤複製來達到目的,由master直接開啟一個socket將rdb檔案傳送給slave伺服器。(無盤複製一般應用在磁碟空間有限但是網路狀態良好的情況下)

2. 主從複製結構,一般slave伺服器不能進行寫操作,但是這不是死的,之所以這樣是為了更容易的保證主和各個從之間資料的一致性,如果slave伺服器上資料進行了修改,那麼要保證所有主從伺服器都能一致,可能在結構上和處理邏輯上更為負責。不過你也可以通過配置檔案讓從伺服器支援寫操作。(不過所帶來的影響還得自己承擔哦)

3. 主從伺服器之間會定期進行通話,但是如果master上設定了密碼,那麼如果不給slave設定密碼就會導致slave不能跟master進行任何操作,所以如果你的master伺服器上有密碼,那麼也給slave相應的設定一下密碼吧(通過設定配置檔案中的masterauth);

4. 關於slave伺服器上過期鍵的處理,由master伺服器負責鍵的過期刪除處理,然後將相關刪除命令已資料同步的方式同步給slave伺服器,slave伺服器根據刪除命令刪除本地的key

 

哨兵模式

Sentinel(哨兵)是用於監控redis叢集中Master狀態的工具,是Redis的高可用性解決方案。sentinel是redis高可用的解決方案,sentinel系統可以監視一個或者多個redis master服務,以及這些master服務的所有從服務;當某個master服務下線時,自動將該master下的某個從服務升級為master服務替代已下線的master服務繼續處理請求。
sentinel可以讓redis實現主從複製,當一個叢集中的master失效之後,sentinel可以選舉出一個新的master用於自動接替master的工作,叢集中的其他redis伺服器自動指向新的master同步資料。一般建議sentinel採取奇數臺,防止某一臺sentinel無法連線到master導致誤切換。
Sentinel由一個或多個Sentinel 例項 組成的Sentinel 系統可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器,並在被監視的主伺服器進入下線狀態時,自動將下線主伺服器屬下的某個從伺服器升級為新的主伺服器。

 

哨兵工作方式

1.每個Sentinel以每秒鐘一次的頻率向它所知的Master,Slave以及其他 Sentinel 例項傳送一個PING命令
2.如果一個例項(instance)距離最後一次有效回覆PING命令的時間超過 own-after-milliseconds 選項所指定的值,則這個例項會被Sentinel標記為主觀下線
3.如果一個Master被標記為主觀下線,則正在監視這個Master的所有 Sentinel 要以每秒一次的頻率確認Master的確進入了主觀下線狀態
4.當有足夠數量的Sentinel(大於等於配置檔案指定的值)在指定的時間範圍內確認Master的確進入了主觀下線狀態,則Master會被標記為客觀下線
5.在一般情況下,每個Sentinel 會以每10秒一次的頻率向它已知的所有Master,Slave傳送 INFO 命令
6.當Master被Sentinel標記為客觀下線時,Sentinel 向下線的 Master 的所有Slave傳送 INFO命令的頻率會從10秒一次改為每秒一次
7.若沒有足夠數量的Sentinel同意Master已經下線,Master的客觀下線狀態就會被移除。若Master重新向Sentinel 的PING命令返回有效回覆,Master的主觀下線狀態就會被移除

 

搭建哨兵模式

由於哨兵模式是基於主從複製,所以我們就基於上面的環境搭建

搭建的環境模式,一主兩從三哨兵

[root@Redis-Node1 ~]# cd /usr/local/redis/
[root@Redis-Node1 /usr/local/redis]# vim sentinel.conf

port 26379

daemonize yes

protected-mode no

pidfile "/var/run/redis-sentinel.pid"

logfile "/usr/local/redis/logs/sentinel.log"

dir "/usr/local/redis/data"

sentinel monitor mymaster 172.30.93.122 6379 2

# redis主從密碼,這裡也需要設定
# sentinel auth-pass mymaster redis2021

sentinel down-after-milliseconds mymaster 3000 

snetinel parallel-syncs mymaster 1 

sentinel failover-timeout mymaster 180000

sentinel deny-scripts-reconfig yes


[root@Redis-Node1 /usr/local/redis]# vim /etc/systemd/system/redis-sentinel.service

[Unit]
Description=Redis sentinel Server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/redis-sentinel.pid
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/sentinel.conf --sentinel
ExecStop=/usr/local/redis/bin/redis-cli -p 26379 shutdown
Restart=on-failure
[Install]
WantedBy=multi-user.target

[root@Redis-Node1 /usr/local/redis]# systemctl daemon-reload
[root@Redis-Node1 /usr/local/redis]# systemctl start redis-sentinel

三臺伺服器一起執行這些命令就可以了,其他 sentinel.conf 配置檔案都是重新生成的(後期如果主的redis  master掛了,配置檔案會自動修改)

配置檔案修改說明:

//埠預設為26379 
port:26379 

//設定為後臺啟動
daemonize:yes 

//關閉保護模式,可以外部訪問
protected-mode:no 

//PID檔案路徑
pidfile "/var/run/redis-sentinel.pid"

//日誌檔案路徑 
logfile "/usr/local/redis/logs/sentinel.log"

//資料存放路徑
dir "/usr/local/redis/data"

//指定主機IP地址和埠,並且指定當有2臺哨兵認為主機掛了,則對主機進行容災切換
sentinel monitor mymaster 172.30.93.122 6379 2 

//redis主從密碼,這裡也需要設定
# sentinel auth-pass mymaster redis2021

//這裡設定了主機多少秒無響應,則認為掛了 
sentinel down-after-milliseconds mymaster 3000 

//主備切換時,最多有多少個slave同時對新的master進行同步,這裡設定為預設的1
snetinel parallel-syncs mymaster 1 

//故障轉移的超時時間,這裡設定為三分鐘 
sentinel failover-timeout mymaster 180000 

//避免了一個簡單的安全問題,客戶端可以將指令碼設定為任何內容並觸發故障轉移以便執行程式
sentinel deny-scripts-reconfig yes

 

檢視哨兵模式同步

[root@Redis-Node1 ~]# redis -h 172.30.93.122 -p 6379
172.30.93.122:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.93.123,port=6379,state=online,offset=88409,lag=1
slave1:ip=172.30.93.124,port=6379,state=online,offset=88409,lag=1
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:88691
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:88691
172.30.93.122:6379> 
172.30.93.122:6379> 
172.30.93.122:6379> get ops
"dev"
172.30.93.122:6379> 
[root@Redis-Node1 ~]# 
[root@Redis-Node1 ~]# redis -h 172.30.93.122 -p 26379
172.30.93.122:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.30.93.122:6379,slaves=2,sentinels=3
172.30.93.122:26379>

[root@Redis-Node1 ~]# 

可以看到,哨兵已經監聽到當前的主機IP埠和執行狀態,並且有2臺從機,3個哨兵。

 

模擬故障

[root@Redis-Node1 ~]# systemctl stop redis

把Redis主的master停了之後,檢視其他節點情況

[root@Redis-Node2 /usr/local/redis]# redis -h 172.30.93.123 -p 6379
172.30.93.123:6379> info replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:128437
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:128437
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:128437
172.30.93.123:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.30.93.124,port=6379,state=online,offset=151174,lag=0
master_replid:d20539eba07d1083084387dc8e15f55ce265476f
master_replid2:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_repl_offset:151174
second_repl_offset:148600
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:151174
172.30.93.123:6379> 

現在我們去看三臺伺服器的情況,發現剛才的主機(172.30.93.122 6379)已經停機了,而哨兵(Sentinel)通過選舉機制選舉了從機(172.30.93.123 6379)作為了新的主機,還有一個從節點(172.30.93.124 6379)

到此,主從+哨兵的叢集架構搭建完成

 

本文分享完畢,感謝支援點贊~~