閱讀目錄:
關于 Redis 的概念
關于 Redis Sentinel 的概念
搭建 Redis Server(master)
搭建 Redis Server(slave)
搭建 Redis Sentinel
Redis Sentinel 故障轉移測試
前幾天,看到了一篇文章:高可用 Redis 服務架構分析與搭建,思路講的非常好,但是沒有搭建的過程,這篇文章就記錄下 Redis Sentinel 高可用服務架構搭建的過程。
搭建方案,就按照作者的第四種方案:

1. 關于 Redis 的概念
Redis 是完全開源免費的,遵守 BSD 協(xié)議,是一個高性能的 key-value 數(shù)據(jù)庫。
Redis 與其他 key-value 緩存產品有以下三個特點:
Redis 支持數(shù)據(jù)的持久化,可以將內存中的數(shù)據(jù)保存在磁盤中,重啟的時候可以再次加載進行使用。
Redis 不僅僅支持簡單的 key-value 類型的數(shù)據(jù),同時還提供 list,set,zset,hash 等數(shù)據(jù)結構的存儲。
Redis 支持數(shù)據(jù)的備份,即 master-slave 模式的數(shù)據(jù)備份。
Redis 的優(yōu)勢:
性能極高?– Redis 能讀的速度是 110000 次/s,寫的速度是 81000 次/s。
豐富的數(shù)據(jù)類型?– Redis 支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。
原子?– Redis 的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個操作是原子性的。多個操作也支持事務,即原子性,通過 MULTI 和 EXEC 指令包起來。
豐富的特性?– Redis 還支持 publish/subscribe, 通知, key 過期等等特性。
以上內容摘自:http://www.runoob.com/redis/redis-intro.html
2. 關于 Redis Sentinel 的概念
Redis Sentinel(譯為“哨兵”)是 Redis 官方推薦的高可用性(HA)解決方案,當用 Redis 做 Master-slave 的高可用方案時,假如 master 宕機了,Redis 本身(包括它的很多客戶端)都沒有實現(xiàn)自動進行主備切換,而 Redis-sentinel 本身也是一個獨立運行的進程,它能監(jiān)控多個 master-slave 集群,發(fā)現(xiàn) master 宕機后能進行自動切換。
Redis Sentinel 系統(tǒng)用于管理多個 Redis 服務器(instance),該系統(tǒng)執(zhí)行以下三個任務:
監(jiān)控(Monitoring):Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
提醒(Notification):當被監(jiān)控的某個 Redis 服務器出現(xiàn)問題時,Sentinel 可以通過 API 向管理員或者其他應用程序發(fā)送通知。
自動故障遷移(Automatic failover):當一個主服務器不能正常工作時,Sentinel 會開始一次自動故障遷移操作,它會將失效主服務器的其中一個從服務器升級為新的主服務器,并讓失效主服務器的其他從服務器改為復制新的主服務器;當客戶端試圖連接失效的主服務器時,集群也會向客戶端返回新主服務器的地址,使得集群可以使用新主服務器代替失效服務器。
Redis Sentinel 是一個分布式系統(tǒng),你可以在一個架構中運行多個 Sentinel 進程(progress),這些進程使用流言協(xié)議(gossip protocols)來接收關于主服務器是否下線的信息,并使用投票協(xié)議(agreement protocols)來決定是否執(zhí)行自動故障遷移,以及選擇哪個從服務器作為新的主服務器。
一個 Sentinel 進程可以與其他多個 Sentinel 進程進行連接,每個 Sentinel 進程之間可以互相檢查對方的可用性,并進行信息交換。
以上內容摘自:http://redisdoc.com/topic/sentinel.html
3. 搭建 Redis Server(master)
我們就按照上面的架構圖進行搭建,大概三臺服務器(防火墻關閉):
10.9.10.154 master? redis-server redis-sentinel
10.9.10.152 slave? ? redis-server redis-sentinel
10.9.10.215 redis-sentinel
先從?redis.io/releases,下載最新版本的 Redis(需要進行編譯)。
$ wget http://download.redis.io/releases/redis-4.0.8.tar.gz$ tar xzf redis-4.0.8.tar.gz$cdredis-4.0.8$ ls00-RELEASENOTES? COPYING? ? Makefile? redis.conf? ? ? runtest-sentinel? testsBUGS? ? ? ? ? ? INSTALL? ? README.md? runtest? ? ? ? ? sentinel.conf? ? utilsCONTRIBUTING? ? MANIFESTO? deps? ? ? runtest-cluster? src$cdsrc$ make install? ? CC Makefile.dep? ? INSTALL redis-sentinel? ? CC redis-cli.o? ? LINK redis-cli? ? CC redis-benchmark.o? ? LINK redis-benchmark? ? INSTALL redis-check-rdbHint: It's a good idea to run 'maketest' ;)
? ? INSTALL install
? ? INSTALL install
? ? INSTALL install
? ? INSTALL install
? ? INSTALL install
編譯成功后,會在redis-4.0.8/src目錄下,生成redis-server和redis-sentinel可執(zhí)行文件。
然后,我們在 master 節(jié)點(10.9.10.154)上,創(chuàng)建redis-4.0.8/redis-master.conf配置文件,示例配置:
# 使用守護進程模式daemonize yes# 非保護模式,可以外網訪問protected-mode no# 端口號port 6379# 綁定ip,本機的ipbind10.9.10.154# 學習開發(fā),使用最大日志級別,能夠看到最多的日志信息loglevel debug# 指定日志文件路徑,沒有文件的話,先創(chuàng)建logfile /home/ubuntu/redis/redis-4.0.8/redis-server.log# 客戶端訪問,需要密碼連接requirepass 123456
然后啟動 master:
$ src/redis-server redis-master.config$ cat redis-server.log8517:C 28 Feb 06:10:38.345# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo8517:C 28 Feb 06:10:38.345# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=8517, just started8517:C 28 Feb 06:10:38.345# Configuration loaded8518:M 28 Feb 06:10:38.349 * Increased maximum number of open files to 10032 (it was originallysetto 1024).8518:M 28 Feb 06:10:38.352 * Running mode=standalone, port=6379.8518:M 28 Feb 06:10:38.352# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.8518:M 28 Feb 06:10:38.352# Server initialized8518:M 28 Feb 06:10:38.352# WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.8518:M 28 Feb 06:10:38.352 * Ready to accept connections8518:M 28 Feb 06:10:38.352 - 0 clients connected (0 slaves), 765776 bytesinuse
查看 Redis 的狀態(tài):
$ redis-cli -h 10.9.10.154 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:masterconnected_slaves:0master_replid:7f90fb4ba0c2c450b184a348f23f31d9c40b010dmaster_replid2:0000000000000000000000000000000000000000master_repl_offset:0second_repl_offset:-1repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:010.9.10.154:6379> pingPONG
添加和獲取鍵值測試:
10.9.10.154:6379>settesthelloOK10.9.10.154:6379> gettest"hello"
Redis 常用命令:
啟動服務:service redis start
停止服務:service redis stop
重啟服務:service ngredisnx restart
如果沒有配置為 Service 服務,可以用下面命令關閉 Redis:
$ src/redis-cli shutdown或者$ ps aux | grep redis$kill111
4. 搭建 Redis Server(slave)
slave 節(jié)點和 master 節(jié)點搭建差不多,只不過redis-slave.conf配置文件,有些不同:
# 使用守護進程模式daemonize yes# 非保護模式,可以外網訪問protected-mode no# 端口號port 6379# 綁定ip,本機的ipbind10.9.10.152# 指定 master 的 ip 地址和端口slaveof 10.9.10.154 6379# 學習開發(fā),使用最大日志級別,能夠看到最多的日志信息loglevel debug# 指定日志文件路徑,沒有文件的話,先創(chuàng)建logfile /home/ubuntu/redis/redis-4.0.8/redis-server.log# 設置訪問 master 的密碼masterauth 123456
然后啟動 slave:
$ src/redis-server redis-slave.conf$ cat redis-server.log7307:C 28 Feb 06:11:00.987# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7307:C 28 Feb 06:11:00.987# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=7307, just started7307:C 28 Feb 06:11:00.987# Configuration loaded7308:S 28 Feb 06:11:00.989 * Increased maximum number of open files to 10032 (it was originallysetto 1024).7308:S 28 Feb 06:11:00.989 * Running mode=standalone, port=6379.7308:S 28 Feb 06:11:00.990# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.7308:S 28 Feb 06:11:00.990# Server initialized7308:S 28 Feb 06:11:00.990# WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.7308:S 28 Feb 06:11:00.990 * Ready to accept connections7308:S 28 Feb 06:11:00.990 - 0 clients connected (0 slaves), 765736 bytesinuse7308:S 28 Feb 06:11:00.990 * Connecting to MASTER 10.9.10.154:63797308:S 28 Feb 06:11:00.990 * MASTER <-> SLAVE sync started7308:S 28 Feb 06:11:00.990 * Non blocking connectforSYNC fired the event.7308:S 28 Feb 06:11:00.991 * Master replied to PING, replication cancontinue...7308:S 28 Feb 06:11:00.993 * Partial resynchronization not possible (no cached master)7308:S 28 Feb 06:11:00.995 * Full resync from master: 55b29a9f06ffb89f96106287ce95ddfbdeccb986:0
查看 Redis 的狀態(tài):
$ redis-cli -h 10.9.10.152 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:slavemaster_host:10.9.10.154master_port:6379master_link_status:upmaster_last_io_seconds_ago:10master_sync_in_progress:0slave_repl_offset:280slave_priority:100slave_read_only:1connected_slaves:0master_replid:55b29a9f06ffb89f96106287ce95ddfbdeccb986master_replid2:0000000000000000000000000000000000000000master_repl_offset:280second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:28010.9.10.152:6379> pingPONG
然后我們再查看下 master 的狀態(tài)(更新了connected_slaves的信息):
$ redis-cli -h 10.9.10.154 -p 6379 -a 12345610.9.10.154:6379> INFO replication# Replicationrole:masterconnected_slaves:1slave0:ip=10.9.10.152,port=6379,state=online,offset=28,lag=1master_replid:55b29a9f06ffb89f96106287ce95ddfbdeccb986master_replid2:0000000000000000000000000000000000000000master_repl_offset:28second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:28
另外,你可以測試下,在 master 上添加一個 key 和 value,然后就可以在 salve 上獲取這個對應的 key 的 value。
5. 搭建 Redis Sentinel
接著,我們分別在三臺服務器上,配置 Redis Sentinel,創(chuàng)建redis-4.0.8/sentinel-my.conf配置文件,示例配置(記得更改不同的bind ip):
port 26379bind10.9.10.154daemonize yeslogfile /home/ubuntu/redis/redis-4.0.8/redis-sentinel.logsentinel monitor manager1 10.9.10.154 6379 2sentinel auth-pass manager1 123456sentinel down-after-milliseconds manager1 60000sentinel failover-timeout manager1 180000sentinel parallel-syncs manager1 1
這四行配置為一組,因為我們只有一個 master 節(jié)點,所以只配置了一個 master,可以配置多個 master,不用配置 slave 的信息,因為 slave 能夠被自動檢測到(master 節(jié)點會有關于 slave 的消息)
第一行配置指示 Sentinel 去監(jiān)視一個名為manager1的主服務器,這個主服務器的 IP 地址為10.9.10.154,端口號為 6379,而將這個主服務器判斷為失效至少需要 2 個 Sentinel 同意(只要同意 Sentinel 的數(shù)量不達標,自動故障遷移就不會執(zhí)行)。
其他選項的基本格式如下:
sentinel <選項的名字> <主服務器的名字> <選項的值>
選項說明:
auth-pass:選項指定了 master 的連接密碼。
down-after-milliseconds:選項指定了 Sentinel 認為服務器已經斷線所需的毫秒數(shù)。
failover-timeout:如果在該時間(ms)內未能完成 failover 操作,則認為該 failover 失敗。
parallel-syncs:選項指定了在執(zhí)行故障轉移時,最多可以有多少個從服務器同時對新的主服務器進行同步,這個數(shù)字越小,完成故障轉移所需的時間就越長。
接著,我們啟動 Redis Sentinel(默認端口 26379):
$ src/redis-server sentinel-my.conf --sentinel或者$ src/redis-sentinel sentinel-my.conf$ cat redis-sentinel.log5716:X 28 Feb 03:04:17.407# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo5716:X 28 Feb 03:04:17.407# Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=5716, just started5716:X 28 Feb 03:04:17.407# Configuration loaded5716:X 28 Feb 03:04:17.408 * Increased maximum number of open files to 10032 (it was originallysetto 1024).? ? ? ? ? ? ? ? _._? ? ? ? ? _.-``__''-._? ? ? _.-``? ? `.? `_.''-._? ? ? ? ? Redis 4.0.8 (00000000/0) 64 bit? .-`` .-```.? ```\/? ? _.,_''-._ ('? ? ? ,? ? ? .-`? | `,? ? )? ? Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'|? ? Port: 26379
|? ? `-._? `._? ? /? ? _.-'|? ? PID: 5716? `-._? ? `-._? `-./? _.-'? ? _.-'|`-._`-._? ? `-.__.-'? ? _.-'_.-'|
|? ? `-._`-._? ? ? ? _.-'_.-'? ? |? ? ? ? ? http://redis.io
? `-._? ? `-._`-.__.-'_.-'? ? _.-'|`-._`-._? ? `-.__.-'? ? _.-'_.-'|
|? ? `-._`-._? ? ? ? _.-'_.-'? ? |
? `-._? ? `-._`-.__.-'_.-'? ? _.-'`-._? ? `-.__.-'? ? _.-'`-._? ? ? ? _.-'
? ? ? ? ? ? ? `-.__.-'5716:X 28 Feb 03:04:17.410# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.5716:X 28 Feb 03:04:17.412# Sentinel ID is 493852dd16017dccdf7b169a256ce7eea2719aff5716:X 28 Feb 03:04:17.412# +monitor master manager1 10.9.10.154 6379 quorum 2
當有其他服務器啟動 Redis Sentinel 的時候,會有這樣的日志(Redis Sentinel 是會相互通信的):
5716:X28Feb03:18:46.404#-tilt#tiltmodeexited5716:X28Feb03:19:43.959* +sentinelsentinel55ebce153ac69c908800bc14beff24725fc5a72110.9.10.15226379 @ manager110.9.10.1546379
連接測試(測試三臺服務器):
$ redis-cli -h 10.9.10.154 -p 26379
10.9.10.154:6379> ping
PONG
$ redis-cli -h 10.9.10.152 -p 26379
10.9.10.152:6379> ping
PONG
$ redis-cli -h 10.9.10.155 -p 26379
10.9.10.155:6379> ping
PONG
其他常用命令:
PING?- 這個命令簡單的返回 PONE。
SENTINEL masters?- 展示監(jiān)控的 master 清單和它們的狀態(tài)。
SENTINEL master [master name]?- 展示指定 master 的狀態(tài)和信息。
SENTINEL slaves [master name]?- 展示 master 的 slave 清單和它們的狀態(tài)。
SENTINEL sentinels [master name]?- 展示 master 的 sentinel 實例的清單和它們的狀態(tài)。
SENTINEL get-master-addr-by-name [master name]?- 返回 master 的 IP 和端口。如果故障轉移在處理中或成功終止,返回晉升的 slave 的 IP 和端口。
SENTINEL reset [pattern]?- 這個命令將重置所有匹配名字的 masters。參數(shù)是 blog 風格的。重置的過程清空 master 的所有狀態(tài),并移除已經發(fā)現(xiàn)和關聯(lián) master 的所有 slave 和 sentinel。
SENTINEL failover [master name]?- 如果 master 不可到達,強制執(zhí)行一個故障轉移,而不征求其他 Sentinel 的同意。
SENTINEL ckquorum [master name]?- 檢查當前的 Sentinel 配置是否能夠到達故障轉移需要的法定人數(shù),并且需要授權故障轉移的多數(shù)。這個命令應該用于監(jiān)控系統(tǒng)檢查部署是否正確。
SENTINEL flushconfig?- 強制 Sentinel 在磁盤上重寫它的配置,包括當前的 Sentinel 狀態(tài)。通常 Sentinel 每次重寫配置改變它的狀態(tài)。然而有時由于操作錯誤、硬盤故障、包升級腳本或配置管理器可能導致配置文件丟失。在這種情況下收到強制 Sentinel 重寫配置文件。這個命令即使上面的配置文件完全不見了。
6. Redis Sentinel 故障轉移測試
我們的計劃是,將 master 的 Redis 服務停掉,看看 Redis Sentinel 是如何操作的。
首先,我們先查看下目前 master 節(jié)點的信息(記住 IP):
$ redis-cli -h 10.9.10.154 -p 637910.9.10.154:26379> SENTINEL get-master-addr-by-name manager11)"10.9.10.154"2)"6379"
然后執(zhí)行下面命令(強制 Redis Server 休眠 120 秒):
$ redis-cli -h 10.9.10.154 -p 6379 -a 123456 DEBUG sleep 120
然后我們再查看下 master 節(jié)點的信息:
$ redis-cli -h 10.9.10.154 -p 637910.9.10.154:26379> SENTINEL get-master-addr-by-name manager11)"10.9.10.152"2)"6379"
發(fā)現(xiàn) IP 已經變成了此前 salve 節(jié)點的,也就是說10.9.10.152變成了 master,然后我們查看下當前 master 的信息:
$ redis-cli -h 10.9.10.152 -p 6379 -a 12345610.9.10.152:6379> INFO replication# Replicationrole:masterconnected_slaves:1slave0:ip=10.9.10.154,port=6379,state=online,offset=1270535,lag=0master_replid:8b033de60b4be410a1706ff6b27b52b97bcc2981master_replid2:e56e893b96e7df8fda00ebcacf1d4b24c9499c4amaster_repl_offset:1270535second_repl_offset:1208143repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:221960repl_backlog_histlen:1048576
slave0:ip=10.9.10.154,port=6379表示此前的 master,已變?yōu)楝F(xiàn)在的 salve。
整個過程,我們可以查看 Redis Sentinel 的日志:
20153:X 28 Feb 09:13:51.023# +sdown master manager1 10.9.10.154 637920153:X 28 Feb 09:13:51.243# +new-epoch 120153:X 28 Feb 09:13:51.244# +vote-for-leader c14ac16f2a43c311c663677b7e056e744e2e2852 120153:X 28 Feb 09:13:52.102# +odown master manager1 10.9.10.154 6379 #quorum 2/220153:X 28 Feb 09:13:52.102# Next failover delay: I will not start a failover before Wed Feb 28 09:19:51 201820153:X 28 Feb 09:13:52.365# +config-update-from sentinel c14ac16f2a43c311c663677b7e056e744e2e2852 10.9.10.152 26379 @ manager1 10.9.10.154 637920153:X 28 Feb 09:13:52.365# +switch-master manager1 10.9.10.154 6379 10.9.10.152 637920153:X 28 Feb 09:13:52.365 * +slave slave 10.9.10.154:6379 10.9.10.154 6379 @ manager1 10.9.10.152 637920153:X 28 Feb 09:15:00.797 * +convert-to-slave slave 10.9.10.154:6379 10.9.10.154 6379 @ manager1 10.9.10.152 6379
翻譯一下就是:
每個 Sentinel 發(fā)現(xiàn)了主節(jié)點掛掉了并有一個 +sdown 事件
這個事件稍候升級到 +odown,意味著大多數(shù) Sentinel 已經同意了主節(jié)點是不可達的。
Sentinels 開始投票一個 Sentinel 開始并嘗試故障轉移
故障轉移開始
另外,需要注意的是,Redis Sentinel 并不是提供對外服務的地址,它只是管理 Redis 主備切換的監(jiān)測工具,所以,對外 Client 提供的地址,仍是 Redis Server 的地址(包含 salve),當然,也可以像提供負載均衡(SLB)或者虛擬IP(Virtual IP,VIP),進行統(tǒng)一地址的訪問。
參考資料:
Redis 哨兵-實現(xiàn) Redis 高可用(推薦)
Sentinel(推薦)