redis集群实现有以下几种方式:

1.redis-cluster, 官方提供的集群搭建方案(过于重量级,比较适合后期数据量较大的时候的使用)

2.redis+keepalive 虚拟IP,多台配置非常复杂,不宜维护,需要 slaveof no one 脚本

3.redis+zookeeper 需要引入zookeeper,对现有代码变动较大

4.redis+sentinel redis自带监控中间件

本篇实现 redis+sentinel 星形架构

实验环境需要四台Redis服务器
192.168.10.11 redis11 主
192.168.10.12 redis12 从
192.168.10.13 redis13 从
192.168.10.14 redis14 从
192.168.10.100 VIP

使用后端模板创建四台虚拟机

[root@client 桌面]# cd /var/lib/libvirt/images/
[root@client images]# for i in {1..4}
> do
> qemu-img create -b centos7.qcow2  -f qcow2 redis$i.qcow2
> done

[root@client images]# cd /etc/libvirt/qemu/
[root@client qemu]# for i in {1..4}
> do
> virsh dumpxml centos7 > redis$i.xml
> done

[root@client qemu]# vim redis1.xml
<name>redis1</name>    //修改名称
....
<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2'/>
  <source file='/var/lib/libvirt/images/redis1.qcow2'/>    //修改前端镜像文件路径
  <target dev='vda' bus='virtio'/>
</disk>
....
:g/add/d      //删除add个性化参数

启用虚拟机并配置网络参数一次配置四台redis

[root@client qemu]# for i in {1..4}
> do
> virsh define redis$i.xml
> done
定义域 redis1(从 redis1.xml)
....

[root@client qemu]# for i in {1..4}; do virsh start redis$i; done
域 redis1 已开始
....

[root@client qemu]# for i in {1..4}; do virsh console redis$i; done

[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
ONBOOT="yes"
IPV6INIT="no"
TYPE="Etnernet"
BOOTPROTO="static"
IPADDR=192.168.10.11
PREFIX=24
GATEWAY=192.168.10.254
[root@localhost ~]# systemctl restart network
[root@localhost ~]# hostnamectl set-hostname redis11

四台节点配置host、yum、ssh秘钥这里不再演示

[root@redis11 ~]# for i in {11..14}      
> do
> ssh redis$i  yum -y install gcc gcc-c++ make    //所有节点安装依赖包
> done

部署master主机 192.168.10.11

[root@redis11 ~]# tar -xf redis-3.2.11.tar.gz 
[root@redis11 ~]# cd redis-3.2.11
[root@redis11 redis-3.2.11]# make && make install    //安装编译redis

[root@redis11 redis-3.2.11]# cd utils/
[root@redis11 utils]# ./install_server.sh     //初始化redis
....
Starting Redis server...
Installation successful!

修改redis运行参数

[root@redis11 utils]# /etc/init.d/redis_6379 stop
....
bind 192.168.10.11      //修改成本机IP

修改启动脚本

[root@redis11 utils]# vim /etc/init.d/redis_6379
....
IP="192.168.10.11"
...
   PID=$(cat $PIDFILE)
        echo "Stopping ..."
        $CLIEXEC -h $IP -p $REDISPORT  shutdown   //添加主机IP
        while [ -x /proc/${PID} ]
        do
        
[root@redis11 utils]# /etc/init.d/redis_6379 start      //启动服务并确认端口
Starting Redis server...
[root@redis11 utils]# ss -ntulp | grep 6379
tcp    LISTEN    0     128    192.168.10.11:6379    *:*     users:(("redis-server",pid=13531,fd=4))

[root@redis11 utils]# redis-cli -h 192.168.10.11 -p 6379     //登录查看服务运行状态
192.168.10.11:6379> PING
PONG

192.168.10.11:6379> info replication
role:master                       //角色master
connected_slaves:0      //没有slave

部署slave主机(安装步骤与上述相同)

[root@redis12 utils]# /etc/init.d/redis_6379 stop
[root@redis12 utils]# vim /etc/redis/6379.conf 
....
bind 192.168.10.12       //本机ip
slaveof 192.168.10.11 6379    //master主机 ip 端口


[root@redis12 utils]# vim /etc/init.d/redis_6379    //修改启动脚本
....
IP="192.168.10.12"
$CLIEXEC -h $IP -p $REDISPORT shutdown

[root@redis12 utils]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@redis12 utils]# ss -netstat | grep 6379

[root@redis12 utils]# redis-cli -h 192.168.10.12 -p 6379   //登录查看状态
192.168.10.12:6379> PING
PONG
192.168.10.12:6379> INFO replication
#Replication
role:slave      //角色slave
master_host:192.168.10.11    //谁是master
master_port:6379
master_link_status:up

依次启动另外两台slave主机与上述配置相同
登录主库查看slave状态

[root@redis11 utils]# redis-cli -h 192.168.10.11 -p 6379 -a 123456
192.168.10.11:6379> info replication
#Replication
role:master
connected_slaves:3          //已显示三台从库信息
slave0:ip=192.168.10.12,port=6379,state=online,offset=2003,lag=0    
slave1:ip=192.168.10.13,port=6379,state=online,offset=2003,lag=0
slave2:ip=192.168.10.14,port=6379,state=online,offset=2003,lag=0

部署sentinel

[root@redis11 ~]# cp /root/redis-3.2.11/sentinel.conf  /etc/redis/
[root@redis11 ~]# vim /etc/redis/sentinel.conf
....
bind 0.0.0.0              
port 26379
protected-mode no
daemonize yes
dir /tmp
sentinel monitor mymaster 192.168.10.11 6379 2       //master ip 票数
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 5000
sentinel client-reconfig-script mymaster /usr/local/bin/reconfig.sh    //开启故障切换脚本

