Redis高可用方案

语言: CN / TW / HK

前序

在多数后端项目中,缓存这块儿Redis属于一枝独秀。只要是个java程序员基本少不了跟redis打交道,无论是项目中实际应用或者跟面试官切磋。我们知道Redis虽然单机QPS也有好几万,但生产环境上基本没人敢上单机。因为分布式环境中,不稳定因素很多,万一哪天网线被刨断了或者服务器挂了。影响到客户就不得了了。那么为了应对Redis的单机故障,我们一般有如下的三种高可用方案。

Redis高可用方案

方案一(主从+keepalived+VIP)

主从.png 适用场景:之前的单机模式下,在redis负载高时可能会崩溃。故给主节点增加从节点做备用节点,在主挂掉时立马提升为新主。该场景适用于redis负载不是很大,对redis高可用有需求并且客户端对主从切换无感的场景。

Keepalived:集群管理中高可用的一个服务软件,通过健康检查脚本去检测实例节点。当检查失败时会将对应节点的priority值减少。若主节点priority值比备用节点的小时,执行切换VIP脚本跟从节点升主脚本。

VIP:虚拟ip绑定至主节点,一旦主节点挂掉后,由keepalived重新绑定在新主节点上。

优点:应用端连接方面不用改变。

缺点:不能进行读写分离,主节点压力还是很大

修改点:客户端不需要修改。

方案二(主从+sentinel集群)

image.png 适用场景:在系统对redis请求并发高的情况下,方案1场景中主节点负载压力过高。

此时需要主从读写分离来减轻主节点压力,并增加缓存服务的高并发。客户端通过连接

Sentinel获取主从节点信息,并将自己的读写请求分别发送至主从节点进行请求分流,减轻主节点压力。

Sentinel哨兵:哨兵是一个运行在特殊模式下的 Redis 进程,哨兵主要负责的就是三个任务:监控、选主和通知。哨兵运行过程中周期性向所有主从节点发送PING命令,主从节点会给哨兵回复PONG命令。若主节点未在规定时间内回复哨兵,则哨兵标记该主节点为主观下线,之后会通知其它哨兵节点对该主节点进行检测。如果超过一半哨兵都判定为主观下线,则该主节点会被标记为客观下线。随后从该主节点的从节点中选出新主节点。之后会通知其余从节点进行replicaof命令和新主节点建立联系,通知客户端让他们把操作命令发到新的主节点上。

读写分离:在该模式下为分担master节点的请求压力,可在客户端上增加读写分离的逻辑,之后读请求走从节点,写请求走主节点。

增加从节点

启动新的节点并在新节点上执行如下命令即可

slaveof IP PORT(IP和PORT是需要关联的主节点ip和端口)

优点:高可用并能有效减少master上的请求压力

缺点:修改东西较多,如果写请求多,主节点依然有压力大的风险。

修改点

1、 客户端连接方式得改为sentinel模式,

2、 要实现读写分离得修改Jedis连接相关的逻辑

方案三(cluster集群)

image.png 适用场景:当系统对redis的请求负载持续升高时,方案2场景中单个主节点最终因负载过高而崩溃。此时将redis升级为集群模式,该模式下通过分槽机制将请求分散至各master节点,大大减轻单个master节点压力,而且各master节点都有自己的从节点,在主节点挂掉时,其对应的从节点会及时补充为新主节点。该方案适用于系统对redis请求压力高,并对redis有高并发高可用的需求场景。

集群模式:redis cluster集群将16384个Slot(槽位)分给集群主节点。之后客户端请求过来时候会先计算key的哈希值并跟16384取模得到对应槽位。之后根据槽位跟主节点对应关系将该请求发送至相应主节点。每个集群节点均维护一份节点跟槽位的映射关系。 如果在一个节点上操作另外一个节点上的key,会返回去相应节点操作的提示信息。 Master节点内部集成了Sentinel, 故不需单独起Sentinel集群,当有主节点挂掉时,其他Master节点会感知到并从其从节点中选出新主节点。

