Redis 哨兵集羣

哨兵集羣介紹

Redis的哨兵(sentinel) 常用於管理多個 Redis 服務器,它主要會執行以下三個任務:
        監控(Monitoring):哨兵(sentinel) 會不斷地檢查你的Master和Slave是否運作正常。
        提醒(Notification):當被監控的某個 Redis出現問題時, 哨兵(sentinel) 可以通過 API 向管理員或者其他應用程序發送通知。

       自動故障遷移(Automatic failover):當一個Master不能正常工作時,哨兵(sentinel) 會開始一次自動故障遷移操作,它會將 Master 故障後的其中一個 Slave 升級爲新的 Master,並讓 Master 故障後的其他 Slave 改爲複製新的Master;當客戶端試圖連接故障的 Master 時,集羣也會向客戶端返回新Master的地址,使得集羣可以使用新的 Master 代替故障的 Master。

       哨兵(sentinel) 是一個分佈式系統,你可以在一個架構中運行多個哨兵(sentinel) 進程,這些進程使用流言協議(gossipprotocols)來接收關於 Master 是否下線的信息,並使用投票協議(agreement protocols)來決定是否執行自動故障遷移,以及選擇哪個 Slave 作爲新的 Master。
        每個哨兵(sentinel) 會向其它哨兵(sentinel)、master、slave定時發送消息,以確認對方是否“活”着,如果發現對方在指定時間(可配置)內未迴應,則暫時認爲對方已掛(所謂的”主觀認爲宕機” Subjective Down,簡稱sdown)。
        若“哨兵羣”中的多數 sentinel ,報告某一 Master 沒響應,系統才認爲該 Master "徹底死亡"(即:客觀上的真正down機,Objective Down,簡稱odown),通過一定的vote算法,從剩下的slave節點中,選一臺提升爲master,然後自動修改相關配置。
        雖然哨兵(sentinel) 釋出爲一個單獨的可執行文件 redis-sentinel ,但實際上它只是一個運行在特殊模式下的 Redis 服務器,你可以在啓動一個普通 Redis 服務器時通過給定 --sentinel 選項來啓動哨兵(sentinel)。

服務器規劃


Redis安裝

下載官方安裝包:https://redis.io/download

1、Redis支持包安裝

由於 Redis 是由 C 語言編寫,所繫統需要安裝 gcc
[root@rocketmq-nameserver1 ~]# yum install -y gcc automake autoconf libtool make
2、解壓下載的 Redis 安裝包,並進入目錄,進行編譯,分別在3臺服務器上操作。
[root@rocketmq-nameserver1 redis-5.0.4]# make install
此過程大概需要2分鐘左右,耐心等待。。。。。。
說明:如果在編譯過程中出現  該錯誤,則需要在編譯的時候使用此命令 make MALLOC=libc install 可解決。
3、複製 Redis 命令文件到 /usr/bin 目錄
[root@rocketmq-nameserver1 redis-5.0.4]# cd src/
[root@rocketmq-nameserver1 src]# cp redis-cli redis-sentinel redis-server /usr/bin

redis配置

過濾 Redis 配置文件 redis.conf

[root@rocketmq-nameserver1 redis-5.0.4]# grep -Ev "^#|^$" redis.conf

bind 192.168.2.177
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /wdata/redis/data/redis.pid
loglevel notice
logfile "/wdata/redis/logs/redis.log"
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 /wdata/redis
replicaof 192.168.2.177 6379
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

我們對 Redis 配置文件的修改,大概只需要修改上面標紅的部分,其他選項可根據自己的需要修改。其中下面兩項爲

daemonize yes:設置 Redis 啓動時在後臺運行

replicaof 192.168.2.177 6379:設置集羣 Master 服務器地址和端口,注意,在 192.168.2.177 主Redis 服務器上將該項註釋

將修改好的配置文件複製到其他兩臺服務器

for i in 178 180; do scp redis.conf [email protected].$i:/wdata/redis/config; done

哨兵配置

過濾 sentinel 配置文件 sentinel.conf

[root@rocketmq-nameserver1 redis-5.0.4]# grep -Ev "^#|^$" sentinel.conf

bind 192.168.2.177

port 26379
daemonize yes
pidfile /wdata/redis-sentinel.pid
logfile "/wdata/redis/logs/sentinel.log"
dir /wdata/redis

sentinel monitor mymaster 192.168.2.177 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

一般,我們只需要修改上面標紅的部分,其他選項根據實際需要進行修改,其中下面意向的含義爲

sentinel monitor mymaster 192.168.2.177 6379 2:設置哨兵監控的主服務器爲 192.168.2.177,端口爲6379,2 表示如果同時有 2 個哨兵都認爲該主服務器不可訪問時,則進行故障轉移。

將修改好的 sentinel 配置文件分發到其他兩臺服務器。