[root@redis11 ~]# grep -Pv "^(#|$)" /etc/redis/sentinel.conf    //确认配置参数
bind 0.0.0.0
port 26379
protected-mode no
....

将sentinel配置文件拷贝到所有slave节点

[root@redis11 ~]# for i in {12..14}     
> do
> scp /etc/redis/sentinel.conf redis$i:/etc/redis/
> done

在所有redis服务器上添加脚本文件

[root@redis11 ~]# cat > /usr/local/bin/reconfig.sh << EOF
> #!/bin/bash
>   echo "$@" > /tmp/redis.log    //收集切换信息
> EOF

[root@redis11 ~]# chmod 755 /usr/local/bin/reconfig.sh    

在所有redis主机启动sentinel监控

[root@redis11 ~]# /usr/local/bin/redis-sentinel  /etc/redis/sentinel.conf 
[root@redis11 ~]# ss -ntulp | grep 26379
tcp    LISTEN     0      128       *:26379       *:*       users:(("redis-sentinel",pid=13747,fd=4))

[root@redis11 ~]# redis-cli -h 192.168.10.11 -p 26379
192.168.10.11:26379> PING
PONG
192.168.10.11:26379> INFO sentinel   
#Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.10.11:6379,slaves=3,sentinels=4  //状态slave3台 sentinel四台

测试主从切换—将master主机宕机之后查看主从状态

192.168.10.11:6379> shutdown

[root@redis11 ~]# cat /tmp/redis.log     //查看监本日志
mymaster observer start 192.168.10.11 6379 192.168.10.14 6379    //master已经切换到 192.168.10.14 这台主机

登录redis14 查看状态

[root@redis14 ~]# redis-cli -h 192.168.10.14 -p 6379
192.168.10.14:6379> INFO replication
#Replication    
role:master             //角色已经切换成master
connected_slaves:2         //还有两台从库
slave0:ip=192.168.10.12,port=6379,state=online,offset=34337,lag=1
slave1:ip=192.168.10.13,port=6379,state=online,offset=34337,lag=0

恢复redis11主机并加入集群

[root@redis11 ~]# /etc/init.d/redis_6379 start

再次查看redis14主机状态

192.168.10.14:6379> INFO replication
#Replication
role:master
connected_slaves:3        //三台slave,redis11主机已加入集群
slave0:ip=192.168.10.12,port=6379,state=online,offset=86514,lag=1
slave1:ip=192.168.10.13,port=6379,state=online,offset=86514,lag=1
slave2:ip=192.168.10.11,port=6379,state=online,offset=86655,lag=1     

问题:
客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时,主是变化的,所以ip地址也是变化的
客户端程序如何感知当前主redis的ip地址和端口呢?
redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name 就能得到当前主redis的ip和port。

解决方案1:
程序兼容,优势:扩展性好,运维成本低
劣势:开发成本高,连接变成 2 次

解决方案2:
vip 漂移,优势:程序端无感知,架构不需要改变
劣势:集群庞大时配置管理复杂,运维成本高

方案2:
增加配置切换脚本 sentinel.conf
sentinel client-reconfig-script mymaster /usr/local/redis/conf/reconfig.sh

在redis任意主机创建vip自动切换脚本并同步到其他主机(删除原脚本内容)

[root@redis11 ~]# > /usr/local/bin/reconfig.sh
[root@redis11 ~]# vim /usr/local/bin/reconfig.sh

#!/bin/bash
#args=(<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>)
#mymaster    leader  start   old.ip     old.port   new.ip  new.port

logger -p local0.info -t redis "${@:-NULL}"
vip="192.168.10.100/24"

read oldip newip <<<"$4 $6"

if $(ip -o a s |grep -q ${oldip:-0.0.0.0});then
     /usr/sbin/ifconfig eth0:1 down &>/dev/null
elif $(ip -o a s|grep -q ${newip:-0.0.0.0});then
     /usr/sbin/ifconfig eth0:1 ${vip}
/sbin/arping -q -c 3 -A ${vip%/*} -I eth0
fi

同步脚本到其他主机

[root@redis11 ~]# for i in {12..14} 
> do
> scp /usr/local/bin/reconfig.sh  redis$i:/usr/local/bin/ 
> done

在master主机部署VIP 192.168.10.100 (宕机并查看vip切换状态)

[root@redis14 ~]# ifconfig eth0:1 192.168.10.100/24
[root@redis14 ~]# ifconfig eth0:1
eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.10.100  netmask 255.255.255.0  broadcast 192.168.10.255
    ether 52:54:00:3a:1b:34  txqueuelen 1000  (Ethernet)


[root@redis14 ~]# ifconfig eth0:1
eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.10.100  netmask 255.255.255.0  broadcast 192.168.10.255
    ether 52:54:00:57:e8:ab  txqueuelen 1000  (Ethernet)
[root@redis14 ~]# /etc/init.d/redis_6379 stop    //将redis14宕机后再次查看vip已经不存在(vip漂移时间在3~5秒左右)

查找到master主机后ifconfig查看vip已经绑定上(这里不做过多演示)

GitHub 加速计划 / sentine / Sentinel
37
7
下载
alibaba/Sentinel: Sentinel 是阿里巴巴开源的一款面向分布式服务架构的流量控制、熔断降级组件,提供实时监控、限流、降级和系统保护功能,适用于微服务治理场景。
最近提交(Master分支:23 天前 )
4a419818 * Improved Date formatter * change in naming conv * change in datetime format * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> 15 天前
d9398b4f 16 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