Sentinel和Cluster

Sentinel哨兵模式

image.png

哨兵的作用

  • 监控节点状态
  • 故障转移
  • 通知

监控节点状态

  1. **Sentinel****每秒钟****所有的redis实例**发送一个**ping**命令,如果redis实例返回**pong**,则说明该redis在**正常提供服务**
  2. **Sentinel**可能会由于**网络或其他的原因导致命令**没有成功发送或没有成功接收到pong返回值,因此需要引入多个哨兵,两个哨兵当一个成功返回另一个没有时也无法判断,因此Redis主从中**最少设立三个哨兵**
  3. 当单个**Sentinel**没有收到redis的请求时,此时该**Sentinel**则认为该redis为**客观下线**。当集群中**客观下线**的数量达到阈值(**quorum**)此时则会认为该redis实例**主观下线**

故障转移

  1. **Sentinel**集群发现某个节点已经**主观下线**,此时会从slave节点中选取出一个作为新的Master节点
  2. 会根据 slave节点和master节点**断开的时间长短****优先级****offset进度**等条件进行判断从而选举出新的Master节点
  3. 在选举出新的Master节点后,**Sentinel**集群会对该Slave节点发送 master命令,使该**slave**节点变为**Master**
  4. 同时对其他的**所有Slave节点**发送命令,使其他所有的slave节点变为Master的slave节点
  5. 此时其他的slave都会重新对该Master节点进行**全量同步**
  6. 最后哨兵会将原故障的Master节点设定为**新Master节点的slave**,在节点重新恢复服务后会重新进行数据的同步

通知

  • 当出现故障转移后,哨兵会向**redistemplate**发送通知,使得可以即使的进行主从库的切换

Sentinel脑裂问题

  1. 此时如果出现有**Master节点和哨兵与集群断开连接**的情况,即出现了**脑裂**情况。即客户端仍然在对原Master节点进行写操作,集群中又选举出了新的Master,此时则会存在两个Master节点。
  2. 此时客户端仍然在对该节点进行读写操作,而此时会出现问题,因为**读到的数据可能是旧的数据**,并且**写入的数据也会丢失**,因为该Master节点在断开连接后,会从剩余的Slave节点中重新选举出新的Master节点
  3. 此时原先断开的Master节点则会作为Slave节点重新连接,因此先前客户端对原Master节点的写操作可能会丢失
  4. 因此则需要进行配置,防止在脑裂情况下出现数据的问题,可以配置限制参数,**写入Master节点最少要写入的slave节点数**,使得在发生脑裂的情况下,使得Redis节点**不接受写**操作,从而保证数据问题。但这样会**降低Redis的可用性**
//Master节点至少写入的salve数量 如果为0则不开启此功能
//当有3个节点时,可以设置为1,当一个主节点断开连接后,此时该节点不会接受新的写请求
min-replicas-to-write 1
//Master节点在经过这段时间后获取到响应  就会认为该节点失联  停止接受新的写入命令请求
min-replicas-max-tag 10

Cluster集群模式

为什么需要Cluster

**Sentinel**提供了故障转移和读写分离的能力,提高了Redis的**读性能**。但是如果有**大量写操作**时,只有主库处理写操作的能力不足。同时在**Sentinel**架构中,只能存储**一个节点**的数据,在数据量较大的情况下进行数据的存储是不够的。因此需要Cluster支持节点的**动态扩容**,从而环节数据的**存储压力**以及**写操作压力**

Cluster基础架构

  1. **Cluster**架构中最少需要**三个Master节点**,每个Master节点**最少需要有一个Slave节点**,因此在Cluster架构中,最少需要有**6个节点**
  2. **Cluster**中的Slave节点与Sentinel架构中不同的是,Cluster架构中的**Slave节点不对外提供读服务**,仅用做于对应**Master节点的备份使用**,在对应Master节点宕机后,会从对应的Slave节点中选举出新的Master节点进行替换。
  3. Cluster节点中会通过**key的有效部分**计算出对应的Hash值,在与16384进行取余后,从而最终获取到该key对应的**slot插槽**。Redis会根据该插槽进行查询,因此在Cluster中连接到任意Master节点最终都能够查询到数据,因为在计算出插槽后会向**对应的Master**进行请求,如果正在处于**扩容或缩容**状态,会**返回正确的Master地址**,客户端再次进行请求,直至真正请求到到插槽所在的Master节点,最终进行数据的返回。