增加节点:当需要扩展内存增加集群节点时,连接任一主节点并依次执行如下命令:\ redis-cli -a 密码 --cluster add-node  新节点IP:端口  已存在节点IP:端口(增加集群节点) 执行成功后再执行下面命令 redis-cli -a 密码 --cluster reshard 已存在节点IP:端口(给新节点分配槽数) 根据提示分配指定槽数,分配成功后表示新主节点增加成功。再次执行增加节点命令给集群增加从节点。然后再登录新增从节点,执行如下命令,对刚增加的新主从进行关联。 首先登录进新从节点redis-cli -a  -c -h 新从节点IP -p 从节点端口 然后执行cluster replicate 2728a594a0498e98e4b83a537e19f9a0a3790f38 这样便在集群中新增了一对主从节点。

优点:支持高可用、高并发

缺点:占用资源大

修改点

1、 客户端连接方式得改为集群模式

部署步骤

方案1部署步骤

1、 Redis主从安装(记得在从节点配置文件加一行slaveof 主节点ip 端口)

mkdir /opt/software –p

cd /opt/software

wget http://download.redis.io/releases/redis-5.0.8.tar.gz

yum –y install gcc gcc-c++

tar –zxvf redis-5.0.8.tar.gz

mv redis-5.0.8 /usr/local/src

cd /usr/local/src/reids-5.0.8/

make

make install PREFIX=/usr/local/redis

vi /usr/local/src/reids-5.0.8/redis.conf(编辑配置文件)\ 修改bind 127.0.0.1 为 bind 0.0.0.0

修改 protected-mode yes 为protected-mode no

若为从节点需要在配置文件最后增加一句 slaveof 主节点IP 主节点端口

2、 keepalived软件安装(主从节点均要安装)

yum安装即可:yum –y install keepalived

3、 登录进入redis主节点,编辑/etc/keepalikved/keepalived.conf

global_defs {

router_id redis_master

}

vrrp_script chk_redis

{

script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379"

interval 2

timeout 2

fall 3

weight -20

}

vrrp_instance redis {

state MASTER

interface 网卡名称 

virtual_router_id 100

priority  100      

#nopreempt # no seize,must add

advert_int 1

authentication {   #all node must same

auth_type PASS

auth_pass 1111

}  

unicast_src_ip 主节点IP

unicast_peer {

从节点IP

}   

virtual_ipaddress { 

VIP地址

}

track_script {

chk_redis

}

notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1  从节点IP  从节点端口"

notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1  从节点IP  从节点端口"

notify_fault /etc/keepalived/scripts/redis_fault.sh

notify_stop /etc/keepalived/scripts/redis_stop.sh }

4、 登录从节点编辑/etc/keepalived/keepalived.conf内容如下:

global_defs {

router_id redis1

script_user root

enable_script_security

} vrrp_script chk_redis

{

script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379"

interval 2

timeout 2

fall 3

weight -20

} vrrp_instance redis {

state BACKUP

interface eth0 

virtual_router_id 100

priority  90      

#nopreempt # no seize,must add

advert_int 1

authentication {   #all node must same

auth_type PASS

auth_pass 1111

}  

unicast_src_ip 从节点IP

unicast_peer {

主节点IP   

}

virtual_ipaddress { 

VIP

}

track_script {

chk_redis

}

notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1  主节点IP  主节点端口"

notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1  主节点IP  主节点端口"

notify_fault /etc/keepalived/scripts/redis_fault.sh

notify_stop /etc/keepalived/scripts/redis_stop.sh

}

5、 创建存放keepalived所用脚本的目录

make /etc/keepalived/scripts –p

6、 在步骤4中创建的目录下创建以下脚本:

redis_backup.sh

!/bin/bash

REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"

LOGFILE="/etc/keepalived/log/keepalived-redis-state.log"

echo "[backup]" >> $LOGFILE

date >> $LOGFILE

echo "Run SLAVEOF cmd ..." >> $LOGFILE

$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1

sleep 15

redis_check.sh

!/bin/bash

ALIVE=/usr/local/bin/redis-cli -h $1 -p $2 PING

LOGFILE="/etc/keepalived/log/keepalived-redis-check.log"

echo "[CHECK]" >> $LOGFILE

date >> $LOGFILE

if [[ $ALIVE == "PONG"  ]]; then :

