1. 程式人生 > 實用技巧 >搭建高可用Redis快取

搭建高可用Redis快取

搭建高可用Redis快取

前言

  • 什麼是Redis

Redis:Remote Dictionary Server(遠端字典伺服器)。是完全開源免費的,用C語言編寫的,遵守BSD協議,是一個高效能的(key/value)分散式記憶體資料庫,基於記憶體執行並支援持久化的NoSQL資料庫,是當前最熱門的NoSQL資料庫之一,也被人們稱為資料結構伺服器。

  • Redis與其他key - value快取產品有以下三個特點:

1、Redis支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。

2、Redis不僅僅支援簡單的key - value型別的資料,同時還提供list、set、zset、hash等資料結構的儲存。

3、Redis支援資料的備份,即master - slave模式的資料備份。

Redis是一個高效能的key-value資料庫,現時越來越多企業與應用使用Redis作為快取伺服器。在Linux伺服器上搭建Redis,怎麼可以不會呢?下面就開始依次搭建:Redis單機伺服器 -> Redis主從複製 -> Redis-Sentinel高可用。逐步搭建出高可用的Redis快取伺服器。

搭建Redis

\1. 下載並解壓

首先從Redis官網下載Redis並解壓,使用的版本是4.0.2。依次執行如下命令:

cd /usr/local/src

wget http://download.redis.io/releases/redis-5.0.2.tar.gz

# tar zxvf redis-5.0.2.tar.gz

如果沒有安裝gcc依賴包,則安裝對應依賴包

yum install -y gcc-c++ tcl

\2. 編譯並安裝

下載並解壓完畢後,則對原始碼包進行編譯安裝,的Redis安裝路徑為/usr/local/redis,可以自行修改語句:make install PREFIX=你想要安裝的路徑

# mkdir /usr/local/redis

cd /usr/local/src/redis-5.0.2/

make install PREFIX=/usr/local/redis

複製Redis相關命令到/usr/sbin目錄下,這樣就可以直接執行這些命令,不用寫全路徑

[root@localhost redis]# cd /usr/local/redis/bin/

sudo cp redis-cli redis-server redis-sentinel /usr/sbin/

\3. 建立Redis配置檔案

安裝完成之後將 Redis 配置檔案拷貝到系統配置目錄/etc/下,redis.conf 是 Redis 的配置檔案,redis.conf 在 Redis 原始碼目錄,port預設 6379。

[root@localhost bin]# cp -rf /usr/local/src/redis-5.0.2/redis.conf /etc/ ##可以把配置檔案裡需要的資訊留下

Redis配置檔案主要引數解析參考

[root@localhost etc]# egrep -v '^$|^#' redis.conf 
bind 127.0.0.1
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
  • 一個覆蓋的方法
#先進行復制.bak檔案,進行備份
[root@localhost etc]# cp -rf /etc/redis.conf{,.bak}
#擷取有用部分,直接覆蓋至原始檔
[root@localhost etc]# egrep -v '^#|^$' /etc/redis.conf.bak >/etc/redis.conf
#引數說明
daemonize no       

 #redis程序是否以守護程序的方式執行,yes為是,no為否(不以守護程序的方式執行會佔用一個終端)

pidfile /var/run/redis.pid    #指定redis程序的PID檔案存放位置

port 6379       #redis程序的埠號

bind 127.0.0.1      #繫結的主機地址

timeout 300      #客戶端閒置多長時間後關閉連線,預設此引數為0即關閉此功能

loglevel verbose     #redis日誌級別,可用的級別有debug.verbose.notice.warning

logfile stdout      #log檔案輸出位置,如果程序以守護程序的方式執行,此處又將輸出檔案設定為stdout的話,就會將日誌資訊輸出到/dev/null裡面去了

databases 16      #設定資料庫的數量,預設為0可以使用select <dbid>命令在連線上指定資料庫id

save <seconds> <changes>   #指定在多少時間內重新整理次數達到多少的時候會將資料同步到資料檔案;

rdbcompression yes     #指定儲存至本地資料庫時是否壓縮檔案,預設為yes即啟用儲存;

dbfilename dump.db     #指定本地資料庫檔名

dir ./        #指定本地資料問就按存放位置;

