Redis Case: Master Slave HA

Redis 主从高可用方案

简介

主从高可用方案由一主一从,双 redis 节点 + 一 Sentinel 节点构成 redis 服务。云环境和机房环境有各自的具体实现方法。云环境下,由从节点的 Sentinel 通过 iptables 屏蔽从节点 redis 端口,确保仅主节点通过云平台负载均衡对外服务。

节点清单

实例名 IP 服务 侦听地址及端口
prd-redis-01-01 172.17.177.1 Sentinel 0.0.0.0:26379
prd-redis-01-02 172.17.177.2 Redis 0.0.0.0:6379
    Sentinel 0.0.0.0:26379
prd-redis-01-03 172.17.177.3 Redis 0.0.0.0:6379
    Sentinel 0.0.0.0:26379

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

 

Author: njun
njun's picture
Updated: 2018/10/11