redis 集群模式

redis 集群模式

1.1 redis主从复制

image

1.1.1 redis复制原理

redis 的复制分为两部分操作 同步(SYNC)和 命令传播(command propagate)

  • 同步(SYNC)用来将从服务器的状态 更新到 和主服务器 一致。白话文解释就是从服务器主动获取 主服务器的数据。保持数据一致。具体实现是,主服务器收到SYNC命令后,生成RDB快照文件,然后发送给从服务器。
  • 命令传播 (command propagate)用于在主服务器数据被修改后,主从不一致,为了让从服务器保持和主服务器状态一致,而做的命令传播。白话文解释就是主服务器收到客户端修改数据命令后,数据库数据发生变化,同时将命令缓存起来,然后将缓存命令发送到从服务器,从服务器通过载入缓存命令来达到主从数据一致。这就是所谓的命令传播。
  • 为什么需要有同步和命令传播的两种复制操作: 当只有同步操作时候,那么在从服务器向主服务器发送SYNC命令时候,主服务器在生成RDB快照文件时候,仍然会收到客户端的命令修改数据状态,这部分数据如果不能传达给从服务器,那么就会出现主从数据不一致的现象。这时候就出现了命令传播,主服务器收到从服务器的SYNC命令后,生成RDB快照文件同时,将此段时间内收到的命令缓存起来,然后使用命令传播的操作发送从服务器。来达到主从数据一致。

上面介绍了redis复制的两种操作,而redis得主从复制正式基于 同步 和 命令传播 来实现得。下面两张图展示了redis复制的流程:
image

1.1.2 redis主从复制优缺点

优点:

  • 实现读写分离,提高了可用性,解决了单机故障
  • 主从复制期间master和slave都是非阻塞方式,仍然可用。

缺点:

  • master宕机期间,需要手动切换主机,同时会有部分数据不能及时同步从服务器,造成数据不一致(需要人工手动介入)
  • slave宕机后,多个slave恢复后,大量的SYNC同步会造成master IO压力倍增(可以手动规避启动时间)
  • 在线扩容较复杂。
    总结:
    redis主从复制的优点主要是提高了可用性缺点

2.1 Sentinel 哨兵模式

Sentinel 哨兵本质上是一个运行在特殊模式下的Redis实例,只是初始化的过程和工作与普通的Redis不同,本质上也是一个单独的进程。
Sentinel 哨兵 是Redis的高可用解决方案:一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在主服务器下线时可以自动切换从服务器升级为主服务器。

2.1.1 Sentinel系统

下图是一个简单的Sentinel系统架构图,一个Sentinel系统监视一个主从集群,其中server1是Redis主服务器,server2/3/4是Redis 从服务器。主从之间利用上面的主从复制来达到主从一致。而Sentinel系统监视整个主从集群
image

2.1.2 Sentinel故障转移

当Sentinel系统察觉到Server1主服务器下线时,就会终止server2/3/4的复制
image

同时Sentinel将server2升级为主服务器,server3/4从新的主服务器进行复制。同时等待server1的再次上线
image

Sentinel系统也可以主动降级主服务为从服务器,将从服务器升级为主服务器
image

2.1.3 哨兵的工作方式

  • 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
  • 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
  • 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
  • 当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
  • 在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
  • 当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  • 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

2.1.4 哨兵模式的优缺点

优点

  • 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
  • 主从可以自动切换,系统更健壮,可用性更高。

缺点

  • Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂

Codis架构图
image

Twemproxy架构图
image

Tweproxy推出的时间最久,在早期没有好的服务端分片集群方案时,应用范围很广,而且性能也极其稳定。
但它的痛点就是无法在线扩容、缩容,这就导致运维非常不方便,而且也没有友好的运维UI可以使用。Codis就是因为在这种背景下才衍生出来的。

3.1 Redis-Cluster集群

image

redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。

Redis-Cluster采用无中心结构,它的特点如下:

  • 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  • 节点的fail是通过集群中超过半数的节点检测失效时才生效。
  • 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

3.1.1 工作方式

在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了。

3.1.1.1 集群建立,结点间建立集群关系

假设有6个结点。分别为1,2,3,4,5,6
通过发送 cluster meet ip 端口号命令,将指定IP和端口号的结点加入集群。
结点1,依次向2,3,4,5,6发送cluster meet。然后通过cluster nodes查看,就可以发现当前集群已经有6个结点

过程:

  • 结点1向2发送meet命令,保存2的信息;
  • 结点2接收到1的meet命令,保存1的信息,并向1反馈PONG命令;
  • 之后1,2结点通过PING,PONG进行正常的结点通信。
3.1.1.2 分配slot

在未给结点分配slot时,节点不能响应读写操作。
使用cluster addslots为结点分配slot,slot的分配应该均匀。
注意:任意一个slot未分配,集群就不可用。
使用cluster info可以查看slot的分配

3.1.1.3 建立主从关系

Redis Cluster保证高可用,所以需要搭建主从。
在从节点4,5,6上使用cluster replicate nodeId建立主从关系。
这里的nodeId 是主节点以集群模式启动时生成的48位的16进制id,与runId不同,他只会创建一次。

3.1.2 Redis Cluster 数据分片原理

redis 数据分片使用的是hash slot, redis集群有16384个哈希槽,每个Key通过CRC16校验后对16384取模来决定放置哪一个槽。
当存取redis key时候,redis会根据CRC16算法得到一个结果,然后把结果和16384求余,通过这个值去对应得节点获取数据。
这个时候,应用客户端实际上只需要连接其中任意一个节点即可,然后Redis Cluster 中每个节点都保存了其他节点得槽信息。这样当存取key计算完槽之后,通过保存槽信息从配置中获取节点信息,然后再去对应得节点获取数据。