slaveof <masterip> <masterport> #指定當本機為slave服務時,設定master服務的IP地址及埠,在redis啟動的時候他會自動跟master進行資料同步

masterauth <master-password>  #當master設定了密碼保護時,slave服務連線master的密碼;

requirepass footbared    #設定redis連線密碼,如果配置了連線密碼,客戶端在連線redis是需要通過AUTH<password>命令提供密碼,預設關閉

maxclients 128      #設定同一時間最大客戶連線數,預設無限制;redis可以同時連線的客戶端數為redis程式可以開啟的最大檔案描述符,如果設定 maxclients 0,表示不作限制。當客戶端連線數到達限制時,Redis會關閉新的連線並向客戶端返回max number of clients reached錯誤資訊

maxmemory<bytes>      #指定Redis最大記憶體限制,Redis在啟動時會把資料載入到記憶體中,達到最大記憶體後,Redis會先嚐試清除已到期或即將到期的Key,當此方法處理 後,仍然到達最大記憶體設定,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis新的vm機制,會把Key存放記憶體,Value會存放在swap區

appendonly no      #指定是否在每次更新操作後進行日誌記錄,Redis在預設情況下是非同步的把資料寫入磁碟,如果不開啟,可能會在斷電時導致一段時間內的資料丟失。因為 redis本身同步資料檔案是按上面save條件來同步的,所以有的資料會在一段時間內只存在於記憶體中。預設為no

appendfilename appendonly.aof  #指定跟新日誌檔名預設為appendonly.aof

appendfsync everysec    #指定更新日誌的條件,有三個可選引數no:表示等作業系統進行資料快取同步到磁碟(快),always:表示每次更新操作後手動呼叫fsync()將資料寫到磁碟(慢,安全), everysec:表示每秒同步一次(折衷,預設值);

3.1 設定後端啟動:

由於Redis預設是前端啟動,必須保持在當前的視窗中,如果使用ctrl + c退出,那麼Redis也就退出,不建議使用。

vi /etc/redis.conf

修改Redis配置檔案把舊值daemonize no 改為 新值daemonize yes

3.2 設定訪問:

Redis預設只允許本機訪問,可是有時候我們也需要 Redis 被遠端訪問。

vi /etc/redis.conf

找到 bind 那行配置,預設是: # bind 127.0.0.1

去掉#註釋並改為: bind 0.0.0.0 此設定會變成允許所有遠端訪問。如果想指定限制訪問,可設定對應的IP。

3.3 配置Redis日誌記錄:

找到logfile那行配置,預設是:logfile "",改為logfile /var/log/redis_6379.log

3.4 設定 Redis 請求密碼:

vi /etc/redis.conf

找到預設是被註釋的這一行:# requirepass foobared

去掉註釋,把 foobared 改為你想要設定的密碼,比如我打算設定為:123456,所以我改為:requirepass "123456"

修改之後重啟下服務

/usr/local/redis/bin/redis-server /etc/redis.conf

有了密碼之後,進入客戶端,就得這樣訪問:redis-cli -h 127.0.0.1 -p 6379 -a 123456

\4. Redis常用操作

4.1 啟動

/usr/local/redis/bin/redis-server /etc/redis.conf

4.2 關閉

/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 shutdown

4.3 檢視是否啟動

ps -ef | grep redis

4.4 進入客戶端

redis-cli

4.5 關閉客戶端

redis-cli shutdown

4.6 設定開機自動啟動配置

echo "/usr/local/redis/bin/redis-server /etc/redis.conf" >> /etc/rc.local

4.7 開放防火牆埠

新增規則:iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT

儲存規則:service iptables save

重啟 iptables:service iptables restart

\5. 將Redis註冊為系統服務

在/etc/init.d目錄下新增Redis服務的啟動,暫停和重啟指令碼:

vi /etc/init.d/redis

指令碼內容如下:

