redis集群高可用架构(代码片段)

小乐乐的天台 小乐乐的天台     2023-01-17     106

关键词:

1、Redis高可用集群

1.1、Redis高可用集群模式和哨兵模式方案比较

哨兵模式

上图是Redis的哨兵模式
在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master。哨兵模式一般会有以下几个问题
1、哨兵的配置略微复杂。
2、当主节点挂掉之后,有访问瞬断的情况
3、由于只有一个可写的主节点,没法支持很高的并发。
4、由于只有一个主节点,数据存储能力有限,如果节点内存设置过大,在数据持久化或恢复时会影响性能。

高可用集群模式

redis集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。

1.2、Redis高可用集群搭建

redis集群需要至少三个master节点,我们这里搭建三个master节点,并且给每个master再搭建一个slave节点,总共6个redis节点,这里用三台机器部署6个redis实例,每台机器一主一从,搭建集群的步骤如下:


1、修改相应需要的配置,这里我为了规范,修改了很多路径配置:
普通配置

配置含义
daemonize yes默认Redis实例后台启动
port 7001redis实例对外映射端口
pidfile /var/run/redis_7001.pid进程号记录文件路径
logfile “…/logs/7001.log”日志路径
dir …/data/7001/快照文件和集群节点信息文件路径
protected-mode no设置为no,外围机器可以访问
appendonly yes开启aof快照
# bind 127.0.0.1注释掉回环地址
requirepass ale设置redis访问密码
masterauth ale设置集群节点间访问密码

重要配置

配置含义
cluster‐enabled yes启用集群模式
cluster‐config‐file nodes‐8001.conf集群节点信息文件
cluster‐node‐timeout 5000集群访问超时时间

这里粘贴上我修改后的配置文件,可参考
链接:https://pan.baidu.com/s/1_pfVzkIf_vpfkrMmc6N_dQ
提取码:5kcu


2、启动6个redis实例。


3、为了防止防火墙等原因,先在三台服务器上将防火墙关闭,以及禁止开机启动。
systemctl stop firewalld # 临时关闭防火墙
systemctl disable firewalld # 禁止开机启动


4、任意找一台机器的客户端,输入下面命令
这里的 -a 后面跟的是密码,–cluster-replicas 1 后面的 1 代表每个master下面都有一个从节点,默认会将我们命令中的前三个设置为主节点,从节点是随机的。
./redis-cli -a ale --cluster create --cluster-replicas 1 192.168.231.132:7001 192.168.231.133:8001 192.168.231.134:9001 192.168.231.132:7002 192.168.231.133:8002 192.168.231.134:9002
执行完成,如下图所示:

这里的三个段表示我们我们的三个主节点分别对应这三个段,每当我们set一个值时,会先计算这个key的hash值,根据这个位桶数组取模判断是放在哪个节点中,三个节点的数据互相不重复,然后我们输入yes,会出现下图所示:

出现上图现象就代表成功。


6、集群操作:
连接客户端:./redis-cli -a ale -c -h 192.168.231.134 -p 9001
查看集群信息:cluster info
查看节点列表:cluster nodes
关闭集群:./redis-cli -a ale -c -h 192.168.231.134 -p 9001 shutdown

2、Java操作Redis集群

创建一个Maven项目,引入相应的jar包

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.3</version>
</dependency>
public class JedisClusterTest 
    public static void main(String[] args) throws IOException 

        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);

        Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort("192.168.231.132", 7001));
        jedisClusterNode.add(new HostAndPort("192.168.231.132", 7002));
        jedisClusterNode.add(new HostAndPort("192.168.231.133", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.231.133", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.231.134", 9001));
        jedisClusterNode.add(new HostAndPort("192.168.231.134", 9002));


        JedisCluster jedisCluster = null;
        try 
            //connectionTimeout:指的是连接一个url的连接等待时间
            //soTimeout:指的是连接上一个url,获取response的返回等待时间
            jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "ale", config);
            System.out.println(jedisCluster.set("cluster", "ale"));
            System.out.println(jedisCluster.get("cluster"));
         catch (Exception e) 
            e.printStackTrace();
         finally 
            if (jedisCluster != null) 
                jedisCluster.close();
            
        
    

3、Redis集群原理分析

Redis Cluster 将所有数据划分为 16384 个 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。
在每一次连接时,客户端会将集群的信息缓存到本地,这样定位一个节点时就可以定位到是要放到集群的哪个节点上。
但有时候服务端改变了但是客户端没有变,还需要纠正机制来实现槽位信息的校验调整

3.1、槽位定位算法

当我们set一个值的时候,我们会拿到这个值的 key ,对其进行 CRC16 算法,然后再和 16384-1 取 & 运算。
也就相当于和 16384 取模运算。

public static int getSlot(String key) 
    key = JedisClusterHashTagUtil.getHashTag(key);
    return getCRC16(key) & 16383;

3.2、跳转重定位

当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表。

3.3、Redis集群节点间的通信机制

redis cluster节点间采取gossip协议进行通信维护集群的元数据(集群节点信息,主从角色,节点数量,各节点共享的数据等)有两种方式:集中式和gossip


