首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis集群

Redis集群

原创
作者头像
Eulogy
发布2025-08-07 09:42:13
发布2025-08-07 09:42:13
2010
举报
文章被收录于专栏:笔记本笔记本

Redis集群

不使用redis单节点,而是使用多个redis实例,分为主(master)和从(slave)节点分别做不同的事情,来提高整体业务的性能。就例如将读写进行分离,master节点主要负责写操作(可以读),而从节点只能进行读操作(不可以写)。这样可以提高读请求的响应速度,并且从节点可以设置多个,在高并发的情况下也可以很好地应对。

多个redis节点就会遇到一个问题,就是这些节点之间怎么进行数据同步,保证数据一致性?

数据同步

全量同步: 主从第一次建立连接时或者backlog被覆盖导致offset过旧时会触发全量同步,一共分为三个阶段。

首先,每个 Master 都有一个唯一的复制 ID(replid),Slave 在同步时会记录该 ID 和当前同步偏移量(offset)。

当 Slave 连接 Master 时,会发送 PSYNC 命令。Master 判断能否进行增量同步,如果不能,就开始全量同步( 判断依据是slave保存的replid是否是master的replid ):

  1. Master 会通过 bgsave 生成 RDB 快照文件,并将其发送给 Slave;
  2. Slave 收到 RDB 文件后加载到内存,完成一次性数据初始化;
  3. 同时,Master 在生成 RDB 过程中通过内存中的 replication backlog buffer 缓存所有新写入命令,RDB 发送完后再将这些命令发送给 Slave,确保数据一致。

同步完成后,主从双方会维护相同的 replidoffset,后续就可以进行 增量同步

增量同步: 当主从节点已经完成一次全量同步并持续保持连接状态,或者从节点在短暂断线后重新连接成功时,将进入 增量同步阶段。此阶段不会再传输全量的 RDB 文件,而是通过命令流的形式将主节点新增的数据同步给从节点,性能更高、效率更好。

增量同步依赖两个核心机制:

  • replid:用于标识主节点身份,确保当前连接的是之前同步的 Master;
  • offset:表示从节点已同步到的数据位置,用于计算需要增量同步的数据起点。

当 Slave 断线重连时,会向 Master 发送 PSYNC 命令,并携带上次保存的 replidoffset

  1. Master 校验请求中的 replid 是否和自身当前的一致;
  2. 检查请求中的 offset 是否还落在 Master 的 replication backlog buffer(一个固定大小的内存环形缓冲区)中;
  3. 如果满足以上两个条件,则进行 部分重同步(partial resynchronization)
    • Master 从 backlog 中找出 offset 之后的写命令;
    • 将这些命令发送给 Slave;
  4. Slave 应用这些命令,状态追平 Master;
  5. 主从继续保持实时命令同步。

若条件不满足(如 offset 太旧,尚未备份的数据被覆盖(因为backlog是一个环,进行的是 覆盖写 ,写满后会覆盖之前的数据)或 replid 不一致),则无法进行增量同步,会回退为 全量同步

哨兵

slave节点宕机了可以直接重启然后找master进行数据同步就行,虽然有短暂的数据延迟,但是最终还是会与master数据一致。那么master节点宕机了怎么办呢?那么在master节点重启恢复的过程中,写操作就不会被执行了。

Sentinel作用: Redis就提供了哨兵(sentinel)机制来监测集群的健康状态;如果master故障了,那么sentinel就会选择一个slave提升为master。故障节点恢复后,依旧是以新提升的master作为master节点;并且是sentinel通知客户端哪个节点是master,哪个节点是slave的。

服务状态监控: 那么sentinel如何知道哪个节点还在线,哪个节点下线了呢?通过心跳检测机制。sentinel会每隔1s向集群所有实例发送ping命令,然后等待接收实例返回pong命令,如果超过一定时间没有返回,该sentinel就会认为该实例 主观下线 了。sentinel也有集群,如果超过指定数量(quorum)的sentinel都认为该实例下线了那么就认为该实例 客观下线 了,quorum值最好超过sentinel实例数量的一半。

选举新的master: 首先会根据slave节点和master节点断开的时间长短来排除一些数据过旧的节点,将超过指定值的slave节点排除;然后会判断slave节点的slave-priority值,值越小优先级越高;*接着判断slave节点的 offset值 ,越大说明数据越新,优先级越高;最后判断slave节点的运行id大小,越小优先级越高。

故障转移: 使用slaveof no one命令,让该节点成为master;然后会发送广播告诉其它所有的slave节点,让这些slave节点以新的master节点为master;然后sentinel会把故障的master节点标记为slave,等他重启之后,他就会变成新的master节点的slave节点。

哨兵和读写分离建立好了之后,客户端每次请求都是访问哨兵,哨兵会通知客户端哪个节点是master,哪些节点是slave,然后客户端就可以根据读请求还是写请求去访问对应的redis节点了。并且master宕机后,sentinel也能监测到并且自动地建立新的master并通知客户端。

分片集群

数据量太大的时候,如果都放在一个redis中,高并发写的时候,所有并发请求访问一个master的话,性能依旧会有影响。并且高并发读的时候依旧会有问题。总之,分片集群就是用来解决 海量数据存储 以及 高并发请求 的。

特征: 集群中有多个master,每个master保存不同的数据。master都可以有多个slave节点。所以可以既满足分片集群,也满足主从集群。master和master之间可以通过ping来监测彼此健康状态,就不需要哨兵了,各个master之间可以进行健康检测。

散列插槽: Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,数据key不是与节点绑定,而是与插槽绑定,redis会根据key的有小部分计算插槽值,分为两种情况:

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

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

为什么key和slot绑定?而不是和redis节点绑定? 因为为了实现高效的水平扩展和动态迁移,Redis才引入了”slot“作为中间层,使得key和节点解耦,这样当增加redis节点或者删除redis节点的时候,只需要移动slot,将slot分配到不同的redis节点就可以了。

集群伸缩: 添加一个或者移除一个节点在集群中。 添加一个节点到redis集群中时,需要为这个集群分配插槽。

故障转移: 分片集群中没有哨兵,但是依旧是可以自动做故障转移的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redis集群
    • 数据同步
    • 哨兵
    • 分片集群
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档