#!/bin/sh
#  
# redis - this script starts and stops the redis-server daemon  
#  
# chkconfig:   - 85 15  
# description:  Redis is a persistent key-value database  
# processname: redis-server  
# config:      /usr/local/redis/bin/redis-server
# config:      /etc/redis.conf  
# Source function library.  
. /etc/rc.d/init.d/functions  
# Source networking configuration.  
. /etc/sysconfig/network  
# Check that networking is up.  
[ "$NETWORKING" = "no" ] && exit 0  
redis="/usr/local/redis/bin/redis-server" 
prog=$(basename $redis)  
REDIS_CONF_FILE="/etc/redis.conf" 
[ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis  
lockfile=/var/lock/subsys/redis 
start() {  
   [ -x $redis ] || exit 5  
   [ -f $REDIS_CONF_FILE ] || exit 6  
   echo -n $"Starting $prog: "  
   daemon $redis $REDIS_CONF_FILE  
   retval=$?  
   echo  
   [ $retval -eq 0 ] && touch $lockfile  
   return $retval  
}  
stop() {  
   echo -n $"Stopping $prog: "  
   killproc $prog -QUIT  
   retval=$?  
   echo  
   [ $retval -eq 0 ] && rm -f $lockfile  
   return $retval  
}  
restart() {  
   stop  
   start  
}  
reload() {  
   echo -n $"Reloading $prog: "  
   killproc $redis -HUP  
   RETVAL=$?  
   echo  
}  
force_reload() {  
   restart  
}  
rh_status() {  
   status $prog  
}  
rh_status_q() {  
   rh_status >/dev/null 2>&1  
}  
case "$1" in  
   start)  
       rh_status_q && exit 0  
       $1  
       ;;  
   stop)  
       rh_status_q || exit 0  
       $1  
       ;;  
   restart|configtest)  
       $1  
       ;;  
   reload)  
       rh_status_q || exit 7  
       $1  
       ;;  
   force-reload)  
       force_reload  
       ;;  
   status)  
       rh_status  
       ;;  
   condrestart|try-restart)  
       rh_status_q || exit 0  
   ;;  
   *)  
       echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart| reload|orce-reload}"  
       exit 2  
esac

賦予指令碼許可權

chmod 755 /etc/init.d/redis

啟動並檢視狀態

[root@localhost init.d]# /etc/init.d/redis status
● redis.service - SYSV: Redis is a persistent key-value database
  Loaded: loaded (/etc/rc.d/init.d/redis)
  Active: active (exited) since 三 2020-02-12 05:05:54 CST; 1min 42s ago
    Docs: man:systemd-sysv-generator(8)
 Process: 8572 ExecStart=/etc/rc.d/init.d/redis start (code=exited, status=0/SUCCESS)

2月 12 05:05:53 localhost.localdomain systemd[1]: Starting SYSV: Redis is a persistent key-val.....
2月 12 05:05:54 localhost.localdomain systemd[1]: Started SYSV: Redis is a persistent key-valu...e.
Hint: Some lines were ellipsized, use -l to show in full.

[root@localhost init.d]# /etc/init.d/redis status
● redis.service - SYSV: Redis is a persistent key-value database
  Loaded: loaded (/etc/rc.d/init.d/redis)
  Active: active (exited) since 三 2020-02-12 05:05:54 CST; 1min 42s ago
    Docs: man:systemd-sysv-generator(8)
 Process: 8572 ExecStart=/etc/rc.d/init.d/redis start (code=exited, status=0/SUCCESS)

2月 12 05:05:53 localhost.localdomain systemd[1]: Starting SYSV: Redis is a persistent key-val.....
2月 12 05:05:54 localhost.localdomain systemd[1]: Started SYSV: Redis is a persistent key-valu...e.
Hint: Some lines were ellipsized, use -l to show in full.

設定開機自啟

echo "/usr/local/redis/bin/redis-server /etc/redis.conf" >> /etc/rc.local

啟動、停止和重啟:

service redis start

service redis stop

service redis restart

至此,Redis單機伺服器已搭建完畢,下面我們看看主從架構如何搭建。

以上主伺服器就搭建好了,然後再建立一個虛擬機器進行搭建從伺服器

從主伺服器上覆制redis.tar.gz 包

[root@localhost src]# scp /usr/local/src/redis-5.0.2.tar.gz  192.168.200.120:/root/
The authenticity of host '192.168.200.120 (192.168.200.120)' can't be established.
ECDSA key fingerprint is 26:9d:b1:37:68:e4:45:bd:22:f7:31:d2:59:c7:71:9d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.200.120' (ECDSA) to the list of known hosts.
[email protected]'s password: 
redis-5.0.2.tar.gz                                                100% 1907KB   1.9MB/s   00:00 