Cluster的节点扩容或缩容

扩容
  1. 在为Cluster节点扩容时,需要配置 新节点的ip和端口号,和要加入的集群中其中一个节点的ip和端口号,用于通知集群中的其他节点
  2. 新节点的进入默认为Master节点,但是也可以设置为某个Master节点的Slave节点
  3. 新的节点加入后不会有数据保存,因为此时新的节点中并不持有slot插槽,因为Redis中数据是与插槽绑定的。需要将其他Master节点的插槽分配到新节点中,才能顺利让该节点中存储数据。
缩容
  1. 在删除某个节点时,需要先将该节点上的插槽分配给其他Master节点,在一个节点上仍然持有插槽时,无法删除该节点。

Cluster的分片算法

  1. **Cluster**没有通过**一致性哈希**进行数据的分配,而是采用了**插槽机制**
  2. 总共有16384个插槽,分配到不同的Master节点上,多个key会对应一个插槽
  3. Cluster中Hash的计算函数是Crc16,返回值的范围在0~65535,Hash值的计算是通过该key的有效部分,如果key中**不存在{}**,则key的**全部部分都是有效部分**,如果**存在{}**,并且其中包含最少一个字符,则**括号内的所有部分为有效部分**
  4. 在进行操作时,会先使用该key的有效部分计算该key所对应的Hash值,再通过Hash值对16384做取余操作,即得到该key所对应的**插槽位置**
  5. **客户端**中保存着**插槽与Master节点的对应关系的缓存**,通过计算出的插槽位置,程序会向对应的Master节点发送请求,如果插槽位置正确则返回正确的数据。
  6. 如果插槽的位置不正确,例如遇到**扩容缩容**等场景,则该Master节点会**告知客户端正确的地址**

image.png

为什么Cluster的插槽是16384个

  1. Cluster的Hash函数返回的范围在**0~65535**,理论上可以一直65536个插槽
  2. 但是因为**gossip**进行通信,每个节点都会向**所有Master节点**发送**ping**命令进行心跳的判断,ping命令需要发送该节点的**插槽信息**,并且**Master节点越多**,需要发送的**心跳请求也就越多**。都会发送该节点的插槽信息,如果是要65536个插槽,会占用更多的空间,并且**16384已经足够用**,因为Cluster不会设置过多的主节点
  3. 因为主节点之间通过gossip协议进行通信,在每个节点之间进行消息的通信包含该节点的插槽信息。插槽信息中包含一个bitmap,其中如果是该节点持有的插槽即设置为1,在消息传递的过程中会进行压缩,bitmap中的1越多也就导致压缩率变低,而如果设置为过大的插槽数,则会导致bitmap压缩率变低,从而增大了网络的开销。

Cluster在扩容缩容期间可以提供服务吗

Cluster针对这个问题提供了两种重定向策略

  1. **ASK** 重定向:**暂时**重定向,不会更新节点信息,后续请求仍然发送到**旧节点**
  2. **MOVED** 重定向:**永久**重定向,会更新节点信息,后续请求将会发送到**新节点**

当客户端向将要进行插槽转移的节点发送请求时

  1. 如果该插槽**还在Master节点**内,则直接返回对应的数据
  2. 如果该插槽已经在**迁移的过程中**,但是该key的**数据还保留在该节点**中,则也会**直接返回**
  3. 如果该插槽已经在迁移的过程中,并且该key的**数据也已经被转移到其他节点**,此时该节点则会向客户端发送**ASK重定向**并携带上**转移后节点的信息**,此时会**强制**客户端向新节点发送**ASKING**请求。如果可能新节点**还未完全将数据完全导入**,如果是还没有导入的插槽,则会返回 **TRYAGAIN**
  4. 在后续客户端请求该key时,因为ASK请求并不会同步新节点信息,因此在后续请求**仍然会请求之前的Master节点**
  5. 直到原Master节点的该插槽**完全转移到新Master节点**后,该节点会返回**MOVED**,此时客户端才会更新对应的节点信息,以后再访问该key时就会访问新的节点。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值