使用二进制安装包进行Redis Sentinel哨兵模式部署
转载自:https://www.oiox.cn/index.php/archives/411/
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的主观下线状态就会被移除。
环境
安装编译环境
# 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>