Redis HA架构:Redis(master/slave) + Keepalived + Redis Sentinel + Twemproxy + Twemproxy Agent

一、Redis HA架构描述:
目前,Redis高可用方案,主要集中于以下几种:
1.Redis(master/slave)
2.Redis(master/slave) + Keepalived + Redis Sentinel
3.Codis
4.Redis(master/slave) + Keepalived + Redis Sentinel + Twemproxy + Keepalived
5.Redis(master/slave) + Keepalived + Redis Sentinel + Twemproxy + Twemproxy Agent + nodejs +npm
第 4 种,我们通过 两个keepalived 来是实现HA,一个是实现Redis HA的vip ;一个是Twemproxy HA的VIP
第 5 种,使用一个 keepalived 来实现Twemproxy HA,通过 Twemproxy Agent 来更新 Twemproxy 配置(当redis主从切换时)
下面,我们主要讲解第 5 种 方案:
Redis(master/slave) + Keepalived + Redis Sentinel + Twemproxy + Twemproxy Agent + nodejs + nodejs-forever-agent + npm

二、Redis HA架构图:

Image

三、Redis(master/slave) + Redis Sentinel 部署:
具体的安装可以参照:
Redis HA 下的
20141202:Redis 主从部署
20150421:Redis Sentinel + keepalived 部署
下面,将简单描述:
1.Redis(master/slave) 的部署:[ 部署在 10.55、10.56 ]
10.55、10.56 都部署两套Redis,
# 第二套redis,只要将配置文件( redis.conf) 复制并改名为 redis_6380.conf
# 新配置文件/ 启动脚本等 修改,参照 Redis 主从部署一篇
2.Redis Sentinel 部署:[ 部署在 10.54、10.55、10.56 ]
# 只要在Redis Sentinel 的配置文件,把新建的Redis master 添加进去,就可;
# 具体,参照如下文件:
vim /usr/local/redis-sentinel/etc/sentinel.conf
port 26379
dir /usr/local/redis-sentinel/data
sentinel monitor mymaster 172.16.10.55 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 60000
# sentinel client-reconfig-script mymaster /usr/local/redis-sentinel/bin/keepalived.sh # 这里我们在故障切换时,就不再执行脚本
sentinel monitor mymaster2 172.16.10.56 6380 1
sentinel down-after-milliseconds mymaster2 5000
sentinel parallel-syncs mymaster2 1
sentinel failover-timeout mymaster2 60000
3.下面启动相关Redis服务:
(1).启动 Redis服务;
(2).启动 Redis Sentinel 服务;
(3).测试 Redis master/slave 切换情况;

四、keepalived 部署:[ 部署在 10.53、10.54 ]
# keepalived 部署 参照 ”20150421:Redis Sentinel + keepalived 部署 “ 文章中的 keepalived 部署 一段
# 在此,就不再赘述

五、Twemproxy 部署:[ 部署在 10.53、10.54 ]
# Twemproxy 部署 参照 “Redis 中间件” 中的 “20150427:twemproxy 简介、安装配置”文章
# 在此,就不再赘述

六、Twemproxy Agent 部署:[ 部署在 10.53、10.54 ]
1.安装nodejs + npm:
yum -y install nodejs npm
2.安装forever:
npm install forever -g
3.安装Twemproxy Agent
(1).解压Twemproxy Agent 包,并复制到指定目录:
mv /tmp/redis-twemproxy-agent-master /usr/local/redis-twemproxy-agent
(2).修改redis-twemproxy-agent/lib/cli.js文件:
修改cli.parse里的文件路径为部署的路径,具体参照如下配置:
cli.parse
({
host: [‘h’, ‘Redis sentinel hostname’, ‘string’, ‘172.16.10.54’],
port: [‘p’, ‘Redis sentinel port number’, ‘number’, 26379],
config: [‘f’, ‘Path to twemproxy config’, ‘path’, ‘/usr/local/twemproxy/conf/nutcracker.yml’],
command: [‘c’, ‘Command to restart twemproxy’, ‘string’, ‘/etc/init.d/twemproxy restart’],
log: [‘l’, ‘The log file location’, ‘string’, ‘/usr/local/twemproxy/run/twemproxy_sentinel.log’]
});
(3).将 redis-twemproxy-agent/init.d/twemproxy_sentinel 复制到 /etc/init.d/ 目录下:
cp /usr/local/redis-twemproxy-agent/init.d/twemproxy_sentinel /etc/init.d/