從節點的配置檔案

[root@localhost etc]# cat redis.conf
bind 0.0.0.0             #從節點需要更改
protected-mode no        #從節點需要更改
slaveof 192.168.200.160  #從節點需要增加
masterauth 123456        #從節點需要增加
port 6379   #從節點需要增加,這個埠是多少,等會登陸進redis的時候,-p後面加的埠就得是多少,redis-cli -h 127.0.0.1 -p 6379 -a 123456
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes            #從節點需要增加
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes

然後把主節點的 /etc/init.d/redis 複製到 從節點裡

[root@localhost src]# scp  /etc/init.d/redis 192.168.200.120:/etc/init.d/redis
[email protected]'s password: 
redis                                                             100% 1944     1.9KB/s   00:00  

之後進行啟動從節點

[root@localhost ~]# ps -ef |grep redis
root      38351   3688  0 23:58 pts/1    00:00:00 grep --color=auto redis

[root@localhost ~]# /usr/local/redis/bin/redis-server /etc/redis.conf
38361:C 28 Dec 2019 23:58:58.200 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
38361:C 28 Dec 2019 23:58:58.200 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=38361, just started
38361:C 28 Dec 2019 23:58:58.200 # Configuration loaded

[root@localhost ~]# /etc/init.d/redis status
Unit redis.service could not be found.

[root@localhost ~]# ps -ef |grep redis                               
root      38362      1  0 23:58 ?        00:00:00 /usr/local/redis/bin/redis-server 0.0.0.0:6380
root      38379   3688  0 23:59 pts/1    00:00:00 grep --color=auto redis

[root@localhost ~]# /etc/init.d/redis status
Unit redis.service could not be found.

[root@localhost ~]# /etc/init.d/redis stop
Reloading systemd:                                         [  確定  ]
Stopping redis (via systemctl):                            [  確定  ]

[root@localhost ~]# /etc/init.d/redis status
● redis.service - SYSV: Redis is a persistent key-value database
   Loaded: loaded (/etc/rc.d/init.d/redis; bad; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)
     
[root@localhost ~]# /etc/init.d/redis start
Starting redis (via systemctl):                            [  確定  ]

[root@localhost ~]# /etc/init.d/redis status
● redis.service - SYSV: Redis is a persistent key-value database
   Loaded: loaded (/etc/rc.d/init.d/redis; bad; vendor preset: disabled)
   Active: active (exited) since 六 2019-12-28 23:59:54 CST; 49s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 38448 ExecStart=/etc/rc.d/init.d/redis start (code=exited, status=0/SUCCESS)

12月 28 23:59:54 localhost.localdomain systemd[1]: Starting SYSV: Redis is a persistent key-va.....
12月 28 23:59:54 localhost.localdomain systemd[1]: Started SYSV: Redis is a persistent key-val...e.
Hint: Some lines were ellipsized, use -l to show in full.


#修改配置要重啟服務
[root@localhost ~]# /etc/init.d/redis restart               

檢視

#檢視主節點
[root@localhost etc]# redis-cli -h 127.0.0.1 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.200.120,port=6380,state=online,offset=336,lag=1
master_replid:f34e55b755b64c119beed991cf0031f7aac63d60
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:336
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:336

#檢視從節點
[root@localhost ~]# redis-cli -h 127.0.0.1 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> INFO replication
# Replication
role:slave
master_host:192.168.200.160
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:546
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f34e55b755b64c119beed991cf0031f7aac63d60
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:546
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:449
repl_backlog_histlen:98

搭建Redis主從架構

\1. redis-server說明

192.168.100.30:6379 主

192.168.100.60:6379 從

\2. Redis主從架構配置

編輯從機的 Redis 配置檔案,找到 210 行(大概),預設這一行應該是註釋的: # slaveof

我們需要去掉該註釋,並且填寫我們自己的主機的 IP 和 埠,比如:slaveof 192.168.100.30 6379,如果主機設定了密碼,還需要找到masterauth 這一行,去掉註釋,改為masterauth 主機密碼。

