redis高可用
- 高可用的概念
高可用HA(High Availability)是分布式系統(tǒng)架構(gòu)設(shè)計(jì)中必須考慮的因素之一,它通常是指,通過設(shè)計(jì)減少系統(tǒng)不能提供服務(wù)的時間。
-
通過三大要點(diǎn)解釋高可用:
單點(diǎn)是系統(tǒng)高可用的大敵,應(yīng)該盡量在系統(tǒng)設(shè)計(jì)的過程中避免單點(diǎn)
保證系統(tǒng)高可用,架構(gòu)設(shè)計(jì)的核心準(zhǔn)則是:冗余。
每次出現(xiàn)故障需要人工介入恢復(fù)勢必會增加系統(tǒng)的不可服務(wù)實(shí)踐,實(shí)現(xiàn)自動故障轉(zhuǎn)移
重啟服務(wù),看服務(wù)是否每次都獲取鎖失敗
-
分布式高可用經(jīng)典架構(gòu)環(huán)節(jié)分析
- 【客戶端層】到【反向代理層】的高可用,是通過反向代理層的冗余來實(shí)現(xiàn)的。以nginx為例:有兩臺nginx,一臺對線上提供服務(wù),另一臺冗余以保證高可用, 常見的實(shí)踐是keepalived存活探測
- 【反向代理層】到【web應(yīng)用】的高可用,是通過站點(diǎn)層的冗余來實(shí)現(xiàn)的。假設(shè)反向代理層是nginx,nginx.conf里能夠配置多個web后端,并且nginx能夠探測到多個后端的存活性。
- 自動故障轉(zhuǎn)移:當(dāng)web-server掛了的時候,nginx能夠探測到,會自動的進(jìn)行故障轉(zhuǎn)移,將流量自動遷移到其他的web-server,整個過程由nginx自動完成,對調(diào)用方是透明的。
- 【服務(wù)層】到【緩存層】的高可用,是通過緩存數(shù)據(jù)的冗余來實(shí)現(xiàn)的。
redis天然支持主從同步,redis官方也有sentinel哨兵機(jī)制,來做redis的存活性檢測。 - 【服務(wù)層】到【數(shù)據(jù)庫層】的高可用,數(shù)據(jù)庫層用“主從同步,讀寫分離”架構(gòu),所以數(shù)據(jù)庫層的高可用,又分為“讀庫高可用”與“寫庫高可用”兩類。
- 讀庫采用冗余的方式實(shí)現(xiàn)高可用,寫庫采用keepalived存活探測 binlog進(jìn)行同步
Redis高可用架構(gòu)Sentinel
災(zāi)備切換Sentinel的使用
手動模擬Sentinel功能
有三臺啟動的redis接口
[root@localhost redis-4.0.6]# ps -aux | grep redis
root 101389 0.0 0.0 142928 2248 ? Ssl 19:04 0:03 ./src/redis-server *:6379
root 101400 0.0 0.0 142944 2232 ? Ssl 19:04 0:03 ./src/redis-server *:6380
root 101446 0.0 0.0 142960 2232 ? Ssl 19:06 0:03 ./src/redis-server *:6381
root 102804 0.0 0.0 112708 976 pts/1 R+ 20:20 0:00 grep --color=auto redis
[root@localhost redis-4.0.6]#
查看三個節(jié)點(diǎn)信息
[root@localhost redis-4.0.6]# ./src/redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=6560,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=6546,lag=1
master_replid:a65d77d76690218bfc290701e6d2a6da0e35997e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:6560
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:6560
127.0.0.1:6379>
6379作為主節(jié)點(diǎn),6380和6381作為從節(jié)點(diǎn)。
- 把6379主節(jié)點(diǎn)停止(服務(wù)宕機(jī))
127.0.0.1:6379> shutdown save
not connected>
- 把6381設(shè)置為主節(jié)點(diǎn)
127.0.0.1:6380> slaveof no one
OK
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_replid:686c89241d8161d8d78c1ab6e8ba471bc5ba3d6a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:6700
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:6700
127.0.0.1:6380>
- 把6380變成6381的主節(jié)點(diǎn)
127.0.0.1:6380> exit
[root@localhost redis-4.0.6]# ./src/redis-cli -p 6381
127.0.0.1:6381> slaveof 127.0.0.1 6380
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:6700
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:e71bd6fc66c8ed23a4b359d7365d5c1d654bf4a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:6700
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:6701
repl_backlog_histlen:0
127.0.0.1:6381>
使用sentinel
- 復(fù)制
sentinel.conf
到redis-cluster
[root@localhost redis-4.0.6]# cp sentinel.conf redis-cluster/
[root@localhost redis-4.0.6]# cd redis-cluster/
[root@localhost redis-cluster]# ll
total 20
drwxr-xr-x. 2 root root 4096 Dec 8 22:29 6379
drwxr-xr-x. 2 root root 4096 Dec 11 21:28 6380
drwxr-xr-x. 2 root root 4096 Dec 12 20:52 6381
-rw-r--r--. 1 root root 7606 Dec 12 21:10 sentinel.conf
[root@localhost redis-cluster]#
- 開啟配置
sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
- 啟動sentinel
[root@localhost redis-4.0.6]# ./src/redis-sentinel redis-cluster/sentinel.conf
103750:X 12 Dec 21:24:09.277 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
103750:X 12 Dec 21:24:09.277 # Redis version=4.0.6, bits=64, commit=00000000, modified=0, pid=103750, just started
103750:X 12 Dec 21:24:09.277 # Configuration loaded
103750:X 12 Dec 21:24:09.277 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.6 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 103750
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
103750:X 12 Dec 21:24:09.278 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
103750:X 12 Dec 21:24:09.278 # Sentinel ID is f7547863b810f8e3b0a014fb793e14f503f9fdad
103750:X 12 Dec 21:24:09.278 # +monitor master mymaster 127.0.0.1 6379 quorum 1
103750:X 12 Dec 21:24:09.280 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:24:09.281 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
從啟動日志中可以明確看出6379為主節(jié)點(diǎn),6380和6381為從節(jié)點(diǎn)
- 關(guān)閉7379主節(jié)點(diǎn),查看sentinel日志
[root@localhost redis-4.0.6]# ./src/redis-cli -p 6379 shutdown
[root@localhost redis-4.0.6]#
sentinel監(jiān)控日志
103750:X 12 Dec 21:27:34.231 # +sdown master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.231 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
103750:X 12 Dec 21:27:34.231 # +new-epoch 2
103750:X 12 Dec 21:27:34.231 # +try-failover master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.232 # +vote-for-leader f7547863b810f8e3b0a014fb793e14f503f9fdad 2
103750:X 12 Dec 21:27:34.232 # +elected-leader master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.232 # +failover-state-select-slave master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.303 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.303 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:34.356 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:35.267 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:35.267 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:35.357 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:36.312 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:37.321 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:37.392 # +failover-end master mymaster 127.0.0.1 6379
103750:X 12 Dec 21:27:37.392 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
103750:X 12 Dec 21:27:37.393 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
103750:X 12 Dec 21:27:37.393 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
103750:X 12 Dec 21:27:47.401 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
從日志中可以看出+switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
6381替代了6380作為主節(jié)點(diǎn),我們登陸6381進(jìn)行驗(yàn)證
- 驗(yàn)證故障轉(zhuǎn)移是否生效
[root@localhost redis-4.0.6]# ./src/redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=30776,lag=1
master_replid:5f978d7756e69e16ae5e28a8064e43e98574f811
master_replid2:10584b87ac8a21e262a9bf1173a5c2ea4dc677c6
master_repl_offset:30909
second_repl_offset:12820
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:30909
127.0.0.1:6381>
節(jié)點(diǎn)信息顯示6381
已經(jīng)作為了主節(jié)點(diǎn),有一個活躍從節(jié)點(diǎn)為6380
。
命令解析
-
sentinel monitor mymaster 127.0.0.1 6379 1
mymaster的主節(jié)點(diǎn)名稱,1表示將這個主服務(wù)器判斷為失效至少需要1個
Sentinel
同意(只要同意 Sentinel 的數(shù)量不達(dá)標(biāo),自動故障遷移就不會執(zhí)行),如果redis節(jié)點(diǎn)分布為3主6從,那么這個值可以為2,至少需要兩個從點(diǎn)同意。 -
down-after-milliseconds
選項(xiàng)指定了
Sentinel
認(rèn)為服務(wù)器已經(jīng)斷線所需的毫秒數(shù) -
failover(故障切換)
過期時間,當(dāng)
failover
開始后,在此時間內(nèi)仍然沒有觸發(fā)任何failover
操作,當(dāng)前sentinel
將會認(rèn)為此次failoer
失敗 -
parallel-syncs
選項(xiàng)指定了在執(zhí)行故障轉(zhuǎn)移時, 最多可以有多少個從服務(wù)器同時對新的主服務(wù)器進(jìn)行同步, 這個數(shù)字越小, 完成故障轉(zhuǎn)移所需的時間就越長。
如果從服務(wù)器被設(shè)置為允許使用過期數(shù)據(jù)集, 那么你可能不希望所有從服務(wù)器都在同一時間向新的主服務(wù)器發(fā)送同步請求, 因?yàn)楸M管復(fù)制過程的絕大部分步驟都不會阻塞從服務(wù)器, 但從服務(wù)器在載入主服務(wù)器發(fā)來的 RDB 文件時, 仍然會造成從服務(wù)器在一段時間內(nèi)不能處理命令請求: 如果全部從服務(wù)器一起對新的主服務(wù)器進(jìn)行同步, 那么就可能會造成所有從服務(wù)器在短時間內(nèi)全部不可用的情況出現(xiàn)。
Sentinel三大任務(wù)講解
冷備和熱備概念
-
冷備
- 概念:冷備份發(fā)生在數(shù)據(jù)庫已經(jīng)正常關(guān)閉的情況下,當(dāng)正常關(guān)閉時會提供給我們一個完整的數(shù)據(jù)庫
- 優(yōu)點(diǎn):
- 是非常快速的備份方法(只需拷文件)
- 低度維護(hù),高度安全
- 缺點(diǎn):
- 單獨(dú)使用時,只能提供到“某一時間點(diǎn)上”的恢復(fù)
- 再實(shí)施備份的全過程中,數(shù)據(jù)庫必須要作備份而不能作其他工作。也就是說,在冷備份過程中,數(shù)據(jù)庫必須是關(guān)閉狀態(tài)
-
熱備
概念:熱備份是在數(shù)據(jù)庫運(yùn)行的情況下,采用archivelog mode方式備份數(shù)據(jù)庫的方法
-
優(yōu)點(diǎn):
- 備份的時間短
- 備份時數(shù)據(jù)庫仍可使用
- 可達(dá)到秒級恢復(fù)
-
缺點(diǎn)
- 若熱備份不成功,所得結(jié)果不可用于時間點(diǎn)的恢復(fù)
- 因難于維護(hù),所以要非凡仔細(xì)小心
Sentinel三大任務(wù)講解
- 監(jiān)控(Monitoring): Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
- 提醒(Notification): 當(dāng)被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
- 自動故障遷移(Automatic failover): 當(dāng)一個主服務(wù)器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務(wù)器的其中一個從服務(wù)器升級為新的主服務(wù)器, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器; 當(dāng)客戶端試圖連接失效的主服務(wù)器時, 集群也會向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。
Redis高可用Sentinel故障轉(zhuǎn)移原理
Sentinel是如何工作的
-
主觀下線概念:
概念主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實(shí)例對服務(wù)器做出的下線判斷
-
主管下線特點(diǎn):
如果一個服務(wù)器沒有在 master-down-after-milliseconds 選項(xiàng)所指定的時間內(nèi), 對向它發(fā)送 PING 命令的 Sentinel 返回一個有效回復(fù)(valid reply), 那么 Sentinel 就會將這個服務(wù)器標(biāo)記為主觀下線
-
服務(wù)器對 PING 命令的有效回復(fù)可以是以下三種回復(fù)的其中一種:
返回 +PONG 。 返回 -LOADING 錯誤。 返回 -MASTERDOWN 錯誤。
-
客觀下線
-
客觀下線概念:
- 指的是多個 Sentinel 實(shí)例在對同一個服務(wù)器做出 SDOWN 判斷, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服務(wù)器下線判斷。 (一個 Sentinel 可以通過向另一個 Sentinel 發(fā)送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認(rèn)為給定的服務(wù)器已下線。)
-
客觀下線特點(diǎn):
- 從主觀下線狀態(tài)切換到客觀下線狀態(tài)并沒有使用嚴(yán)格的法定人數(shù)算法(strong quorum algorithm), 而是使用了流言協(xié)議: 如果 Sentinel 在給定的時間范圍內(nèi), 從其他 Sentinel 那里接收到了足夠數(shù)量的主服務(wù)器下線報告, 那么 Sentinel 就會將主服務(wù)器的狀態(tài)從主觀下線改變?yōu)榭陀^下線。 如果之后其他 Sentinel 不再報告主服務(wù)器已下線, 那么客觀下線狀態(tài)就會被移除。
-
客觀下線注意點(diǎn):
- 客觀下線條件只適用于主服務(wù)器: 對于任何其他類型的 Redis 實(shí)例, Sentinel 在將它們判斷為下線前不需要進(jìn)行協(xié)商, 所以從服務(wù)器或者其他 Sentinel 永遠(yuǎn)不會達(dá)到客觀下線條件。 只要一個 Sentinel 發(fā)現(xiàn)某個主服務(wù)器進(jìn)入了客觀下線狀態(tài), 這個 Sentinel 就可能會被其他 Sentinel 推選出, 并對失效的主服務(wù)器執(zhí)行自動故障遷移操作。
-
springboot整合sentinel
由sentinel哨兵模式圖解可知,sentinel
類似nginx
進(jìn)行代理服務(wù),所以項(xiàng)目中只需要連接sentinel
即可,無需單獨(dú)配置連接redis
節(jié)點(diǎn)。
- 配置文件
redis:
sentinel:
master: mymaster #mymaster
nodes: 172.16.244.133:26379
- 引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 啟用redis節(jié)點(diǎn),并配置
sentinel.conf
節(jié)點(diǎn)外網(wǎng)IP
protected-mode no
sentinel monitor mymaster 192.168.25.11 6381 1
sentinel known-slave mymaster 127.0.0.1 6380
sentinel known-slave mymaster 192.168.25.11 6379
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 192.168.25.11 6380
- 啟動項(xiàng)目測試,查看各節(jié)點(diǎn)是否主從復(fù)制數(shù)據(jù)
@RequestMapping("/redis/setAndGet")
@ResponseBody
public String setAndGetValue(String name, String value) {
redisTemplate.opsForValue().set(name, value);
return (String) redisTemplate.opsForValue().get(name);
}