# 修改该脚本redis-twemproxy-agent,nodejs,forever,的路径为实际路径,参考如下:
ROOT=/usr/local/redis-twemproxy-agent
EXEC=$ROOT/bin/redis_twemproxy_agent
NODE=/usr/bin/node
FOREVER=/usr/bin/forever
(4).启动 redis-twemproxy-agent 服务:
/etc/init.d/twemproxy_sentinel start

# 此测试结果,没有能证明 redis-twemproxy-agent 能自动修改 twemproxy 的配置文件,可能在文件配置方面有误,后续再研究

Redis Sentinel + keepalived 部署

一、Redis Sentinel简介:
Redis Sentinel 是一个分布式系统,你可以在一个架构中运行多个Sentinel 进程(progress),这些进程使用流言协议(gossipprotocols) 来接收关于主服务器是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个从服务器作为新的主服务器。
虽然Redis Sentinel只是一个单独的可执行文件 redis-sentinel,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel。
源码编译安装后,src目录有一个命名为redis-sentinel的程序。
对于redis-sentinel 程序,你可以用以下命令来启动Sentinel 系统:redis-sentinel /path/to/sentinel.conf

二、Redis Sentinel 的部署:
1.复制 redis 目录为 Redis Sentinel
# 这里我们基于原先 源码编译安装的redis目录,复制一个副本,改名为: Redis Sentinel
cp -r /usr/local/redis-3.0 /usr/local/redis-sentinel

2.正常安装:我们需要建 etc、bin、data、log 等目录;
但是,因为我们是复制redis目录,这写目录都有了,我们只需要稍作改动:
# 在 10.54、10.55 、 10.56 的redis上,都配置此文件,只是在 10.54[ 此机器上没有装redis ]上的配置文件 sentinel client-reconfig-script 注释掉
vim /usr/local/redis-sentinel/etc/sentinel.conf
port 26379
dir /usr/local/redis-sentinel/data
sentinel monitor mymaster 172.16.10.55 6379 1
sentinel down-after-milliseconds mymaster 5000 # 单位为毫秒
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 60000
sentinel client-reconfig-script mymaster /usr/local/redis-sentinel/bin/keepalived.sh # 检测故障后,调用的keepalive脚本,需要有X权限

3.部署redis-sentinel 启动脚本:
vim /usr/local/redis-sentinel/bin/startup.sh
#!/bin/bash
CMD_PATH=/usr/local/redis-sentinel/bin/redis-sentinel
CONF_PATH=/usr/local/redis-sentinel/conf/sentinel.conf
LOG_PATH=/usr/local/redis-sentinel/log/sentinel.log
${CMD_PATH} ${CONF_PATH} >> ${LOG_PATH} 2>&1 &

以下为参考脚本,暂不使用:
#!/bin/bash
#Configurations injected by install_server below….
EXEC=/usr/local/redis-sentinel/bin/redis-sentinel
CLIEXEC=/usr/local/redis-sentinel/bin/redis-cli
PIDFILE=/usr/local/redis-sentinel/log/redis-sentinel_26379.pid
CONF=”/usr/local/redis-sentinel/etc/sentinel.conf”
REDISPORT=”26379″
case “$1” in
start)
if [ -f $PIDFILE ]
then
echo “$PIDFILE exists, process is already running or crashed”
else
echo “Starting Redis server…”
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo “$PIDFILE does not exist, process is not running”
else
PID=$(cat $PIDFILE)
echo “Stopping …”
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo “Waiting for Redis to shutdown …”
sleep 1
done
echo “Redis stopped”
fi
;;
status)
PID=$(cat $PIDFILE)
if [ ! -x /proc/${PID} ]
then
echo ‘Redis is not running’
else
echo “Redis is running ($PID)”
fi
;;
restart)
$0 stop
$0 start
;;
*)
echo “Please use start, stop, restart or status as first argument”
;;
esac

三、keepalived 部署:
1.keepalive的安装,安装目录为/usr/local/keepalive
# 默认软件已上传并且解压,进入keepalived目录
./configure –prefix=/usr/local/keepalived
make && make install

# 在配置过程中可能出现某些软件包没有正确安装的提示,如openssl,popt等。
解决办法是使用 yum install openssl*以及yum install popt popt-deve l来安装缺少的软件包。
Keepalived 安装完成后,会在安装目录/usr/local/keepalived 生成 bin,etc,man,sbin 这4 个目录。其中etc为配置文件所在的目录。

2.配置 keepalived 环境变量
# 给root用户增加环境变量,在export PATH行之前加入一行:
vi ~/.bash_profile
PATH=$PATH:/usr/local/keepalived/sbin
保存退出,执行下面命令,使参数生效
. ~/.bash_profile

