Redis Sentinel哨兵模式部署

小陈运维發表於2024-06-16

Redis Sentinel哨兵模式部署

主從模式的弊端就是不具備高可用性,當master掛掉以後,Redis將不能再對外提供寫入操作,因此sentinel模式應運而生。sentinel中文含義為哨兵,顧名思義,它的作用就是監控redis叢集的執行狀況,此模式具有如下一些特點:

  • sentinel模式是建立在主從模式的基礎上,如果只有一個Redis節點,sentinel就沒有任何意義;
  • 當master掛了以後,sentinel會在slave中選擇一個做為master,並修改它們的配置檔案,其他slave的配置檔案也會被修改,比如slaveof屬性會指向新的master;
  • 當master重新啟動後,它將不再是master,而是做為slave接收新的master的同步資料;
  • sentinel因為也是一個程序,所以有掛掉的可能,所以sentinel也會啟動多個形成一個sentinel叢集;
  • 多sentinel配置的時候,sentinel之間也會自動監控;
  • 當主從模式配置密碼時,sentinel也會同步將配置資訊修改到配置檔案中;
  • 一個sentinel或sentinel叢集可以管理多個主從Redis,多個sentinel也可以監控同一個redis;
  • sentinel最好不要和Redis部署在同一臺機器,不然Redis的伺服器掛了以後,sentinel也可能會掛掉。

其工作的流程如下所示:

  • 每個sentinel以每秒鐘一次的頻率向它所知的master,slave以及其他sentinel例項傳送一個 PING 命令;
  • 如果一個例項距離最後一次有效回覆 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個例項會被sentinel標記為主觀下線;
  • 如果一個master被標記為主觀下線,則正在監視這個master的所有sentinel要以每秒一次的頻率確認master的確進入了主觀下線狀態;
  • 當有足夠數量的sentinel(大於等於配置檔案指定的值)在指定的時間範圍內確認master的確進入了主觀下線狀態, 則master會被標記為客觀下線;
  • 在一般情況下, 每個sentinel會以每 10 秒一次的頻率向它已知的所有master,slave傳送 INFO 命令; - 當master被sentinel標記為客觀下線時,sentinel向下線的master的所有slave傳送 INFO 命令的頻率會從 10 秒一次改為 1 秒一次;
  • 若沒有足夠數量的sentinel同意master已經下線,master的客觀下線狀態就會被移除;若master重新向sentinel的 PING 命令返回有效回覆,master的主觀下線狀態就會被移除。

環境

IP 角色
192.168.1.21 master, sentinel
192.168.1.22 slave1, sentinel
192.168.1.23 slave2, sentinel

安裝編譯環境

# ubuntu
apt install make gcc
# centos
yum install make gcc

安裝 Redis

# 檢視 Redis 版本
http://download.redis.io/releases/

# 下載 Redis
wget http://download.redis.io/releases/redis-7.2.5.tar.gz

# 解壓
tar xvf redis-7.2.5.tar.gz 
cd redis-7.2.5/

# 進行編譯
make && make install

配置服務

# Redis 服務
cat << EOF > /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-server /usr/local/redis/redis.conf --supervised systemd
ExecStop=/usr/local/redis/redis-shutdown
Type=forking
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
LimitNOFILE=65536
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

配置停止指令碼

mkdir /usr/local/redis
vim /usr/local/redis/redis-shutdown
#!/bin/bash
#
# Wrapper to close properly redis and sentinel
test x"$REDIS_DEBUG" != x && set -x
REDIS_CLI=/usr/local/bin/redis-cli
# Retrieve service name
SERVICE_NAME="$1"
if [ -z "$SERVICE_NAME" ]; then
   SERVICE_NAME=redis
