2015/3/2

redis HA sentinel

如果要建置 redis 的 HA 環境,有兩種選擇,第一種是基於 replication 的 sentinel,第二種則是還在 alpha 階段的 redis 3.0 提供的 cluster 功能。

redis cluster 目前還在 alpha 階段,他所提供最重要的功能,就是 auto sharding,

HA

考量到 HA 的議題,要思考兩點 (1) data availability (2) service availability,以目前 2.8 版的狀況,redis 支援 data replication,針對 service availabilty 也提供了sentinel做 redis daemon 的監控。

redis 與 sentinel 的關係可參考下圖,這兩個分別是獨立的 daemon,redis 服務的 port 為 tcp 6379,sentinel 是 tcp 26379。



當 master node 消失,sentinel 會自動將 slave node 改為 master,並繼續提供 redis 服務,如果 slave node 有多個,那麼 sentinel 只會自動將某一個 slave node 改為 master。



以下我們假設 master node ip 為 192.168.1.10,slave node 為 192.168.1.20

data replication

依照上圖,我們必須在 slave 的機器上,設定 replication,將資料由 master node 複製過來,這裡要注意的是,master node 不能填寫這個設定。

修改 192.168.1.20 機器上的 redis 設定檔

vi /etc/redis/6379.conf

slave of 192.168.1.10 6379

然後 restart redis

service redis restart

簡單的驗證方式如下,在 master node 寫入,在 slave node 讀取。

> redis-cli -h 192.168.1.10 -p 6379
192.168.1.10:6379> set hello world

> redis-cli -h 192.168.1.20 -p 6379
192.168.1.20:6379> get hello
"world"

Sentinel

根據 Sentinel 的文件,主要功能有四項

  1. Monitor
    sentinel 會持續檢查 master 與 slave redis server 的狀態
  2. Notification
    sentinel 會通知系統管理員或是透過 API 通知其他程式,監控的 redis server 發生故障的狀況。
  3. Automatic failover
    如果 master node 故障,sentinel 會自動找到一個 slave node 更改為 master,其他的 slave node 也會自動將 master 更改為新的 master node。
  4. Configuration provider
    sentinel 作為 client 端處理 service discovery 的功能,連接到 sentinel 的 clients 會詢問目前 redis 的 master node 的 ip,當 failover 發生時,會自動回報為新的 ip。

接下來要設定 sentinel,用來監控 redis server,設定檔內容如下

> vi /etc/redis/sentinel.conf
port 26379
dir /tmp

daemonize yes
pidfile /var/run/redis-sentinel.pid
loglevel verbose
logfile /var/log/redis-sentinel.log

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 192.168.1.10 6379 1
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

當 quorum 是 2,就表示需要有兩個 sentinels 回報 master node 失效時,才會進行 failover process。

vi /etc/init.d/redis-sentinel

#!/bin/sh
#
# sentinel - this script starts and stops the sentinel daemon
#
# chkconfig:   - 86 14
# description:  Redis Sentinel is monitor and aut-failover for redis.
# processname: redis-sentinel
# config:      /etc/redis/sentinel.conf
# config:      /etc/sysconfig/redis-sentinel
# pidfile:     /var/run/redis-sentinel.pid

# 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/bin/redis-sentinel"
prog=$(basename $redis)

REDIS_CONF_FILE="/etc/redis/sentinel.conf"

[ -f /etc/sysconfig/redis-sentinel ] && . /etc/sysconfig/redis-sentinel

lockfile=/var/lock/subsys/redis-sentinel

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 -TERM
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    sleep 1
    start
}

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)
        $1
        ;;
    status)
        rh_status
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart}"
        exit 2
esac
chkconfig redis-sentinel on
service redis-sentinel start

當我們把 master node 的 redis service 停掉,就會在 sentinel 的 log 中看到 fail-over 的過程。

[2880] 03 Feb 15:28:37.861 * +slave slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379

[2880] 03 Feb 15:39:24.062 # +sdown master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.063 # +odown master mymaster 192.168.1.10 6379 #quorum 1/1
[2880] 03 Feb 15:39:24.063 # +new-epoch 1
[2880] 03 Feb 15:39:24.063 # +try-failover master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.113 # +vote-for-leader bf0e42815cc599c9dc2b931b08342f3575767a23 1
[2880] 03 Feb 15:39:24.113 # +elected-leader master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.113 # +failover-state-select-slave master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.181 # +selected-slave slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.181 * +failover-state-send-slaveof-noone slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:24.284 * +failover-state-wait-promotion slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:25.158 - -role-change slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379 new reported role is master
[2880] 03 Feb 15:39:25.282 # +promoted-slave slave 192.168.1.20:6379 192.168.1.20 6379 @ mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:25.282 # +failover-state-reconf-slaves master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:25.284 # +failover-end master mymaster 192.168.1.10 6379
[2880] 03 Feb 15:39:25.285 # +switch-master mymaster 192.168.1.10 6379 192.168.1.20 6379
[2880] 03 Feb 15:39:25.286 * +slave slave 192.168.1.10:6379 192.168.1.10 6379 @ mymaster 192.168.1.20 6379
[2880] 03 Feb 15:39:55.364 # +sdown slave 192.168.1.10:6379 192.168.1.10 6379 @ mymaster 192.168.1.20 6379

sentinel client

使用 sentinel ,需要搭配 client 的實做,讓 client 能夠自動尋找 master node 並 fail-over 到 backup node。

如果是使用 java,通常是用 jedis library,JedisSentinelTest 提供利用 jedis 連結 sentinel 的範例。

另外 jedis-sentinel-pool 則是提供了 jedis connection pool 的實做。

docker for redis cluster

我們也可以搭配 docker 建置 redis cluster 環境,這篇文章:用Docker構建分佈式Redis集群 提供了利用 docker 建置 redis cluster 環境的過程範例。