Redis高可用方案
前序
在多数后端项目中,缓存这块儿Redis属于一枝独秀。只要是个java程序员基本少不了跟redis打交道,无论是项目中实际应用或者跟面试官切磋。我们知道Redis虽然单机QPS也有好几万,但生产环境上基本没人敢上单机。因为分布式环境中,不稳定因素很多,万一哪天网线被刨断了或者服务器挂了。影响到客户就不得了了。那么为了应对Redis的单机故障,我们一般有如下的三种高可用方案。
Redis高可用方案
方案一(主从+keepalived+VIP)
适用场景:之前的单机模式下,在redis负载高时可能会崩溃。故给主节点增加从节点做备用节点,在主挂掉时立马提升为新主。该场景适用于redis负载不是很大,对redis高可用有需求并且客户端对主从切换无感的场景。
Keepalived:集群管理中高可用的一个服务软件,通过健康检查脚本去检测实例节点。当检查失败时会将对应节点的priority值减少。若主节点priority值比备用节点的小时,执行切换VIP脚本跟从节点升主脚本。
VIP:虚拟ip绑定至主节点,一旦主节点挂掉后,由keepalived重新绑定在新主节点上。
优点:应用端连接方面不用改变。
缺点:不能进行读写分离,主节点压力还是很大
修改点:客户端不需要修改。
方案二(主从+sentinel集群)
适用场景:在系统对redis请求并发高的情况下,方案1场景中主节点负载压力过高。
此时需要主从读写分离来减轻主节点压力,并增加缓存服务的高并发。客户端通过连接
Sentinel获取主从节点信息,并将自己的读写请求分别发送至主从节点进行请求分流,减轻主节点压力。
Sentinel哨兵:哨兵是一个运行在特殊模式下的 Redis 进程,哨兵主要负责的就是三个任务:监控、选主和通知。哨兵运行过程中周期性向所有主从节点发送PING命令,主从节点会给哨兵回复PONG命令。若主节点未在规定时间内回复哨兵,则哨兵标记该主节点为主观下线,之后会通知其它哨兵节点对该主节点进行检测。如果超过一半哨兵都判定为主观下线,则该主节点会被标记为客观下线。随后从该主节点的从节点中选出新主节点。之后会通知其余从节点进行replicaof命令和新主节点建立联系,通知客户端让他们把操作命令发到新的主节点上。
读写分离:在该模式下为分担master节点的请求压力,可在客户端上增加读写分离的逻辑,之后读请求走从节点,写请求走主节点。
增加从节点:
启动新的节点并在新节点上执行如下命令即可
slaveof IP PORT(IP和PORT是需要关联的主节点ip和端口)
优点:高可用并能有效减少master上的请求压力
缺点:修改东西较多,如果写请求多,主节点依然有压力大的风险。
修改点:
1、 客户端连接方式得改为sentinel模式,
2、 要实现读写分离得修改Jedis连接相关的逻辑
方案三(cluster集群)
适用场景:当系统对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 download.redis.io/releases/re…
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−p1 -p 1−p3"
LOGFILE="/etc/keepalived/log/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Run SLAVEOF cmd ..." >> $LOGFILE
REDISCLISLAVEOFREDISCLI SLAVEOF REDISCLISLAVEOF2 3>>3 >> 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−p1 -p 1−p2 PING ALIVE">>ALIVE" >> ALIVE">>LOGFILE 2>&1
exit 0
else
echo "FAILED:redis-cli -h 1−p1 -p 1−p2 PING ALIVE">>ALIVE" >> 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−p1 -p 1−p3"
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 22 23 >> $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
转载自:https://juejin.cn/post/7108321375202312222