配置完成後重啟從機Redis 服務

重啟完之後,進入主機的 redis-cli 狀態下redis-cli -h 127.0.0.1 -p 6379 -a 123456,輸入:INFO replication 可以查詢到當前主機的 Redis處於什麼角色,有哪些從機已經連上主機。

主機資訊192.168.100.30

# Replication

role:master

connected_slaves:1

slave0:ip=192.168.100.60,port=6379,state=online,offset=28,lag=1

master_replid:625ae9f362643da5337835beaeabfdca426198c7

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:28

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:28

從機資訊192.168.100.60

# Replication

role:slave

master_host:192.168.100.30

master_port:6379

master_link_status:up

master_last_io_seconds_ago:3

master_sync_in_progress:0

slave_repl_offset:210

slave_priority:100

slave_read_only:1

connected_slaves:0

master_replid:625ae9f362643da5337835beaeabfdca426198c7

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:210

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:210

此時已經完成了主從配置,我們可以測試下: 我們進入主機的 redis-cli 狀態,然後 set 某個值,比如:set myblog YouMeek.com

我們切換進入從機的 redis-cli 的狀態下,獲取剛剛設定的值看是否存在:get myblog,此時,我們可以發現是可以獲取到值的。

\3. Redis主從架構總結

需要注意的是:從庫不具備寫入資料能力,不然會報錯。 從庫只有只讀能力。

主從架構的優點:除了減少主庫連線的壓力,還有可以關掉主庫的持久化功能,把持久化的功能交給從庫進行處理。

第一個從庫配置的資訊是連上主庫,後面的第二個從庫配置的連線資訊是連上第一個從庫, 假如還有第三個從庫的話,我們可以把第三個從庫的配置資訊連上第二個從庫上,以此類推。

Redis Sentinel高可用架構搭建

\1. 自動故障轉移

雖然使用主從架構配置Redis做了備份,看上去很完美。但由於Redis目前只支援主從複製備份(不支援主主複製),當主Redis掛了,從Redis只能提供讀服務,無法提供寫服務。所以,還得想辦法,當主Redis掛了,讓從Redis升級成為主Redis。

這就需要自動故障轉移,Redis Sentinel帶有這個功能,當一個主Redis不能提供服務時,Redis Sentinel可以將一個從Redis升級為主Redis,並對其他從Redis進行配置,讓它們使用新的主Redis進行復製備份。

注意:搭建Redis Sentinel推薦至少3臺伺服器,但由於偷懶,下面用例只用了2臺伺服器。

Redis Sentinel的主要功能如下:

監控:哨兵不斷的檢查master和slave是否正常的執行。

通知:當監控的某臺Redis例項發生問題時,可以通過API通知系統管理員和其他的應用程式。

自動故障轉移:如果一個master不正常運行了,哨兵可以啟動一個故障轉移程序,將一個slave升級成為master,其他的slave被重新配置使用新的master,並且應用程式使用Redis服務端通知的新地址。

配置提供者:哨兵作為Redis客戶端發現的權威來源:客戶端連線到哨兵請求當前可靠的master的地址。如果發生故障,哨兵將報告新地址。

預設情況下,每個Sentinel節點會以每秒一次的頻率對Redis節點和其它的Sentinel節點發送PING命令,並通過節點的回覆來判斷節點是否線上。

如果在down-after-millisecondes毫秒內,沒有收到有效的回覆,則會判定該節點為主觀下線。

如果該節點為master,則該Sentinel節點會通過sentinel is-master-down-by-addr命令向其它sentinel節點詢問對該節點的判斷,如果超過個數的節點判定master不可達,則該sentinel節點會將master判斷為客觀下線。

這個時候,各個Sentinel會進行協商,選舉出一個領頭Sentinel,由該領頭Sentinel對master節點進行故障轉移操作。

故障轉移包含如下三個操作:

在所有的slave伺服器中,挑選出一個slave,並將其轉換為master。

讓其它slave伺服器,改為複製新的master。

將舊master設定為新master的slave,這樣,當舊的master重新上線時,它會成為新master的slave。

\2. 搭建Redis Sentinel高可用架構

這裡使用兩臺伺服器,每臺伺服器上開啟一個redis-server和redis-sentinel服務。

