Redis集群

作者: 我可能是个假开发 | 来源:发表于2024-01-09 10:12 被阅读0次

一、主从同步

单节点的Redis并发能力有上限,要进一步提升Redis的并发能力,就需要搭建主从集群,实现读写分离。


image.png

1.全量同步

主从第一次同步是全量同步:


image.png
  • Replication id:简称replid,是数据集的标记,id一致说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave的数据落后于master,需要更新。

因此,slave做数据同步时,必须向master声明自己的Replication id和offset,master才可以判断到底需要同步哪些数据。


image.png

2.全量同步流程

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命
    令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

3.增量同步

slave重启后同步,执行增量同步。


image.png

repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步。

4.同步优化

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO。
  • 适当提高repl baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力
image.png

5.总结

全量同步和增量同步区别:

  • 全量同步: master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl baklog,逐个发送给slave
  • 增量同步: slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave

执行全量同步时机:

  • slave节点第一次连接master节点时
  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

执行增量同步时机:
slave节点断开又恢复,并且在repl_baklog中能找到offset时

二、Redis哨兵💂

1.哨兵的作用和原理

Redis提供了哨兵机制来实现主从集群的自动故障恢复。

image.png

作用:

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

2.服务状态监控

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

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

3.选举master

一旦发现master故障,sentinal需要在slave中选择一个作为新的master,依据:

  • 判断slave节点与master节点断开时间长短,如果超过指定值 (down-after-milliseconds* 10)则会排除该slave节点
  • 判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  • 判断slave节点的运行id大小,越小优先级越高.

4.故障转移

image.png

当选择了其中一个slave为新的master后,故障转移步骤:

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002命令,让这些slave成为新master的从节点,开始从新的master上同步数据
  • sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

5.RedisTemplate的哨兵模式

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故转移而发生变化,Redis的客户端必须感知这种变化及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

1.在pom文件中引入redis的starter依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.在配置文件application.yml中指定sentinel相关信息:

spring:
  redis:
    sentinel:
    master: mymaster # 指定master名称
    nodes: # 指定redis-sentinel集群信意
      - 192.168.150.101:27001
      - 192.168.150.101:27002
      - 192.168.150.101:27003

3.配置主从读写分离

@Bean
public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
  return configBuilder -> configBuilder.readFrom(ReadFrom.REPLICA PREFERRED);
}

ReadFrom配置redis的读取策略:

  • MASTER:从主节点读
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave节点读取
  • REPLICA_PREFERRED:优先从slave节点读取,所有slave节点不可用才读取master

三、Redis分片集群

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题
  • 高并发写的问题

使用分片集群可以解决上述问题,分片集群特征:

  • 集群中有多个master,每个master保存不同数据
  • 每个master都可以有多个slave节点
  • master之间通过ping监测彼此健康状态
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点
image.png

1.散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上


image.png

数据kev不是与节点绑定,而是与插槽绑定。
redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  • key中不包含“{}”,整个key都是有效部分

例如: key是num,那么就根据num计算,如果是{hcx}num,则根据hcx计算。计算方式是利用CRC16算法得到个hash值,然后对16384取余,得到的结果就是slot值。

2.集群伸缩

添加节点:redis -cli --cluster add-node ip:port ip:port
分配插槽:redis -cli --cluster reshard ip:port

3.故障转移

自动故障转移

  • 实例与其他实例失去连接
  • 疑似宕机
  • 确定下线,自动升一个slave为master

手动故障转移
利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:

image.png

手动的Failover支持三种不同模式

  • 缺省: 默认的流程,如图1~6步
  • force: 省略了对offset的一致性校验
  • takeover: 直接执行第5步,忽略数据一致性、忽略master状态和其它master的意见

4.RedisTemplate访问分片集群

RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致
1.引入redis的starter依赖

  1. 配置分片集群地址
    3.配置读写分离

与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下:

spring:
  redis:
    cluster:
      nodes: # 指定分片集群的每一个节点信息
        - 192.168.150.101:7001192.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集群

    本文链接:https://www.haomeiwen.com/subject/ouxondtx.html