for i in 178 180; do scp sentinel.conf [email protected].$i:/wdata/redis/config; done

啓動Redis

在三臺服務器上分別執行

[root@rocketmq-nameserver1 ~]# service redis start

查看 Redis 是否啓動成功

[root@rocketmq-nameserver1 ~]# ps -ef | grep redis

或者

[root@rocketmq-nameserver1 ~]# service redis status

啓動哨兵

在三臺服務器上分別執行

[root@rocketmq-nameserver1 ~]# service sentinel start

查看哨兵啓動是否成功

[root@rocketmq-nameserver1 ~]# ps -ef | grep sentinel

或者

[root@rocketmq-nameserver1 ~]# service sentinel status

查看哨兵集羣狀態

我們的 Redis 服務和哨兵(sentinel)服務均已成功啓動,接下來我們需要驗證一下集羣是否正常。

[root@rocketmq-nameserver1 ~]# redis-cli -h 192.168.2.177 -p 26379
192.168.2.177:26379> SENTINEL sentinels mymaster
1)  1) "name"
    2) "648ced6a4a5126ffe053c7190a7787ce8507122d"
    3) "ip"
    4) "192.168.2.178"
    5) "port"
    6) "26379"
    7) "runid"
    8) "648ced6a4a5126ffe053c7190a7787ce8507122d"
    9) "flags"
   10) "sentinel"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "203"
   19) "last-ping-reply"
   20) "203"
   21) "down-after-milliseconds"
   22) "30000"
   23) "last-hello-message"
   24) "425"
   25) "voted-leader"
   26) "?"
   27) "voted-leader-epoch"
   28) "0"
2)  1) "name"
    2) "25133c581dc5a5dcc41ed40d720bf417b70d6449"
    3) "ip"
    4) "192.168.2.180"
    5) "port"
    6) "26379"
    7) "runid"
    8) "25133c581dc5a5dcc41ed40d720bf417b70d6449"
    9) "flags"
   10) "sentinel"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "203"
   19) "last-ping-reply"
   20) "203"
   21) "down-after-milliseconds"
   22) "30000"
   23) "last-hello-message"
   24) "870"
   25) "voted-leader"
   26) "?"
   27) "voted-leader-epoch"
   28) "0"

由輸出可見,其他兩個哨兵運行正常

192.168.2.177:26379> SENTINEL masters
1)     1) "name"
     2) "mymaster"
     3) "ip"
     4) "192.168.2.177"
     5) "port"
     6) "6379"
     7) "runid"
     8) "f2c92c055ec129186fec93d0b394a99ad120fd1d"
     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) "800"
    19) "last-ping-reply"
    20) "800"
    21) "down-after-milliseconds"
    22) "30000"
    23) "info-refresh"
    24) "10034"
    25) "role-reported"
    26) "master"
    27) "role-reported-time"
    28) "120535"
    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"

由上輸出可見,主 Redis 正常

192.168.2.177:26379> SENTINEL slaves mymaster
1)     1) "name"
     2) "192.168.2.180:6379"
     3) "ip"
     4) "192.168.2.180"
     5) "port"
     6) "6379"
     7) "runid"
     8) "2675617f208ace5c13161e133819be75f7079946"
     9) "flags"
    10) "slave"
    11) "link-pending-commands"
    12) "0"
    13) "link-refcount"
    14) "1"
    15) "last-ping-sent"
    16) "0"
    17) "last-ok-ping-reply"
    18) "448"
    19) "last-ping-reply"
    20) "448"
    21) "down-after-milliseconds"
    22) "30000"
    23) "info-refresh"
    24) "4606"
    25) "role-reported"
    26) "slave"
    27) "role-reported-time"
    28) "235584"
    29) "master-link-down-time"
    30) "0"
    31) "master-link-status"
    32) "ok"
    33) "master-host"
    34) "192.168.2.177"
    35) "master-port"
    36) "6379"
    37) "slave-priority"
    38) "100"
    39) "slave-repl-offset"
    40) "47120"
2)     1) "name"
     2) "192.168.2.178:6379"
     3) "ip"
     4) "192.168.2.178"
     5) "port"
     6) "6379"
     7) "runid"
     8) "803d8178c44a4380243523248dca0838c7964299"
     9) "flags"
    10) "slave"
    11) "link-pending-commands"
    12) "0"
    13) "link-refcount"
    14) "1"
    15) "last-ping-sent"
    16) "0"
    17) "last-ok-ping-reply"
    18) "448"
    19) "last-ping-reply"
    20) "448"
    21) "down-after-milliseconds"
    22) "30000"
    23) "info-refresh"
    24) "4606"
    25) "role-reported"
    26) "slave"
    27) "role-reported-time"
    28) "235627"
    29) "master-link-down-time"
    30) "0"
    31) "master-link-status"
    32) "ok"
    33) "master-host"
    34) "192.168.2.177"
    35) "master-port"
    36) "6379"
    37) "slave-priority"
    38) "100"
    39) "slave-repl-offset"
    40) "47120"