集中式:

优点在于元数据的更新和读取,时效性非常好,一旦元数据出现变更立即就会更新到集中式的存储中,其他节点读取的时候立即就可以立即感知到;不足在于所有的元数据的更新压力全部集中在一个地方,可能导致元数据的存储压力。
很多中间件都会借助zookeeper集中式存储元数据。

gossip:

gossip协议包含多种消息,包括ping,pong,meet,fail等等。
meet:某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信;
ping:每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据(类似自己感知到的集群节点增加和移除,hash slot信息等);
pong::对ping和meet消息的返回,包含自己的状态和其他信息,也可以用于信息广播和更新;
fail:某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了。
gossip协议的优点在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力;缺点在于元数据更新有延时可能导致集群的一些操作会有一些滞后。


gossip通信的10000端口
每个节点都有一个专门用于节点间gossip通信的端口,就是自己提供服务的端口号+10000,比如7001,那么用于节点间通信的就是17001端口。
每个节点每隔一段时间都会往另外几个节点发送ping消息,同时其他节点接收到ping消息之后返回pong消息。

3.4、Redis集群选举原理

当slave发现自己的主节点挂掉之后,就会去选举新的主节点,因为从节点(slave)不止一个,就会出现竞争的关系。
1、slave发现自己的master变为FAIL。
2、将自己记录的集群currentEpoch(选举次数)加1,并广播FAILOVER_AUTH_REQUEST(需要重新选取主节点) 信息。
3、其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK(确认合法可以推荐当前从节点为新的主节点),对每一个epoch(从节点)只发送一次ack。
4、从节点收到主节点的确认信息。
5、当收到所有集群节点一半以上时就会把自己置为主节点。
6、slave广播Pong消息通知其他集群节点。


这个时候我们会发现一个问题,就是如果说从节点们都平票了怎么办,平票就需要重新选举,重新走一次上面的流程,那如果每一次都平票了怎么办,其实这种问题redis有自己的一个解决办法,那就是每一个从节点不是一旦感知到主节点没有响应就直接发的,而是会有一个延迟算法,在这个时间经过之后,才会向外发送请求,自荐自己要当主节点。
历史版本有一个延迟时间算法:
DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)。

3.5、Redis集群为什么至少需要三个master节点,并且推荐节点数为奇数?

因为新master的选举需要大于半数的集群master节点同意才能选举成功,如果只有两个master节点,当其中一个挂了,是达不到选举新master的条件的。
奇数个master节点可以在满足选举该条件的基础上节省一个节点,比如三个master节点和四个master节点的集群相比,大家如果都挂了一个master节点都能选举新master节点,如果都挂了两个master节点都没法选举新master节点了,所以奇数的master节点更多的是从节省机器资源角度出发说的。

3.6、Redis集群对批量操作命令的支持

我们正常使用 mset 来批量设置值的时候,如果计算出多个key值的slot值不相等,则会直接报错,如下图所示:

Redis集群给我们提供了一个大括号,当我们加上这个大括号之后,计算solt值时就只会计算大括号里面的数据,就是person的hash值,如下图所示:

4、Redis集群可能会遇到的问题

4.1、网络抖动

所谓的网络抖动就是集群中由于网络问题突然从节点就和主节点发生了瞬断,这个时候按照原理来说的话就应该重新选取主节点了,但是这个时候主节点不一定是挂掉,可能只是在很短的时间里网络原因没有联通而已,所以redis给我们提供了 cluster-node-timeout 参数,可以设置时间,当超过这个时间还是没有连接上,就判定这个节点挂了。
如果没有这个参数,一旦访问不同主节点就去选举,就会造成一个集群节点中出现多个主节点,这就会产生脑裂问题。

4.2、集群脑裂数据丢失问题

当一个集群节点中出现了多个主节点时,如果这两个主节点都可以写数据,然后过了一段时间,网络恢复,原来的那个主节点又变成了从节点,那么在这一段时间写到原来主节点的数据就会丢失,redis对其的解决办法就是配置下面这一个信息:
解决方案:
min-replicas-to-write 1
// 写数据成功最少同步的slave数量,如果达不到这个数量,就不会写成功。

4.3、集群是否完整才能对外提供服务

这里其实涉及到一个参数。
当redis.conf的配置cluster-require-full-coverage为no时,意思是大集群里面有好多小集群,当有一个小集群的主节点挂掉之后,已经没有从节点给它顶上的时候,说明这个小集群已经瘫痪掉,当上面的配置为no时,整个的集群还是可用的,如果为yes,整个集群就不能用了。

redis高可用架构-redis集群,一文get三种方式(代码片段)

...解决,但是redis3.0中提供了解决方案。就是无中心化集群 查看详情

如何保证redis高可用和高并发(主从+哨兵+集群)(代码片段)

...那么如何保证Redis的高并发和高可用?Redis主要有三种集群方式用来保证高并发和高可用:主从复制,哨兵模式和集群。2.主从复制在分布式系 查看详情