3.整理相关文件和命令,方便使用service 启动
cp -a /usr/local/keepalived/sbin/keepalived /usr/sbin/
cp -a /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
cp -a /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
# 让chkconfig管理新添加的服务
chkconfig –add keepalived
# 添加启动级别
chkconfig keepalived on
# 查看启动设置
chkconfig –list keepalived

4.keepalived配置文件的修改如下:配置文件目录在( /etc/keepalived/keepalived.conf )
# 172.16.10.55 master 的配置文件
global_defs {
notification_email
{
13501960667@139.com # 收件邮箱
}
notification_email_from mysql_lab@localhost # 发件邮箱
smtp_server localhost # 发件服务器
smtp_connect_timeout 30 # 超时时间
router_id HAOWU_55
}
vrrp_sync_group VG1 {
group
{
VI_1
}
}
vrrp_instance VI_1 {
state MASTER
# state BACKUP
# nopreempt
interface eth0
virtual_router_id 96
priority 110
advert_int 1
authentication
{
auth_type PASS
auth_pass Pa$$w0rd
}
virtual_ipaddress
{
172.16.10.251
}
}

# 172.16.10.56 slave 的配置文件
global_defs {
notification_email
{
13501960667@139.com
}
notification_email_from mysql_lab@localhost
smtp_server localhost
smtp_connect_timeout 30
router_id HAOWU_56
}
vrrp_sync_group VG1 {
group
{
VI_1
}
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 96
priority 100
advert_int 1
authentication
{
auth_type PASS
auth_pass Pa$$w0rd
}
virtual_ipaddress
{
172.16.10.251
}
}

注:
# 红色部分 是在我们实际配置中,需要修改的地方;
# 紫红色部分 是我们在HA操作中,可以参考的设置下:
具体理解如下:
主/从的state 都设置为: BACKUP ,同是将 priority( 110>100 ) 大的机器设置为 nopreempt 可以避免切换后,vip抢占问题;
nopreempt 只能工作于 state 为BACKUP 的状态下;

5.编写keepalived 切换脚本(55、56上配置此脚本):
vim /usr/local/redis-sentinel/bin/keepalived.sh
# 红色加粗脚本,只适用于主机宕机
#!/bin/bash
REDISCLI=”/usr/local/redis-3.0/bin/redis-cli”
if $REDISCLI info|grep role|grep -q master ;then
echo “start keepalived” >> ../log/sentinel.log
/etc/init.d/keepalived start >> ../log/sentinel.log
else
echo “stop keepalived” >> ../log/sentinel.log
/etc/init.d/keepalived stop >> ../log/sentinel.log
fi

# 下面脚本为改进脚本:
#!/bin/bash
EXEC=/usr/local/redis-3.0/bin/redis-server
CLIEXEC=/usr/local/redis-3.0/bin/redis-cli
CONF=”/usr/local/redis-3.0/etc/redis.conf”
REDISPORT=”6379″
KEEP_PID=`ps -A | grep keepalived |awk ‘{print $1}’ > /dev/null`

$CLIEXEC -p $REDISPORT info > /dev/null
if [ $? -eq 0 ]; then
if [ -z “$KEEP_PID” ]; then
# try to start keepalived again
/etc/init.d/keepalived start
else
echo “ERROR!!! server:keepalved is down!” | mail -s “ERROR!! keepalived is down !!!” 13501960667@139.com
fi
else
# try to start it again
# 以下部分 为了测试需要需要注释掉[ 下面这段脚本是判断能否重启redis,这里为测试需要,注释掉 ]
# $EXEC $CONF
# $CLIEXEC -p $REDISPORT info > /dev/null
# if [ $? -eq 0 ]; then
# exit 0
# else
# restart failed
/etc/init.d/keepalived stop
# fi
fi

# 给予脚本 执行权限:
chmod +x /usr/local/redis-sentinel/bin/keepalived.sh

四、部署测试:
1.测试keepalived 虚 ip 切换情况:
master(55) 和 slave(56) :
# 启动 keepalived
/etc/init.d/keepalived start
# 执行 ip addr:查看当前虚ip情况(停掉matser 的keepalived 看 虚IP 是否飘到 slave 上)

2.redis-sentinel启动测试:
/usr/local/redis-sentinel/bin/redis-sentinel /usr/local/redis-sentinel/etc/sentinel.conf
# 启动后,会有详细的信息输出,包括当前的主,redis-sentinel的个数,地址等

# 登陆 redis-sentinel 查看相关信息:
bin/redis-cli -h 172.16.10.56 -p 26379
172.16.10.56:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=172.16.10.55:6379,slaves=1,sentinels=3