fi
# Get the proper config file based on service name
CONFIG_FILE="/usr/local/redis/$SERVICE_NAME.conf"
# Use awk to retrieve host, port from config file
HOST=`awk '/^[[:blank:]]*bind/ { print $2 }' $CONFIG_FILE | tail -n1`
PORT=`awk '/^[[:blank:]]*port/ { print $2 }' $CONFIG_FILE | tail -n1`
PASS=`awk '/^[[:blank:]]*requirepass/ { print $2 }' $CONFIG_FILE | tail -n1`
SOCK=`awk '/^[[:blank:]]*unixsocket\s/ { print $2 }' $CONFIG_FILE | tail -n1`
# Just in case, use default host, port
HOST=${HOST:-127.0.0.1}
if [ "$SERVICE_NAME" = redis ]; then
    PORT=${PORT:-6379}
else
    PORT=${PORT:-26739}
fi
# Setup additional parameters
# e.g password-protected redis instances
[ -z "$PASS"  ] || ADDITIONAL_PARAMS="-a $PASS"
# shutdown the service properly
if [ -e "$SOCK" ] ; then
        $REDIS_CLI -s $SOCK $ADDITIONAL_PARAMS shutdown
else
        $REDIS_CLI -h $HOST -p $PORT $ADDITIONAL_PARAMS shutdown
fi

授權啟動服務

chmod +x /usr/local/redis/redis-shutdown
useradd -s /sbin/nologin redis

cp /root/redis-7.2.5/redis.conf /usr/local/redis/ && chown -R redis:redis /usr/local/redis
mkdir -p /usr/local/redis/data && chown -R redis:redis /usr/local/redis/data
mkdir -p /usr/local/redis/sentinel && chown -R redis:redis /usr/local/redis/sentinel

修改配置

vim /usr/local/redis/redis.conf
# master節點配置
bind 0.0.0.0 -::1                # 監聽ip,多個ip用空格分隔
daemonize yes               # 允許後臺啟動
logfile "/usr/local/redis/redis.log"                # 日誌路徑
dir /usr/local/redis/data                 # 資料庫備份檔案存放目錄
masterauth 123123               # slave連線master密碼,master可省略
requirepass 123123              # 設定master連線密碼,slave可省略
appendonly yes                  # 在/usr/local/redis/data目錄生成appendonly.aof檔案,將每一次寫操作請求都追加到appendonly.aof 檔案中

vim /usr/local/redis/redis.conf
#slave1節點配置
bind 0.0.0.0 -::1                # 監聽ip,多個ip用空格分隔
daemonize yes               # 允許後臺啟動
logfile "/usr/local/redis/redis.log"      # 日誌路徑
dir /usr/local/redis/data                 # 資料庫備份檔案存放目錄
replicaof 192.168.1.21 6379   #  replicaof用於追隨某個節點的redis,被追隨的節點為主節點,追隨的為從節點。就是設定master節點
masterauth 123123               # slave連線master密碼,master可省略
requirepass 123123              # 設定master連線密碼,slave可省略
appendonly yes                  # 在/usr/local/redis/data目錄生成appendonly.aof檔案,將每一次寫操作請求都追加到appendonly.aof 檔案中

vim /usr/local/redis/redis.conf
#slave2節點配置
bind 0.0.0.0 -::1                # 監聽ip,多個ip用空格分隔
daemonize yes               # 允許後臺啟動
logfile "/usr/local/redis/redis.log"                # 日誌路徑
dir /usr/local/redis/data                 # 資料庫備份檔案存放目錄
replicaof 192.168.1.21 6379   #  replicaof用於追隨某個節點的redis,被追隨的節點為主節點,追隨的為從節點。就是設定master節點
masterauth 123123               # slave連線master密碼,master可省略
requirepass 123123              # 設定master連線密碼,slave可省略
appendonly yes                  # 在/usr/local/redis/data目錄生成appendonly.aof檔案,將每

# 三個節點都執行
cat >/usr/local/redis/sentinel.conf<<EOF
port 26379
daemonize yes
logfile "/usr/local/redis/sentinel.log"
# sentinel工作目錄
dir "/usr/local/redis/sentinel"
# 判斷master失效至少需要2個sentinel同意,建議設定為n/2+1,n為sentinel個數
# sentinel monitor <master-name> <ip> <port> <count>
sentinel monitor mymaster 192.168.1.21 6379 2
sentinel auth-pass mymaster 123123
# 判斷master主觀下線時間,預設30s
sentinel down-after-milliseconds mymaster 30000
EOF