redis高可用架构之cluster集群和分⽚(代码片段)

高可用架构之Cluster集群和分⽚1.前言2.Cluster模式介绍2.1什么是Cluster模式?2.2为什么需要Cluster模式?2.2.1垂直拓展(scaleup)和水平拓展(scaleout)2.2.2RedisCluster提供的好处2.2.3RedisCluster和replication+sentinel如... 查看详情

linux企业运维——k8s高可用集群架构搭建详解(代码片段)

K8s高可用集群文章目录K8s高可用集群一、K8s高可用集群架构原理二、实验环境三、K8s高可用集群架构搭建3.1、负载均衡Loadbalancer部署—haproxy3.2、Docker部署3.3、K8s集群部署3.4、K8s集群添加worker节点四、集群高可用性能测试一、K8s... 查看详情

linux企业运维——k8s高可用集群架构搭建详解(代码片段)

K8s高可用集群文章目录K8s高可用集群一、K8s高可用集群架构原理二、实验环境三、K8s高可用集群架构搭建1、负载均衡Loadbalancer部署—haproxy2、Docker部署3、K8s集群部署4、K8s集群添加worker节点四、集群高可用性能测试一、K8s高可用... 查看详情

mysql高可用集群架构-mha架构(代码片段)

简介MHA(MasterHighAvailability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过... 查看详情

redis技术专题「高可用技术基础」一同分析一下redis高可用的“基石”之主从架构的本质原理解析(代码片段)

...:持久化、主从复制(及读写分离)、哨兵和集群(Cluster)。📕📕持久化:侧重解决的是Redis数据的单机备份问题(从内存到硬盘 查看详情

redis进阶-高可用:集群(代码片段)

...受单机限制,以及无法实现写操作的负载均衡。Redis集群解决了上述问题,实现了较为完善的高可用方案。本文将详细介绍集群,主要内容包括:集群的作用; 查看详情

redis的高可用实现方案:哨兵与集群(代码片段)

...从复制主从复制概念主从复制的作用主从复制流程:集群:概念:数据存储原理:集群的功能限制:集群的通信原理 查看详情

❤️万字长文总结❤️一篇学会redis高可用✔集群✔搭建详细教程(代码片段)

...、Windows域控Exchange架构今日重点:今天总结一下Redis集群高可用的搭建流程【惊喜推荐+优质资源见文末,建议收藏!!!】建议:收藏+实操,一定要自己来一遍哦。一、 查看详情

❤️万字长文总结❤️一篇学会redis高可用✔集群✔搭建详细教程(代码片段)

...、Windows域控Exchange架构今日重点:今天总结一下Redis集群高可用的搭建流程【惊喜推荐+优质资源见文末,建议收藏!!!】建议:收藏+实操,一定要自己来一遍哦。一、 查看详情

redis单节点➤redissentinel高可用➤rediscluster集群(代码片段)

...部署Redis数据节点部署Sentinel节点部署技巧四、RedisCluster集群准备节点节点握手分配槽redis-trib.rb搭建集群一、Redis单节点Redis安装之后,src目录下多了几个以redis开头可执行文件& 查看详情

redis单节点➤redissentinel高可用➤rediscluster集群(代码片段)

...部署Redis数据节点部署Sentinel节点部署技巧四、RedisCluster集群准备节点节点握手分配槽redis-trib.rb搭建集群一、Redis单节点Redis安装之后,src目录下多了几个以redis开头可执行文件& 查看详情

linux云计算-mysql-高可用集群架构-mha架构(代码片段)

文章目录部署MHA高可用集群mysql-MHA群环境说明配置所有节点的ssh免密码登录安装mha-node安装MHAManager安装mysql5.7配置mysql主从环境配置MHA管理用户配置MHAMHA配置检查实战-故障转移以及故障恢复实战-故障转移故障恢复后重新加入mysql... 查看详情

redis高可用架构之哨兵模式-sentinel(代码片段)

Redis高可用架构之哨兵模式-Sentinel1.前言2.RedisSentinel哨兵集群搭建2.1一主两从2.2三个哨兵3.RedisSentinel原理剖析3.1什么哨兵模式3.2哨兵机制的主要任务3.2.1监控(1)每1s发送一次PING命令(2)PING命令的回复有两种情况&... 查看详情

redis的高可用实现方案:哨兵与集群(代码片段)

...从复制主从复制概念主从复制的作用主从复制流程:集群:概念:数据存储原理:集群的功能限制:集群的通信原理:补充:Gossip协议Gossip协议工作流程示例Gossip协议优点Gossip协议消息分类高可用什么... 查看详情

微服务架构eureka集群高可用配置(代码片段)

工具:idea环境:java8、maven3版本:springboot 1.5.15.RELEASE1.搭建springbooteureka项目 2.pom.xml添加相应依赖,如下:<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmln 查看详情

redis实战搭建高可用架构(代码片段)

...近在看关于redis缓存方面的知识,今天就来个Redissentinel高可用架构,实战开始之前,先看看sentinel的概念 什么是redis-sentinel  Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如mast... 查看详情