echo "SUCCESS:reidis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1

exit 0

else

echo "FAILED:redis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1

exit 1

fi

redis_fault.sh

!/bin/bash

LOGFILE=/etc/keepalived/log/keepalived-redis-state.log

echo "[fault]" >> $LOGFILE

date >> $LOGFILE

redis_master.sh

!/bin/bash

REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"

LOGFILE="/etc/keepalived/log/keepalived-redis-state.log"

echo "[master]" >> $LOGFILE

date >> $LOGFILE

echo "Being master...." >> $LOGFILE 2>&1 

echo "Run MASTER cmd ..." >> $LOGFILE 2>&1

\$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 

sleep 10

delay 10 s wait data async cancel sync

echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE

\$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1

redis_stop.sh

!/bin/bash

LOGFILE=/etc/keepalived/log/keepalived-redis-state.log

echo "[stop]" >> $LOGFILE

date >> $LOGFILE

这些脚本从节点也需要复制过来一份

给这些脚本赋予执行权限

chmod a+x /etc/keepalived/scripts/*.sh

7、 启动redis跟keepalived软件

方案2部署步骤

1、 参考方案1部署步骤1,安装redis一主两从并启动

2、 sentinel配置(主从节点均需配置)

首先创建一个放置sentinel配置文件的目录

mkdir –p /etc/sentinel

然后将redis安装目录中的sentinel配置文件复制至/etc/sentinel下

cp /usr/local/src/reids-5.0.8/sentinel.conf  /etc/sentinel/

编辑sentinel.conf如下:

监听端口

port 26379

设置daemonize为yes,否则不会采用守护进程启动,启动命令会阻塞

daemonize yes

pidfile 加上端口

pidfile "/var/run/redis-sentinel_26379.pid"

自定义logfile文件的位置

logfile "/opt/redis/logs/sentinel_26379.log"

dir "/tmp"

sentinel都指向redis集群的主节点

sentinel monitor mymaster 主节点IP 主节点端口 2

acllog-max-len 128

sentinel deny-scripts-reconfig yes

sentinel resolve-hostnames no

protected-mode no

sentinel config-epoch mymaster 0

sentinel leader-epoch mymaster 0

3、 启动主从节点上的sentinel

nohup  redis-sentinel  /etc/sentinel/sentinel.conf &

方案3部署步骤

该步骤以三主三从为例,想搭建更多节点集群同理

1、 参照方案1部署步骤1,在三台机器上分别安装redis

2、 分别在三台机器上创建存放集群节点配置文件的文件夹

mkdir –p /etc/redis-cluster

mkdir /etc/redis-cluster/6379 /etc/redis-cluster/6380

3、 从redis安装目录中复制redis.conf至上面的6379跟6380中

cp /usr/local/src/reids-5.0.8/redis.conf  /etc/redis-cluster/6379

4、 修改配置文件内容如下:

(1)daemonize yes

(2)port 6379(根据目录名代表的端口号进行修改)

(3)pidfile /var/run/redis_6379.pid  # 把pid进程号写入pidfile配置的文件

(4)dir /usr/local/redis-cluster/6379/(指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据)

(5)cluster-enabled yes(启动集群模式)

(6)cluster-config-file nodes-6379.conf(集群节点信息文件,这里800x最好和port对应上)

(7)cluster-node-timeout 10000

(8)# bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)

(9)protected-mode  no(关闭保护模式)

(10)appendonly yes

如果要设置密码需要增加如下配置:

(11)requirepass 密码 (设置redis访问密码)

(12)masterauth 密码 (设置集群节点间访问密码,跟上面一致)

5、将上面修改的配置文件,复制到6380,修改第2、3、4、6项的端口号,可进行批量替换:%s/源字符串/目的字符串/g

6、另外两台机器也需做上面几步

7、分别启动6个redis实例

Redis-server /etc/redis-cluster/6379/redis.conf

8、创建redis集群

Redis-cli –a 密码 --cluster create –cluster-replicas 1 节点1IP:6379 节点1IP:6380 节点2IP:6379 节点2IP:6380 节点3IP:6379 节点2IP:6380

「其他文章」