修改linux核心引數

# 臨時生效
sysctl  -w  vm.overcommit_memory=1
# 永久生效
echo 'vm.overcommit_memory=1' >> /etc/sysctl.conf && sysctl -p
### 可選值:0,1,2。
# 0,:表示核心將檢查是否有足夠的可用記憶體供應用程序使用;如果有足夠的可用記憶體,記憶體申請允許;否則,記憶體申請失敗,並把錯誤返回給應用程序。
# 1:表示核心允許分配所有的實體記憶體,而不管當前的記憶體狀態如何。
# 2: 表示核心允許分配超過所有實體記憶體和交換空間總和的記憶體。

啟動 Redis

systemctl daemon-reload
systemctl enable redis
systemctl stop redis
systemctl start redis
systemctl status redis

# 啟動sentinel
/usr/local/bin/redis-sentinel /usr/local/redis/sentinel.conf
root@cby:~# netstat -anpt|grep 26379
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN      9156/redis-sentinel 
tcp6       0      0 :::26379                :::*                    LISTEN      9156/redis-sentinel 
root@cby:~#

檢視叢集

redis-cli -h 192.168.1.21 -p 26379 -a 123123 
192.168.1.21:26379> info sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_tilt_since_seconds:-1
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.1.21:6379,slaves=2,sentinels=3
192.168.1.21:26379> 

故障模擬

# 停掉master
systemctl stop redis
# 檢視資訊
redis-cli -h 192.168.1.22 -a 123123 info replication
role:slave
master_host:192.168.1.21
master_port:6379
master_link_status:down # 這裡
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_read_repl_offset:4567834
slave_repl_offset:4567834
master_link_down_since_seconds:0
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:449440daec10a3eb742b13e690de4adb26b20a07
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:4567834
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:3515695
repl_backlog_histlen:1052140

# 再次檢視資訊 已經恢復
redis-cli -h 192.168.1.22 -a 123123 info replication
role:master
connected_slaves:1 # 這裡
slave0:ip=192.168.1.23,port=6379,state=online,offset=4574293,lag=1
master_failover_state:no-failover
master_replid:70e80f38d396bd5e649b30bd2669b3ae024f7e25
master_replid2:449440daec10a3eb742b13e690de4adb26b20a07
master_repl_offset:4574571
second_repl_offset:4567835
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:3515695
repl_backlog_histlen:1058877

# 測試一下讀寫
redis-cli -h 192.168.1.22 -a 123123
192.168.1.22:6379> set k2 v2
OK
192.168.1.22:6379> 
192.168.1.22:6379> get k2
"v2"
192.168.1.22:6379> 


# 恢復故障
systemctl start redis
redis-cli -h 192.168.1.22 -a 123123 info replication
role:master
connected_slaves:2 # 這裡
slave0:ip=192.168.1.23,port=6379,state=online,offset=4620778,lag=1
slave1:ip=192.168.1.21,port=6379,state=online,offset=4620940,lag=0
master_failover_state:no-failover
master_replid:70e80f38d396bd5e649b30bd2669b3ae024f7e25
master_replid2:449440daec10a3eb742b13e690de4adb26b20a07
master_repl_offset:4620940
second_repl_offset:4567835
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:3556575
repl_backlog_histlen:1064366

# 測試一下讀寫
redis-cli -h 192.168.1.22 -a 123123
192.168.1.22:6379> set k3 v3
OK
192.168.1.22:6379> get k3
"v3"
192.168.1.22:6379> 

關於

https://www.oiox.cn/

https://www.oiox.cn/index.php/start-page.html

CSDN、GitHub、51CTO、知乎、開源中國、思否、部落格園、掘金、簡書、華為雲、阿里雲、騰訊雲、嗶哩嗶哩、今日頭條、新浪微博、個人部落格

全網可搜《小陳運維》

文章主要釋出於微信公眾號

相關文章