3.1.3 Redis Cluster 复制原理及通信

3.1.3.1 复制原理

redis-cluster集群引入了主从复制模型,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点 ping 一个主节点 A 时,如果半数以上的主节点与 A 通信超时,那么认为主节点 A 宕机了。如果主节点 A 和它的从节点 A1 都宕机了,那么该集群就无法再提供服务了

image

3.1.3.2 通信原理

Redis集群使用P2P形式的Gossip协议进行集群中结点间的数据交换。Gossip协议原理就是结点间不断通过PING,PONG进行通信交换信息,一段时间后,就会得到所有的结点信息

Gossip协议:
Gossip协议的目的就是进行节点间的数据交换。数据交换就是通过发送Gossip消息。
Gossip消息分为:ping , pong , meet, fail四种。

meet

  • 通知其他节点加入集群。

ping

  • 集群中结点交互最频繁的消息,每秒向其他节点发送一个ping命令,以便知道其他节点的存活状态,并进行数据状态信息交互。ping命令包含了发送者自身及其它部分节点的数据状态信息。

pong

  • 作为ping与meet的响应消息,包含响应者自身的信息。

fail

  • 当发现某个结点下线时,会向其他节点广播发送fail信息,其他节点接收后,会将自己记录的对应结点状态更新为下线。

可以看到有3个主节点M,3个从节点S。每个节点都是成功的连接状态
连接任意一个节点端口:
image

设置一个值:
image

前面理论知识我们知道了,分配key的时候,它会使用CRC16(‘my_name’)%16384算法,来计算,将这个key 放到哪个节点,这里分配到了12803slot 就分配到了7002(10923-16383)这个节点上。

redis cluster 采用的方式很直接,它直接跳转到7002 节点了,而不是还在自身的7000节点。

好,现在我们连接7005这个从节点:
image

我们同样是获取my_name的值,它同样也是跳转到了7002上.

3.1.4 redis Cluster 优缺点

优点:

  • 实现了分布式存储,节省了内存

缺点:

4.1 集群伸缩

集群进行伸缩时,进行数据迁移是以slot为单位的。也就是把原先各个节点的slot分配部分给新的结点进行分担。
从这里也可以看出,Redis Cluster的伸缩带来的影响很小。首先只用迁移部分数据,并且当客户端获取某个数据时,是根据数据的key映射到slot,slot再与结点映射。

4.1.1 集群扩容:

假设加入7,8两个结点,在任意一个集群结点上使用meet命令,将7,8加入集群。加入集群后,7,8结点由于没有分配slot,所以暂时无法使用。

对于加入的新的结点,可以作为已有的主节点的从节点进行故障转移,或者是作为主节点分担存储与写的压力。

这里将7作为新的主节点,8作为7的从节点。原来16383个slot由1,2,3三个结点均分为3等分,现在7加入,那么1,2,3分出自己的slot给7,让4个主结点的slot近似相等。分出slot的时候,将slot映射的数据也转移到7.

4.1.2 集群收缩:

下线的如果是主节点,也就是该结点映射的有slot,就把该slot均分给剩余的主节点。当处理完slot或者下线的是从节点,则广播fail消息,让其他结点更新该下线结点的状态。

5.1 故障转移

Redis Cluster自身保证高可用,也就是允许出现部分节点故障。当发生故障时,集群能够发现并转移故障。

上面我们建立来了一个集群。3个主节点[7000-7002]提供数据存粗和读取,3个从节点[7003-7005]则是负责把[7000-7002]的数据同步到自己的节点上来,replicas=1的时候,一个主对应一个从,每个从只同步自己对应的主节点的数据

下面,我们先来模拟其中一台Master主服务器挂掉的情况,那就7000挂掉吧
image
image

好,安装前面的理论,7000主节点挂掉了,那么这个时候,7000的从节点只有7004一个,肯定7004就会被选举称Master节点了

image

数据果真没有丢失,而是从7004上面获取了。

5.1.1 故障发现

这里一个结点的下线也分为主观下线与客观下线 :

主观下线:

  • 当结点A向结点B发送ping命令后,在指定时间内未收到回复,就会将自己维护的状态信息中,把B结点标记为主观下线。

客观下线:

  • 因为Gossip消息传播,结点A标记结点B为主观下线的信息会传播给其他结点。当其他节点发现接收的ping命令时,发现包含把B结点设置为主观下线时,就会判断是否有半数以上的主节点同意B结点下线,当符合时,当前结点就会把结点B标记为客观下线,然后广播发送fail命令,通知其他的结点。

这里之所以进行投票的是主节点,是因为主节点才是维护slot的结点,负责读写与管理slot等关键信息,而从节点只复制主节点的数据与状态信息。

5.1.2 故障恢复

当客观下线的结点是维护slot的主节点,为了保证高可用,要进行故障转移。故障转移工作由该结点的所有从节点负责。

故障转移步骤:

进行资格省察:

  • 从节点看自己最后一次与主节点断开连接的时间是否超过限制,若未超过,则具有晋身为主节点的资格。
    设置选举时间:
  • 从节点根据自己的复制偏移量的大小,设置自己的选举开始时间。偏移量越大代表复制的数据越完整,那么他的选举开始时间越小。可以看出,设置选举时间的作用是为定义一个优先级。
    进行选举:
  • 从节点向集群其它结点发送选举信息,主节点参与投票,当收到主节点个数一半以上的投票时,当前从节点选举为新的主节点。比如有5个主节点,5/2+1=3,也就是说挂掉一个后,需要在剩下4个主节点中获得3票才能选举成功。
    替换下线的主节点:
  • 撤销下线主节点的slot,并交由自己管理,然后广播通知其他节点,自己已经接管了这部分slot

6.1 总结

image

posted @   liwenchao1995  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示