相关内容:
【Redis】持久化操作(RDB、AOF)——分布式缓存(一):https://blog.csdn.net/lucas161543228/article/details/125111930?spm=1001.2014.3001.5501

一、Redis集群 - 主从模式
Redis集群总共有三种模式:主从模式、哨兵模式和分片集群。主从模式是其中最简单的模式,这种模式中,Redis被分为主节点(master)和从节点(slave/replica) 。主节点可以进行读、写操作,而从节点一般只能进行读操作,如果在从节点上进行写操作,Redis会报错。主节点和从节点会进行数据同步,使节点上的数据保持一致。
1、搭建主从架构
在这里插入图片描述
假设我们现在有3台计算机A、B、C作为Redis节点,我们要用它们来搭建主从架构,把A作为master(主节点)。
① 基本配置:首先,我们要在这3个节点上都安装。为保证这3个节点的Redis状态是一样的,因此把A的Redis配置文件复制并覆盖另外两个节点的Redis配置文件。然后启动3个节点上的Redis。
② 开启主从关系:要配置主从可以使用replicaof或者slaveof命令,这两条命令是一样的,只是Redis在5.0版本之后把从节点的名字从slave改成了replica。
有两种方式可以进行配置:临时和永久。

  • 永久配置:在从节点的Redis配置文件(通常是redis.conf)中添加一行配置:slaveof <masterip> <masterport>。其中,后两个参数分别是主节点的ip地址和Redis端口号。
  • 临时配置:使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):slaveof <masterip> <masterport>。

2、主从数据同步
有两种同步方式:全量同步和增量同步。
全量同步
主从第一次建立连接时,会进行一次全量同步,将master节点的所有数据都拷贝给slave节点。此外,当增量同步失败的时候,也会进行全量同步。全量同步的流程如下(从上到下依次执行):
在这里插入图片描述
在第二阶段中,master节点会进行一次bgsave操作生成RDB文件,再把这个RDB文件发给slave节点。我们知道,在bgsave期间,Redis仍然能进行服务,如果在这段时间内,master执行了写操作,那么主从节点之间的数据就会产生差异。因此,master节点会把bgsave执行期间的所有命令都记录到repl_backlog(上图把名字写错了)文件中,然后在发送RDB文件之后把repl_backlog中的命令发送给从节点(图中的2.1.1操作)。从节点会执行这些命令,从而保证主从间的数据是一致的。

Q:一个问题,master是如何得知slave节点是第一次与它建立连接的呢?
A:关于这个问题,首先我们要了解两个概念Replication Id和offset:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid。
  • offset:偏移量。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

slave要进行数据同步时,需要告诉master自己的Replication Id和offset。
由于slave原本也是一个master,因此它也有自己的Replication Id和offset,并且和master的不一样。
master判断发现slave发送来的Replication Id与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。此外,master会将自己的Replication Id和offset都发送给这个slave,因此从,经过第一次全量同步之后,slave的Replication Id就和master的一样了。
将刚才的图升级一下:
在这里插入图片描述
总结一下:
在这里插入图片描述
增量同步
通过bgsave生成RDB是一个比较消耗性能的操作。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步。
增量同步就是只更新slave与master存在差异的部分数据(与offset有关了)。
在这里插入图片描述
首先,我们来再次认识一下repl_backlog文件。
这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。
repl_baklog中会记录Redis处理过的命令日志及offset,包括master当前的offset,和slave已经拷贝到的offset:
在这里插入图片描述
如果master和slave节点的offset没有相差超过一圈,也就是说slave少于master的那部分数据在repl_backlog中都能找到的时候,主从节点间的数据同步就会通过增量同步来完后,也就是从repl_backlog文件中找出slave的offset到master的offset的这部分内容(是一些命令),然后发送给slave节点,slave收到之后再执行这些命令。
但如果master和slave节点的offset相差太多了,导致slave缺的数据已经被新数据覆盖了,如下图所示,那么就会把增量同步改成全量同步操作。在这里插入图片描述
在这里插入图片描述
3、主从同步优化
在这里插入图片描述
主-从-从链式结构:
在这里插入图片描述
4、小结
在这里插入图片描述
二、Redis集群 - 哨兵模式(Sentinel)
1、认识哨兵模式
在主从模式中,如果master节点故障了,Redis就无法对外提供写操作,除非我们手动将某一个slave节点设置为新的master节点。
为解决这个问题,我们可以使用哨兵模式,哨兵能够在后台监控master节点,当发现master节点发生故障时,哨兵会自动将某一个slave节点升级为master节点(可以设置选择slave节点的规则)。
哨兵模式的结构图如下所示(Sentinel即哨兵进程,我们在此处设置了3个哨兵进程):
在这里插入图片描述
Sentinel在本质上是一个独立的进程。Sentinel的作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作。
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主。
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端。

2、Sentinel是如何进行监控的
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个节点发送ping命令,并根据节点的回应情况将它们分为主观下线客观下线两种状态。

  • 主观下线:如果某Sentinel节点发现某节点未在规定时间响应,则认为该节点主观下线。
  • 客观下线:若超过指定数量(quorum)的Sentinel都认为该节点主观下线,则认为该节点客观下线。quorum值最好超过Sentinel实例数量的一半。

3、哨兵模式是如何进行故障恢复的
一旦发现master故障,Sentinel会在slave中选择一个作为新的master,选择的流程如下:

  • 首先,判断各个slave节点与master节点断开时间的长短,如果超过指定值(down-after-milliseconds * 10)则排除该slave节点。
  • 然后判断slave节点的slave-priority值(在slave节点的Redis配置文件中进行配置),值越小表示优先级越高。
  • 如果slave-prority一样,则判断slave节点的offset值,值越大说明数据越新,则优先级越高。
  • 最后是判断slave节点的运行id大小,值越小则优先级越高。

