keepalived 是集群管理中常用的高可用服务软件,用来解决单点故障
什么是单点故障?
当服务是单节点或者不具备主从切换能力的集群,主节点宕时,整个服务不可用,称为单点故障
常见的单点故障解决方案
基于 DNS,一主机名多 IP,DNS 服务自带负载均衡,并且一般任务 DNS 服务是高可用的
使用 keepalived,配置虚拟 IP,监控节点状态,在必要时将虚拟 IP 漂移到备用节点
keepalived 基本原理
VRRP,虚拟链路冗余协议,在网络设计中用来做线路冗余、设备冗余等,防止网络存在单点故障
keepalived 基于 VRRP 协议,将服务器当作路由设备,通过虚拟 IP 的漂移来达到高可用的目的
什么是 Redis 主从复制?
主从复制是一种由主节点向从节点同步数据的功能,Redis 的主从复制是单向的,只能由主到从
主从复制的作用是提供数据的冗余备份,这正是高可用的基础
使用 replicaof(5.0 之前 slaveof) 命令形成主从关系即可开启主从复制
主从复制原理
全量复制
主从刚建立连接时,主库将所有数据生成 RDB 文件,发给从库进行同步,然后再把生成 RDB 过程中产生的修改发给从库
增量复制
Redis 2.8 开始支持增量复制,主要是为了解决网络闪断造成全量复制,开销很大的问题
增量复制的原理是断开的一段时间内,主库保持一个记录主从差异数据的缓冲区
为什么使用 RDB 进行数据同步的传输?
RDB 是定时或需要全量复制时生成的快照,是经过压缩的二进制文件,体积小,恢复快
相比之下 AOF 记录了每次执行的命令,有许多冗余命令,体积大,浪费带宽,并且需要选择刷盘策略,选择不当可能会影响性能
Redis 哨兵模式
Redis 主从复制保证了数据冗余备份,但当集群的主节点宕掉,整个集群将无法提供服务
Redis 哨兵机制提供了集群监控的能力,在主节点宕掉时通过选举产生新主,并完成集群主从角色的切换
Redis keepalived 双活
Redis 哨兵节点至少需要三台以上节点,因为哨兵节点也需要做高可用
当只有两台机器用于部署 Redis 集群时,可以利用 keepalived 进行节点的监控和主从的切换,在资源有限的项目中不失为一个良好的高可用方案
使用 docker centos 镜像,启动两个容器,安装 Redis 和 keepalived 等软件,模拟两个 Redis 节点的集群
节点 IP 和端口规划
# 服务节点 IP
主节点 centos_1 172.18.0.4
从节点 centos_2 172.18.0.5
# redis 端口
centos_1 6376
centos_2 6376
# 虚拟 IP
VIP 172.18.0.10
启动两个节点
拉取 centos 镜像
docker pull centos:7
启动两个 centos 容器
docker run --name centos_1 --privileged=true --ip 172.18.0.4 -d centos:7 /usr/sbin/init
docker run --name centos_2 --privileged=true --ip 172.18.0.5 -d centos:7 /usr/sbin/init
查看容器 IP
docker network inspect bridge | grep -A4 centos_
进入容器
docker exec -it centos_1 bash
安装常用软件
更新软件库
yum update && yum upgrade
安装 net-tools,提供 ifconfig 命令
yum install net-tools
安装 initscripts,提供 service 命令
yum install initscripts
docker 的 centos 镜像内部可能缺少一些常用命令,必要时自行安装
安装 Redis 并启动
安装 EPEL 软件库
yum install epel-release
安装 Redis
yum install redis
修改 Redis 配置文件
vi /etc/redis.conf
主节点 centos_1
bind 0.0.0.0
requirepass 123456
# 配置主从切换时,主节点的密码
masterauth 123456
从节点 centos_2
bind 0.0.0.0
requirepass 123456
masterauth 123456
# 启动时设置主节点
slaveof 172.18.0.4 6379
启动两个节点上的 Redis
redis-server /etc/redis.conf >> redis.log 2>&1
主节点添加一条测试数据
从节点查看数据是否同步
安装 keepalived
yum install keepalived
keepalived 配置的基本结构
global_defs {
# 全局配置
}
vrrp_script [脚本名称] {
# 自定义的检查脚本
}
vrrp_instance VI_1 {
# vrrp 实例配置
}
virtual_server [IP] [端口] {
# LVS 配置
}
keeplaived Redis 主从切换配置
! Configuration File for keepalived
global_defs {
# 当前主机标识
router_id LVS_DEVEL
# 严格模式,一般不开启
# vrrp_strict
# 指定脚本执行用户
script_user root
enable_script_security
}
vrrp_script redis_check {
# 检查脚本,参数:[密码]
script "/var/keepalived/scripts/redis_check.sh 123456"
# 检查时间间隔
interval 1
# 脚本执行结果导致的优先级变更
# 负数表示脚本退出状态非零时要减少的优先级
weight -20
# 重复执行的多少次才认为是成功或失败
rise 3
fall 3
}
vrrp_instance VI_1 {
# 初始状态
state MASTER
# 绑定的网卡
interface eth0
# 集群的统一标识
virtual_router_id 51
# 初始优先级
priority 100
# 心跳检查时间间隔,默认 1s
advert_int 1
# 认证配置
authentication {
# 认证模式:PASS
auth_type PASS
# 密码
auth_pass 1111
}
# 虚拟 IP
virtual_ipaddress {
172.18.0.10
}
# 状态检查脚本
track_script {
redis_check
}
# 当前节点变为 MASTER 时执行,参数:[密码]
notify_master "/var/keepalived/scripts/redis_master.sh 123456"
# 当前节点变为 BACKUP 时执行,参数:[密码] [主节点 IP] [主节点端口]
notify_backup "/var/keepalived/scripts/redis_slave.sh 123456 172.18.0.4 6379"
# 当发现节点故障时执行
notify_fault "/var/keepalived/scripts/redis_falut.sh"
# 当停止 VRRP 时执行
notify_stop "/var/keepalived/scripts/redis_stop.sh"
}
172.18.0.4 主节点初始状态设置为 MASTER,priority 为 100
172.18.0.5 从节点初始状态设置为 BACKUP,priority 为 90
当 .4 主节点 Redis 服务不可用时,优先级降低,VIP 漂移到 .5 上,但是当 .4 服务重新上线后,会抢走 MASTER 身份,造成不必要的主从切换,可以将 .4 配置为 nopreempt(非抢占模式)来避免
如果 .4 配置为非抢占,将不会为 priority 所动,只有 .5 上 keepalived 服务宕掉,VIP 才会漂移到 .4
keepalived 的配置文件要求很严格,避免多余的空格,缩进须使用 Tab
相关脚本
redis_check.sh
#!/bin/bash
CMD_RES=`redis-cli -a $1 PING 2>/dev/null`
LOG_FILE="/var/keepalived/logs/redis-state.log"
if [ "$CMD_RES"x == "PONG"x ]; then :
echo "[CHECK] `date`, SUCCESS" >> $LOG_FILE 2>&1
exit 0
else
echo "[CHECK] `date`, ERROR" >> $LOG_FILE 2>&1
exit 1
fi
redis_master.sh
#!/bin/bash
CMD="redis-cli"
LOG_FILE="/var/keepalived/logs/redis-change.log"
echo "[MASTER] `date`" >> $LOG_FILE
echo "Run SLAVEOF NO ONE cmd" >> $LOG_FILE
$CMD -a $1 SLAVEOF NO ONE >> $LOG_FILE 2>&1
redis_slave.sh
#!/bin/bash
CMD="redis-cli"
LOG_FILE="/var/keepalived/logs/redis-change.log"
echo "[BACKUP] `date`" >> $LOG_FILE
echo "Being slave wait to sync data" >> $LOG_FILE
sleep 1
echo "Run SLAVEOF cmd" >> $LOG_FILE
$CMD -a $1 SLAVEOF $2 $3 >> $LOG_FILE 2>&1
redis_falut.sh
#!/bin/bash
LOG_FILE="/var/keepalived/logs/redis-state.log"
echo "[FAULT] `date`" >> $LOG_FILE
redis_stop.sh
#!/bin/bash
LOG_FILE="/var/keepalived/logs/redis-state.log"
echo "[STOP] `date`" >> $LOG_FILE
测试 Redis 主从复制
启动 keepalived
service keepalived start
也可以直接运行 keepalive 可执行文件
# -f 指定配置文件,-l 开启控制台日志,-n 不在后台运行
/sbin/keepalived -f /etc/keepalived/keepalived.conf -l -n
测试故障转移
通过 Redis cli 连接虚拟 IP,可以正常执行命令
kill 掉主节点的 Redis 进程
观察主节点 keepalived 日志
直连原来的从节点测试写入
172.18.0.5 上可以执行写入命令,说明该节点已经成功切换为主节点