
Redis 主从高可用方案
简介
主从高可用方案由一主一从,双 redis 节点 + 一 Sentinel 节点构成 redis 服务。云环境和机房环境有各自的具体实现方法。云环境下,由从节点的 Sentinel 通过 iptables 屏蔽从节点 redis 端口,确保仅主节点通过云平台负载均衡对外服务。
节点清单
iptables 方案 (Ubuntu 16.04)
共通设置
通过 apt 命令安装 redis-server 和 redis-sentinel 包,用 sudo systemctl disable redis-server.service
命令关闭 prd-redis-01-01 上的 Redis 服务,仅运行 redis-sentinel 服务。
调用 iptables 屏蔽端口需要 root 权限,Sentinel 故障转移脚本以 redis 用户触发,需要把 redis 用户加入 sudoer 组,让 iptables 命令可以通过 sudo 被调用:
# 授权 redis 用户可以通过 sudo 使用 iptables 及相关命令
sudo visudo
# 文件结尾处添加
redis ALL=(ALL) NOPASSWD: /sbin/iptables, /sbin/iptables-save
设置初始化 iptables 规则,让 redis 端口始终可以被相关网段内 Sentinel 服务监控:
# 初始 iptables 规则:允许所有 redis 节点可以相互监控
sudo iptables -I INPUT -s 172.17.177.1/30 -p tcp --dport 6379 -j ACCEPT
sudo iptables -I INPUT -s 127.0.0.1 -p tcp --dport 6379 -j ACCEPT
Sentinel 故障转移时改变的的 iptables 规则,默认系统重启后消失。通过安装 iptables-persistent 包实现 iptables 规则系统重启时持久化。
sudo apt install iptables-persistent
# 添加系统重启时触发的脚本持久化 iptables 规则
sudo touch /etc/network/if-post-down.d/iptablessave
sudo chmod +x /etc/network/if-post-down.d/iptablessave
sudo vim /etc/network/if-post-down.d/iptablessave
#!/bin/sh
iptables-save -c > /etc/iptables/rules.v4
if [ -f /etc/iptables.downrules ]; then
iptables-restore < /etc/iptables.downrules
fi
exit 0
在 redis 主从节点上准备 Sentinel 故障转移通用脚本 /etc/redis/block-slave-port.sh:
# 以 redis 用户名义创建故障转移脚本
sudo touch /etc/redis/block-slave-port.sh
sudo chown redis:redis /etc/redis/block-slave-port.sh
sudo chmod +x /etc/redis/block-slave-port.sh
# 故障转移具体实现
sudo vim /etc/redis/block-slave-port.sh
#!/bin/bash
local_ip=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
master_old_ip="$4"
master_old_port="$5"
master_new_ip="$6"
master_new_port="$7"
logger "+++++ $0 $local_ip +++++"
logger "+++++" $1 $2 $3 ${master_old_ip} ${master_old_port} ${master_new_ip} ${master_new_port}
if [ "${local_ip}"x = "${master_old_ip}"x ]; then
logger "+++++ close ${master_old_port}"
sudo iptables -D INPUT -p tcp --dport ${master_old_port} -j ACCEPT
sudo iptables -A INPUT -p tcp --dport ${master_old_port} -j REJECT
logger "iptables updated rules: $?"
fi
if [ "${local_ip}"x = "${master_new_ip}"x ]; then
logger "+++++ open ${master_new_port}"
sudo iptables -D INPUT -p tcp --dport ${master_new_port} -j REJECT
sudo iptables -A INPUT -p tcp --dport ${master_new_port} -j ACCEPT
logger "iptables updated rules: $?"
fi
exit 0
各节点配置清单
行内注释仅标记该行配置是否需要替换原有项目,不可直接复制混入配置文件。Redis 配置文件不支持行内注释。部署配置文件后需要重启 redis-server 和 redis-sentinel 服务。
prd-redis-01-01
# sentinel.conf
bind 0.0.0.0 # 替换
# 定义 prd-redis-01 主节点
sentinel monitor prd-redis-01 prd-redis-01-02 6379 2 # 替换 mymaster 主节点
sentinel down-after-milliseconds prd-redis-01 2000 # 新增:2 秒未应答视为主观离线,触发故障转移
# VIM 命令:留用默认主节点 mymaster 的配置
:%s/mymaster/prd-redis-01/g
prd-redis-01-02
# redis.conf
bind 0.0.0.0 # 覆盖
# sentinel.conf
bind 0.0.0.0 # 替换
# 定义 prd-redis-01 主节点
sentinel monitor prd-redis-01 prd-redis-01-02 6379 2 # 替换 mymaster 主节点
sentinel down-after-milliseconds prd-redis-01 2000 # 新增:2 秒未应答视为主观离线,触发故障转移
sentinel client-reconfig-script prd-redis-01 /etc/redis/block-slave-port.sh
# 新增:故障转移时调用指定脚本
# VIM 命令,留用默认主节点 mymaster 的配置
:%s/mymaster/prd-redis-01/g
prd-redis-01-03
# redis.conf
bind 0.0.0.0 # 替换
slaveof prd-redis-01-02 6379 # 新增:设置本节点为 prd-redis-01-02 的从节点
# sentinel.conf
bind 0.0.0.0 # 替换
# 定义 prd-redis-01 主节点
sentinel monitor prd-redis-01 prd-redis-01-02 6379 2 # 替换 mymaster 主节点
sentinel down-after-milliseconds prd-redis-01 2000 # 新增:2 秒未应答视为主观离线,触发故障转移
sentinel client-reconfig-script prd-redis-01 /etc/redis/block-slave-port.sh
# 新增:故障转移时调用指定脚本
# VIM 命令,留用默认主节点 mymaster 的配置
:%s/mymaster/prd-redis-01/g