Q:选出新的master节点之后,要如何实现切换呢?
A:流程如下(假设当前选中了节点slave1作为新的master):

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master。如果没有设置哨兵模式,也可以手动执行这条命令slaveof no one来使一个slave节点变成master节点。
  • sentinel给其它所有的slave发送slaveof 192.168.150.101 7002命令(这里的IP和端口号是slave1节点的IP和端口号),让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点(原先的master)标记为slave,当故障节点恢复后会自动成为新的master的slave节点。

在这里插入图片描述
4、搭建哨兵集群
①准备配置文件:新建3个目录(如果要配置的哨兵数量为3),每个目录对应一个哨兵,每个目录下新建一份新的Sentinel配置文件(sentinel.conf),如下所示:
在这里插入图片描述
在这里插入图片描述
②通过redis命令启动哨兵:
在这里插入图片描述
5、总结
在这里插入图片描述
6、RedisTemplate的哨兵模式
Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。通过RedisTemplate配置哨兵集群的流程如下:
①引入依赖。
在这里插入图片描述
②配置Redis的地址。
在这里插入图片描述
③在启动类中添加一个bean,这个bean配置了Redis的读写策略。
在这里插入图片描述在这里插入图片描述
补充:哨兵除了监控Redis节点,也会监控其他哨兵。

三、Redis集群 - 分片集群模式(Sentinel)

1、认识分片集群
在这里插入图片描述
为解决这两个问题,我们可以采用分片集群,分片集群的结构如下图所示:
在这里插入图片描述
分片集群具有以下特点:

  • 集群中有多个master,每个master保存不同数据(将海量数据分散地存储在多个master中)。
  • 每个master可以有自己的slave节点。
  • master之间通过ping监测彼此健康状态(实现了哨兵的功能)。
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点。

2、散列插槽
在Redis中,有一个散列插槽(hash slot)的概念(类似于哈希表中)。Redis会根据key的有效部分计算插槽值,然后把数据存储到对应的插槽中去。
计算插槽值的方式:
①首先获取key的有效部分。

  • 如果key中包含"{}",且“{}”中至少包含1个字符,则“{}”中的部分是有效部分,如{phone}_redmi,这个key的有小部分为“phone”。
  • key中不包含“{}”,则整个key都是有效部分,如phone_redmi
    ②根据有效部分计算插槽,计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

数据key不是与节点绑定,而是与插槽绑定。Redis总共有16384个插槽,Reids会将这些插槽分配给各个节点,当我们读取或者写入数据时,会根据数据的key计算出插槽,然后到对应的节点上进行操作。
【个人有个猜想,当我们没有使用集群时,Redis节点只有一个,所以所有的插槽都分配给该节点了,因此我们没有感受到插槽这个东西。未经验证,仅做记录。】
举个例子:
在这里插入图片描述
小结:
在这里插入图片描述
3、集群伸缩(添加或删除集群节点)
假如现在我们要往集群中加一个新的master节点,并向其中存储 num = 10。那么我们需要实现两个功能:

  • 添加一个节点到集群中。
  • 将部分插槽分配到新插槽(插槽转移)。

添加节点到集群中:
在这里插入图片描述
比如:redis-cli --cluster add-node 192.168.150.101:7004 192.168.150.101:7001

这里把节点192.168.150.101:7004加入到节点192.168.150.101:7001所在的集群中。作为master节点加入。因为如果要作为slave节点加入的话,在这句命令中还需要加上--cluster-slave--cluster-master-id \<arg>.

转移插槽:
前面提到,我们要把keyi为num的数据存储到新加入的这个节点中,因此我们需要先看看num在哪个插槽上,然后把包括num的插槽在内的一部分插槽分配给新节点。分配的时候,这些插槽可能在原先的节点上已经有数据了,因此需要把这些数据转移过来。
具体例子如下(通过计算得知num的插槽为2765,因此我们把0~3000的插槽从原节点(7001)转移到新节点(7004)来):
①与7001建立连接:
在这里插入图片描述
得到如下反馈,询问我们要转移多少插槽
在这里插入图片描述
输入我们要转移的插槽数量(3000),得到如下反馈,询问我们要把这些插槽转移到哪个节点去
在这里插入图片描述
输入7004节点的id。

----补充说明----
如何得到节点id?在第①步操作(建立连接时),当我们输入并执行reshard命令之后会显示各个节点的信息,其中包括各个节点的id,如下图所示:
在这里插入图片描述

----补充说明----

在这里插入图片描述
输入7004节点的id之后,得到反馈(如上图所示)询问这些插槽该从哪个节点移动过来。我们有3种输入方式:
在这里插入图片描述
这里我们要从7001获取,因此填写7001的id:
在这里插入图片描述
填完后,点击done,这样插槽转移就准备好了。最后再按照提示输入yes即可完成转移。

补充:通过help可以查看操作集群的命令:
在这里插入图片描述
4、故障恢复
当集群中有master节点故障时,其他master节点如果确定该master下线了,就会自动提升该master的一个slave节点为新的master(与哨兵模式一样)。
手动进行故障转移
利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:
在这里插入图片描述
在这里插入图片描述
5、搭建分片集群
Redis5.0以后,集群管理已经集成到了redis-cli中,格式如下(后面的这些IP和端口代表要加入集群的Redis节点):

redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003

命令说明:

  • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令
  • create:代表是创建集群
  • –replicas 1或者–cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master

6、ReidsTemplate访问分片集群
与哨兵模式基本一致。
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