由上輸出可見 Redis 從服務正常。

哨兵集羣常用命令

SENTINEL masters                            #列出所有被監視的master,以及當前master狀態
SENTINEL master <master name>                      #列出指定的master
SENTINEL slaves <master name>                      #列出給定master的所有slave以及slave狀態
SENTINEL sentinels <master name>                    #列出監控指定的master的所有sentinel
SENTINEL get-master-addr-by-name <master name>             #返回給定master名字的服務器的IP地址和端口號
SENTINEL reset <pattern>                        #重置所有匹配pattern表達式的master狀態
SENTINEL failover <master name>                     #當msater失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移,但是它會給其他sentinel發送一個最新的配置,其他sentinel會根據這個配置進行更新
SENTINEL ckquorum <master name>                     #檢查當前sentinel的配置能否達到故障切換master所需的數量,此命令可用於檢測sentinel部署是否正常,正常返回ok
SENTINEL flushconfig                                                   #強制sentinel將運行時配置寫入磁盤,包括當前sentinel狀態

redis啓動腳本

#!/bin/sh
#chkconfig: 2345 55 25
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

### BEGIN INIT INFO
# Provides:     redis_6379
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Redis data structure server
# Description:          Redis data structure server. See https://redis.io
### END INIT INFO
source /etc/init.d/functions

REDISPORT=6379
EXEC=/usr/bin/redis-server
CLIEXEC=/usr/bin/redis-cli

PIDFILE=/wdata/redis/data/redis.pid
CONF="/wdata/redis/config/redis.conf"

AUTH=""
BIND_IP='192.168.2.177'

start(){
    if [ -f $PIDFILE ]
    then
            echo "$PIDFILE exists, process is already running or crashed"
    else
            echo "Starting Redis server..."
            $EXEC $CONF
    fi

    if [ "$?"="0" ]
    then
        echo "Redis is running..." 
    else
        echo "Redis not running !"
    fi
}

stop(){
    if [ ! -f $PIDFILE ]
    then
        echo "$PIDFILE does not exist, process is not running"
    else
        PID=$(cat $PIDFILE)
        echo "Stopping ..."
        #$CLIEXEC -h $BIND_IP -a $AUTH -p $REDISPORT shutdown
        $CLIEXEC -h $BIND_IP -p $REDISPORT shutdown
        while [ -x /proc/${PID} ]
        do
            echo "Waiting for Redis to shutdown ..."
            sleep 1
        done
        echo "Redis stopped."
    fi
}
status(){
    ps -ef | grep redis-server | grep -v grep >/dev/null 2>&1

    if [ $? -eq 0 ];then

        echo "redis server is running."

    else
        echo "redis server is stopped."

    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
            ;;
    status)
        status
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

sentinel啓動腳本

#!/bin/sh
#chkconfig: 2345 55 25
#
# Simple Sentinel init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

### BEGIN INIT INFO
# Provides:     redis_6379
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Sentinel data structure server
# Description:          Sentinel data structure server. See https://redis.io
### END INIT INFO
source /etc/init.d/functions

REDISPORT=26379
EXEC=/usr/bin/redis-sentinel
CLIEXEC=/usr/bin/redis-cli

PIDFILE=/wdata/redis/data/redis-sentinel.pid
CONF="/wdata/redis/config/sentinel.conf"

AUTH=""
BIND_IP='192.168.2.177'

start(){
    if [ -f $PIDFILE ]
    then
            echo "$PIDFILE exists, process is already running or crashed"
    else
            echo "Starting Sentinel server..."
            $EXEC $CONF
    fi

    if [ "$?"="0" ]
    then
        echo "Sentinel is running..." 
    else
        echo "Sentinel not running !"
    fi
}

stop(){
    if [ ! -f $PIDFILE ]
    then
        echo "$PIDFILE does not exist, process is not running"
    else
        PID=$(cat $PIDFILE)
        echo "Stopping ..."
        #$CLIEXEC -h $BIND_IP -a $AUTH -p $REDISPORT shutdown
        $CLIEXEC -h $BIND_IP -p $REDISPORT shutdown
        while [ -x /proc/${PID} ]
        do
            echo "Waiting for Sentinel to shutdown ..."
            sleep 1
        done
        echo "Sentinel stopped."
    fi
}
status(){
    ps -ef | grep redis-sentinel | grep -v grep >/dev/null 2>&1

    if [ $? -eq 0 ];then

        echo "Sentinel server is running."

    else
        echo "Sentinel server is stopped."

    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
            ;;
    status)
        status
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章