3.redis 故障测试:
# 将 当前master(172.16.10.55) 关闭,看redis-sentinel 的切换日志
bin/redis-cli -h 172.16.10.55 -p 6379 shutdown
# 切换日志如下:
15296:X 22 Apr 16:38:49.292 # +sdown master mymaster 172.16.10.55 6379
15296:X 22 Apr 16:38:49.292 # +odown master mymaster 172.16.10.55 6379 #quorum 1/1
15296:X 22 Apr 16:38:49.292 # Next failover delay: I will not start a failover before Wed Apr 22 16:40:49 2015
15296:X 22 Apr 16:38:50.313 # +config-update-from sentinel 172.16.10.54:26379 172.16.10.54 26379 @ mymaster 172.16.10.55 6379
15296:X 22 Apr 16:38:50.313 # +switch-master mymaster 172.16.10.55 6379 172.16.10.56 6379
15296:X 22 Apr 16:38:50.313 * +slave slave 172.16.10.55:6379 172.16.10.55 6379 @ mymaster 172.16.10.56 6379
15296:X 22 Apr 16:38:50.441 # -script-error /usr/local/redis-sentinel/bin/keepalived.sh 0 2
15296:X 22 Apr 16:38:55.342 # +sdown slave 172.16.10.55:6379 172.16.10.55 6379 @ mymaster 172.16.10.56 6379

Redis 主从部署

Redis 部署说明:
redis使用两台机器,172.16.10.55,172.16.100.56。
55为redis master,56为redis slave,
监听默认的6379端口。

(1).创建Redis相关目录:
cd /usr/local/redis-3.0
# 如果相关目录已经在安装时,新建,下面步骤就忽略
mkdir -p /usr/local/redis-3.0/{data,log,etc}

(2).编辑Redis Master/Slave 相关配置文件:
vim etc/redis.conf

Master配置文件(生产实际配置文件不是这样,比较简单)
######################## GENERAL ######################
daemonize yes
pidfile /usr/local/redis-3.0/log/redis_6379.pid
port 6379
timeout 0
loglevel notice
logfile “/usr/local/redis-3.0/log/redis_6379.log”
syslog-enabled no
databases 16
#########################SAVE###########################
dbfilename dump.rdb
dir /usr/local/redis-3.0/data
stop-writes-on-bgsave-error no
#########################REPLICATION ###################
slave-serve-stale-data yes
slave-read-only yes
repl-timeout 60
repl-backlog-size 10mb
repl-backlog-ttl 3600
repl-ping-slave-period 10
min-slaves-to-write 0
min-slaves-max-lag 0
##########################SECURITY ######################
########################## LIMITS ########################
maxclients 2000
#########################APPEND ONLY MODE #############
appendonly no
appendfilename “appendonly.aof”
#########################SLOW LOG #######################
slowlog-log-slower-than 10000
slowlog-max-len 1000

**********************************************************************************

Slave配置文件(生产实际配置文件不是这样,比较简单)
######################## GENERAL ######################
daemonize yes
pidfile /usr/local/redis-3.0/log/redis_6379.pid
port 6379
timeout 0
loglevel notice
logfile “/usr/local/redis-3.0/log/redis.log”
syslog-enabled no
databases 16
#########################SAVE###########################
dbfilename dump.rdb
dir /usr/local/redis-3.0/data
stop-writes-on-bgsave-error no
#########################REPLICATION ###################
slaveof 172.16.10.55 6379
slave-serve-stale-data yes
slave-read-only yes
repl-timeout 60
repl-backlog-size 10mb
repl-backlog-ttl 3600
repl-ping-slave-period 10
min-slaves-to-write 0
min-slaves-max-lag 0
##########################SECURITY ######################
########################## LIMITS ########################
maxclients 2000
#########################APPEND ONLY MODE #############
appendonly no
appendfilename “appendonly.aof”
#########################SLOW LOG #######################
slowlog-log-slower-than 10000
slowlog-max-len 1000

(3).启动/关闭Redis服务:
启动Redis服务顺序:
先启动 Redis Master , 再启动 Redis Slave
关闭Redis服务顺序:
先关闭 Redis Master , 再关闭 Redis Slave

(4).验证Redis 主从复制是否正常:
最简单的方式,就是登录 Redis Master,设置一个值:select 0;set name Michael;
然后登录 Redis Slave ,看能不能获取到刚才设置的那个值:select 0;get name;

网上有种验证方式如下:
进入主从服务器的数据目录,查询对比所有服务器数据文件的散列值和文件大小:
find . -type f -name “*.rdb” | xargs md5sum
find . -type f -name “*.rdb” | xargs ls -l

生成报文摘要并验证,如果对比成功则数据已同步:
find . -type f -name “*.rdb” | xargs md5sum >biran
md5sum –check biran