redis-server說明

192.168.100.30:6379 主

192.168.100.60:6379 從

redis-sentinel說明

192.168.100.30:26379

192.168.100.60:26379

2.1 建立Redis配置檔案

如果要做自動故障轉移,則建議所有的redis.conf都設定masterauth,因為自動故障只會重寫主從關係,即slaveof,不會自動寫入masterauth。如果Redis原本沒有設定密碼,則可以忽略。

Redis程式上面已經安裝過了,我們只需增加redis-sentinel的相關配置即可,將 redis-sentinel的配置檔案拷貝到系統配置目錄/etc/下,sentinel.conf 是 redis-sentinel的配置檔案,sentinel.conf 在 Redis 原始碼目錄。

cp /usr/local/redis-4.0.2/sentinel.conf /etc/

修改sentinel.conf配置檔案內容如下:

vi /etc/sentinel.conf

protected-mode no

sentinel monitor mymaster 192.168.100.30 6379 2

# redis在搭建時設定了密碼,所以要進行密碼配置

sentinel auth-pass mymaster “123456“

#5秒內mymaster沒有響應,就認為SDOWN

sentinel down-after-milliseconds mymaster 5000

sentinel failover-timeout mymaster 15000

在配置最後加上

logfile /var/log/sentinel.log

pidfile /var/run/sentinel.pid

daemonize yes

配置檔案說明:

1.port :當前Sentinel服務執行的埠

2.dir : Sentinel服務執行時使用的臨時資料夾

3.sentinel monitor master001 192.168.110.10163792:Sentinel去監視一個名為master001的主redis例項,這個主例項的IP地址為本機地址192.168.110.101,埠號為6379,而將這個主例項判斷為失效至少需要2個 Sentinel程序的同意,只要同意Sentinel的數量不達標,自動failover就不會執行

4.sentinel down-after-milliseconds master001 30000:指定了Sentinel認為Redis例項已經失效所需的毫秒數。當例項超過該時間沒有返回PING,或者直接返回錯誤,那麼Sentinel將這個例項標記為主觀下線。只有一個 Sentinel程序將例項標記為主觀下線並不一定會引起例項的自動故障遷移:只有在足夠數量的Sentinel都將一個例項標記為主觀下線之後,例項才會被標記為客觀下線,這時自動故障遷移才會執行

5.sentinel parallel-syncs master001 1:指定了在執行故障轉移時,最多可以有多少個從Redis例項在同步新的主例項,在從Redis例項較多的情況下這個數字越小,同步的時間越長,完成故障轉移所需的時間就越長

6.sentinel failover-timeout master001 180000:如果在該時間(ms)內未能完成failover操作,則認為該failover失敗

7.sentinel notification-script :指定sentinel檢測到該監控的redis例項指向的例項異常時,呼叫的報警指令碼。該配置項可選,但是很常用

2.2 開放防火牆埠

新增規則:iptables -I INPUT -p tcp -m tcp --dport 26379 -j ACCEPT

儲存規則:service iptables save

重啟 iptables:service iptables restart

2.3 啟動redis-sentinel

redis-sentinel /etc/sentinel.conf

在任意一臺機子均可檢視到相關服務資訊

redis-cli -h 127.0.0.1 -p 26379

INFO 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=192.168.100.30:6379,slaves=1,sentinels=2

\3. 自動故障轉移測試

3.1 停止主Redis

redis-cli -h 192.168.100.30 -p 6379 -a 123456 shutdown

3.2 檢視redis-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=192.168.100.60:6379,slaves=1,sentinels=2

發現從庫提升為主庫。

3.3 注意事項

如果停掉master後,Sentinel顯示足夠數量的sdown後,沒有出現odown或try-failover,則檢查密碼等配置是否正確

如果停掉master後,試圖切換的時候,發現日誌出現 failover-abort-not-elected,則分2種情況分別解決:

如果Redis例項沒有配置

protected-mode yes

bind 192.168.100.30

則在Sentinel 配置檔案加上protected-mode no即可

如果Redis例項有配置

protected-mode yes

bind 192.168.100.30

則在Sentinel配置檔案加上

protected-mode yes

bind 192.168.100.30

至此,redis的高可用方案已經搭建完成。