Redis 之 【高可用架构】(从主从复制、哨兵到集群)

目录

1.主从复制(Replication):高可用的基石

[1.1 配置](#1.1 配置)

建立复制

[info replication](#info replication)

断开复制

切主操作

安全性

只读

传输延迟

[1.2 拓扑](#1.2 拓扑)

[1.3 PSYNC 机制与数据同步](#1.3 PSYNC 机制与数据同步)

复制过程分为三个阶段:

全量复制

部分复制

复制积压缓冲区

实时复制与心跳

[1.4 解决的问题与缺点](#1.4 解决的问题与缺点)

[1.5 Q&A](#1.5 Q&A)

[2. 哨兵机制(Sentinel):自动化的故障转移](#2. 哨兵机制(Sentinel):自动化的故障转移)

[2.1 监控与下线判定 (SDOWN vs ODOWN)](#2.1 监控与下线判定 (SDOWN vs ODOWN))

什么是脑裂?怎么解决?

[2.2 故障转移与选举原理](#2.2 故障转移与选举原理)

[2.3 注意事项](#2.3 注意事项)

[2.4 Q&A](#2.4 Q&A)

[3. Redis Cluster 集群:海量数据的终极解法](#3. Redis Cluster 集群:海量数据的终极解法)

[3.1 数据分片算法:哈希槽](#3.1 数据分片算法:哈希槽)

[3.2 集群故障判定与迁移](#3.2 集群故障判定与迁移)

[3.3 集群扩容](#3.3 集群扩容)

[3.4 Q&A](#3.4 Q&A)

[4. 选型对比](#4. 选型对比)


**1.**主从复制(Replication):高可用的基石

主从复制解决了单节点可用性低和性能有限的问题,通过主写从读、多副本和多种拓扑提升读性能与数据可靠性;但它不能自动故障转移,主节点宕机后仍需人工或额外组件介入

1.1 配置

建立复制

参与复制的 Redis 实例划分为主节点(master)和从节点(slave)。每个从结点只能有⼀个主节点,而⼀个主节点可以同时具有多个从结点。复制的数据流是单向的,只能由主节点到从节点。配置复制的方式有以下三种:

  1. 在配置文件中加入 slaveof {masterHost} {masterPort},随 Redis 启动生效
  2. 在 redis-server 启动命令时加入 --slaveof {masterHost} {masterPort} 生效
  3. 直接使用 Redis 命令:slaveof {masterHost} {masterPort} 生效

注意:修改配置主要是修改从机的配置,主机配置不变

info replication

info replication 是 Redis 中用来查看主从复制(复制/Replica)状态信息的命令

复制代码
它不是独立命令,而是 INFO 命令的一个 section:

redis-cli info replication

进入 redis-cli 后也可以直接:

info replication
  • 在主机上执行

    127.0.0.1:6379> info replication

    Replication

    role:master
    connected_slaves:1
    slave0:ip=127.0.0.1,port=6380,state=online,offset=100,lag=0
    master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:100
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:100

字段 含义
role 当前节点角色为主节点
connected_slaves 当前主节点已连接的从节点数量为 1 个
slave0 第 1 个从节点信息:IP 为 127.0.0.1,端口 6380,状态在线,复制偏移量 100,延迟 0 秒
master_replid 主节点当前复制 ID,用于标识当前复制流
master_replid2 第二个复制 ID,用于故障转移后保留旧主节点的复制历史,以支持部分同步;全 0 表示当前没有
master_repl_offset 主节点当前复制偏移量
second_repl_offset 第二个复制 ID 对应的偏移量;-1 表示未使用
repl_backlog_active 复制积压缓冲区是否启用,1 表示启用
repl_backlog_size 复制积压缓冲区大小,单位字节,即 1MB
repl_backlog_first_byte_offset 复制积压缓冲区中第一个字节的偏移量
repl_backlog_histlen 复制积压缓冲区中有效历史数据长度
  • 从机上执行

    127.0.0.1:6380> info replication

    Replication

    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:1
    master_sync_in_progress:0
    slave_repl_offset:170
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:2fbd35a8b8401b22eb92ff49ad5e42250b3e7a06
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:170
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:170

字段 含义
role 当前节点角色为从节点。Redis 5.0 后也常用 replica 表示
master_host 主节点 IP 地址
master_port 主节点端口
master_link_status 与主节点连接状态正常;down 表示断开
master_last_io_seconds_ago 最近一次与主节点通信距今 1 秒
master_sync_in_progress 是否正在进行全量同步,0 表示没有
slave_repl_offset 从节点当前的复制偏移量
slave_priority 从节点优先级,供 Sentinel 选主使用;数值越小优先级越高,0 表示不会被提升为主节点
slave_read_only 从节点是否只读,1 表示只读
connected_slaves 当前节点作为主节点时连接的从节点数量;这里从节点下面没有从节点,所以为 0
master_replid 从节点记录的主节点复制 ID
master_replid2 第二个复制 ID,全 0 表示没有
master_repl_offset 从节点记录的主节点复制偏移量,表示已处理到的位置
second_repl_offset 第二个复制 ID 对应偏移量;-1 表示未使用
repl_backlog_active 复制积压缓冲区是否启用,1 表示启用
repl_backlog_size 复制积压缓冲区大小,单位字节,即 1MB
repl_backlog_first_byte_offset 复制积压缓冲区中第一个字节的偏移量
repl_backlog_histlen 复制积压缓冲区中有效历史数据长度

断开复制

在从节点执行:

复制代码
slaveof no one

可断开与主节点的复制关系。断开复制流程:

  1. 断开与主节点的复制关系
  2. 从节点晋升为主节点

特点:

  • 从节点断开复制后,不会抛弃原有数据
  • 只是无法再获取主节点上的后续数据变化

切主操作

在从节点执行:

复制代码
slaveof {newMasterIp} {newMasterPort}

可将当前从节点的数据源切换到另一个主节点。切主操作流程:

  1. 断开与旧主节点的复制关系
  2. 与新主节点建立复制关系
  3. 删除从节点当前所有数据
  4. 从新主节点进行复制操作

安全性

  1. 对数据比较重要的节点,主节点可通过 requirepass 设置密码验证
  2. 设置后,所有客户端访问都必须使用 AUTH 命令进行校验
  3. 从节点与主节点之间的复制连接,是通过一个特殊标识的客户端完成的
  4. 因此,从节点需要配置 masterauth,并与主节点密码保持一致
  5. 只有这样,从节点才能正确连接主节点并发起复制流程

只读

  1. 默认情况下,从节点使用 slave-read-only=yes,即只读模式
  2. 复制方向只能从主节点到从节点
  3. 对从节点的任何修改,主节点都无法感知
  4. 修改从节点会造成主从数据不一致
  5. 所以线上环境不建议修改从节点的只读模式

传输延迟

  1. 主从节点一般部署在不同机器上,网络延迟需要重点考虑
  2. Redis 提供 repl-disable-tcp-nodelay 参数,用于控制是否禁用 TCP_NODELAY
  3. 默认值为 no,即不禁用,也就是开启 TCP_NODELAY 功能
  4. repl-disable-tcp-nodelay=no 时:
    1. 主节点产生的命令数据无论大小都会及时发送给从节点
    2. 主从延迟变小
    3. 但会增加网络带宽消耗
    4. 适用于网络环境良好的场景,如同机房部署
  5. repl-disable-tcp-nodelay=yes 时:
    1. 主节点会合并较小的 TCP 数据包,从而节省带宽
    2. 默认发送时间间隔取决于 Linux 内核,一般约为 40 毫秒
    3. 节省了带宽,但会增大主从之间的延迟
    4. 适用于网络环境复杂的场景,如跨机房部署

1.2 拓扑

拓扑结构 特点 优点 注意/缺点 适用场景
一主一从 一个主节点 + 一个从节点 简单,支持故障转移 主节点关闭持久化时需避免宕机后自动重启 简单复制、故障转移
一主多从 一个主节点 + 多个从节点,星形 读写分离,读命令可负载均衡 写并发高时,主节点需多次发送写命令,负载加重 读多写少
树形主从 从节点可继续作为下层的主节点 降低主节点负载,减少数据传输量 结构更复杂,管理成本更高 从节点较多、需要分层减压

1.3 PSYNC 机制与数据同步

Redis 使用 PSYNC 命令完成主从数据同步,PSYNC 的语法格式:

复制代码
PSYNC replicationid offset
  • 如果 replicationid 设为 ? 并且 offset 设为 -1 此时就是在尝试进行全量复制.
  • 如果 replicationid offset 设为了具体的数值, 则是尝试进行部分复制.

PSYNC 运行流程

  1. 从节点向主节点发送:PSYNC replid offset;第一次复制时,从节点没有主节点复制 ID 和复制偏移量,所以发送:PSYNC ? -1
  2. 主节点根据 PSYNC 参数和自身数据情况决定响应结果:
    1. +FULLRESYNC replid offset:需要进行全量复制
    2. +CONTINUE:可以进行部分复制
    3. -ERR:主节点版本过低,不支持 PSYNC;从节点改用 SYNC 进行全量复制
  3. 使用特点:
    1. PSYNC 一般不需要手动执行,Redis 在主从复制模式下会自动调用
    2. SYNC 会阻塞 Redis Server 处理其他请求
    3. PSYNC 不会阻塞

复制过程分为三个阶段:

  1. **建立连接:**从节点保存主节点信息 -> 建立 TCP 连接 -> 发送 PING -> 权限验证
  2. **数据同步:**首次连接触发全量复制;网络闪断后触发部分复制
  3. **命令传播:**后续主节点的写命令持续同步给从节点

首次先全量复制,再实时复制;断线后先尝试部分复制,再实时复制;部分复制不行就退回全量复制,然后继续实时复制。它们共同组成完整的主从复制流程

核心概念

  • Replid(复制ID):标识一个数据集。每个主节点重启或从节点晋升都会生成新的 replid。从节点会记录主节点的 master_replid 和 master_replid2(用于网络分区后的数据找回)
  • Offset(偏移量):主从节点分别维护。主节点每执行一条写命令,offset 累加;从节点每秒上报自身 offset。replid + offset 共同标识了唯一的数据集

全量复制

  1. 全量复制是 Redis 最早支持的复制方式,也是主从第一次建立复制时必须经历的阶段
  2. 全量复制流程:
    1. 从节点发送 PSYNC ? -1 给主节点
    2. 主节点解析后判断需要全量复制,回复 +FULLRESYNC
    3. 从节点接收并保存主节点的运行信息
    4. 主节点执行 BGSAVE,生成 RDB 文件
    5. 主节点将 RDB 文件发送给从节点,从节点保存 RDB 数据到本地硬盘
    6. 主节点将"生成 RDB 到从节点接收完成"期间执行的写命令,暂存到主节点上为该从节点维护的输出缓冲区中。等从节点保存并加载完 RDB 后,主节点再把这些写命令发送给从节点,从节点按顺序执行,从而与主节点保持一致
    7. 从节点清空自身原有旧数据
    8. 从节点加载 RDB 文件,得到与主节点一致的数据
    9. 如果从节点开启了 AOF 持久化,加载 RDB 完成后会执行 BGREWRITEAOF,得到最新的 AOF 文件
  3. 全量复制成本很高:
    1. 主节点 BGSAVE 时间
    2. RDB 网络传输时间
    3. 从节点清空旧数据时间
    4. 从节点加载 RDB 时间
  4. 结论:
    1. 应尽量避免对已有大量数据集的 Redis 进行全量复制

无磁盘复制 :主节点 bgsave 时不落盘,直接通过网络发送 RDB,节省磁盘 IO

大内存场景慎用,可能撑爆网卡

部分复制

部分复制是 Redis 针对全量复制过高开销做出的优化措施,使用命令:

复制代码
PSYNC replicationId offset

适用场景:从节点正在复制主节点时出现网络闪断或命令丢失等异常情况,从节点向主节点要求补发丢失的命令数据

部分复制流程:

  1. 主从节点之间网络中断,超过 repl-timeout 时间后,主节点认为从节点故障并中断复制连接
  2. 主从连接中断期间,主节点依然响应命令,但这些复制命令无法及时发送给从节点,于是暂时滞留在复制积压缓冲区中
  3. 网络恢复后,从节点再次连上主节点
  4. 从节点将之前保存的 replicationId 和复制偏移量作为 PSYNC 参数发送给主节点,请求部分复制
  5. 主节点接到 PSYNC 请求后进行必要验证,根据 offset 去复制积压缓冲区查找合适数据,并回复 +CONTINUE
  6. 主节点将需要从节点同步的数据发送给从节点,最终完成一致性

复制积压缓冲区

  1. 定义:保存在主节点上的一个固定长度的队列,默认大小为 1MB,当主节点有连接的从节点时被创建

  2. 写入机制:主节点响应写命令时,不但会把命令发送给从节点;还会写入复制积压缓冲区

  3. 作用:保存最近已复制的数据;用于部分复制和复制命令丢失的数据补救

  4. 相关统计信息可通过主节点 INFO replication 查看:

    复制代码
    repl_backlog_active:1          // 开启复制缓冲区
    repl_backlog_size:1048576      // 缓冲区最大长度
    repl_backlog_first_byte_offset:7479  // 起始偏移量
    repl_backlog_histlen:1048576   // 已保存数据的有效长度
  5. 可用偏移量范围:

    复制代码
    [repl_backlog_first_byte_offset,
     repl_backlog_first_byte_offset + repl_backlog_histlen]
  6. 本质:相当于一个基于数组实现的环形队列,上述区间中的值就是"数组下标"

  7. 重要限制:如果当前从节点需要的数据已经超出主节点积压缓冲区的范围,则无法进行部分复制,只能全量复制

实时复制与心跳

  1. **实时复制:**主从节点建立复制连接后;主节点会把自己收到的修改操作,通过 TCP 长连接源源不断传输给从节点;从节点根据这些请求同步修改自身数据,从而保持与主节点数据一致
  2. **心跳机制:**这种长连接需要通过心跳包维护连接状态;这里的心跳是应用层自己实现的心跳。主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信
  3. 主节点心跳:主节点默认每隔 10 秒对从节点发送 PING 命令;用于判断从节点的存活性和连接状态
  4. 从节点心跳:从节点默认每隔 1 秒向主节点发送:REPLCONF ACK {offset} 给主节点上报自身当前的复制偏移量
  5. 超时判定:如果主节点发现从节点通信延迟超过 repl-timeout 配置的值;默认 repl-timeout 为 60 秒;则判定从节点下线,断开复制客户端连接;从节点恢复连接后,心跳机制继续

1.4 解决的问题与缺点

问题:

  1. **单点可用性问题:**单个 Redis 节点可用性不高,故障后服务容易中断
  2. **单点性能问题:**单个 Redis 节点性能有限,读请求压力大时容易成为瓶颈
  3. 通过主从复制,可以为数据提供多个副本,提升可用性和读性能

缺点:

  1. 从节点过多时,复制数据延迟会非常明显
  2. 主节点挂掉后,从节点不会自动升级为主节点
  3. 只能通过人工干预恢复,或额外引入 Sentinel、Redis Cluster 等机制实现自动故障转移

1.5 Q&A

Q:主从复制是怎么实现的?

  • Redis 主从复制基于 PSYNC 命令实现,从节点发送 PSYNC replid offset,主节点根据复制 ID 是否一致、偏移量是否还在复制积压缓冲区内,决定走全量复制还是部分复制;同步完成后进入命令传播阶段,主节点通过 TCP 长连接持续把写命令发给从节点,从节点执行并累加自身偏移量,同时主节点默认每 10 秒发 PING、从节点每秒回 REPLCONF ACK {offset},通过心跳维护连接和检测数据丢失

Q:全量复制和部分复制怎么选?

  • 首次连接、复制 ID 不一致,或者从节点要的 offset 已经不在主节点复制积压缓冲区内时,只能走全量复制,主节点 BGSAVE 生成 RDB 发给从节点,期间写命令暂存到该从节点对应的输出缓冲区,等从节点加载完 RDB 再补发;如果复制 ID 一致且 offset 仍在复制积压缓冲区内,就走部分复制,只补发缺失的命令,开销远小于全量复制

Q:频繁全量复制怎么办?

  • 核心是调大复制积压缓冲区 repl-backlog-size,它默认是 1MB 的环形队列,网络抖动断连后,如果从节点 offset 仍落在缓冲区内,就能触发部分复制而不是全量复制;可按"峰值写入速率 × 最大重连时间 × 2"估算,生产环境常设为 64MB~256MB,高写入场景可更大,同时可开无磁盘复制加快全量复制速度

Q:主从延迟怎么解决?

  • Redis 默认 repl-disable-tcp-nodelay no,即开启 TCP_NODELAY,主节点产生命令会立即发送给从节点,减小延迟;但跨机房部署时建议改为 yes 以节省带宽,代价是内核合并小包,默认约 40ms 延迟。此外还可优化网络、控制写入峰值、提升从节点性能、调大 repl-backlog-size,并用 min-slaves-max-lag 等参数在延迟过大时拒绝写入,避免主从差距继续扩大

2. 哨兵机制(Sentinel):自动化的故障转移

2.1 监控与下线判定 (SDOWN vs ODOWN)

哨兵节点(独立进程 redis-sentinel)定期监控所有 Redis 数据节点,其余哨兵节点是否可达

  • 主观下线 (SDOWN):单个哨兵发现主节点超过 down-after-milliseconds(默认30秒)没响应。此时可能仅仅是该哨兵网络不通
  • 客观下线 (ODOWN):该哨兵向其他哨兵发起投票(sentinel monitor <quorum> 法定票数)。票数 >= quorum 才能判定主节点真的挂了
  • 建议哨兵节点为奇数个(至少3个),因为 Raft 选举需要半数以上同意,奇数可以避免平票,提高选举效率,防止脑裂

什么是脑裂?怎么解决?

  • 脑裂是指网络分区后,原 Master 与哨兵失联,但客户端仍能连上原 Master 写入;哨兵选出新 Master,导致集群出现两个 Master 同时写。网络恢复后原 Master 降为 Slave,期间写入的数据可能丢失
  • 缓解方案是在主节点配置 min-replicas-to-write 1 和 min-replicas-max-lag 10,表示如果健康从节点少于 1 个,或从节点同步延迟超过 10 秒,主节点就拒绝写命令。这能降低旧主在分区期间继续写入的概率,但不能完全杜绝脑裂,也不能保证数据绝对安全。还需要配合哨兵奇数部署、合理 quorum、客户端正确连接等措施

2.2 故障转移与选举原理

当主节点被判定为 ODOWN 后,触发故障转移:

  1. **选举 Leader 哨兵:**哨兵之间选出 Leader。可以简单的认为谁先发起拉票(网络延迟最小),谁就大概率当选
  2. Leader 挑选新主节点: 从所有从节点中筛选,规则依次为:
    1. 过滤掉长时间未通信的节点(保证数据相对完整)
    2. slave-priority 最高(数值最小)
    3. 复制偏移量 offset 最大(数据最新)
    4. run id 最小(字典序,避免平票)
  3. **执行转移:**向新主发送 slaveof no one,向其他从发送 slaveof <newMaster>,并通知客户端
  4. **旧主恢复:**旧主重启后,会被哨兵作为从节点加入集群

2.3 注意事项

  1. 哨兵节点不能只有一个,否则哨兵节点挂了也会影响系统可用性
  2. 哨兵节点最好是奇数个,方便选举 Leader,得票更容易超过半数
  3. 哨兵节点不负责存储数据,仍然由 Redis 主从节点负责存储
  4. 哨兵 + 主从复制解决的问题是"提高可用性",不能解决"数据极端情况下写丢失"的问题
  5. 哨兵 + 主从复制不能提高数据的存储容量,当需要存储的数据接近或超过机器的物理内存时,这种结构就难以胜任。为了能存储更多数据,就引入了集群

2.4 Q&A

Q:哨兵是怎么判定主节点下线的?

  • Sentinel 会定期向主节点发送 PING,如果超过 down-after-milliseconds 没收到有效回复,单个 Sentinel 先把主节点标记为主观下线;随后它会向其他 Sentinel 发送 is-master-down-by-addr 询问,当认为主节点下线的 Sentinel 数量达到配置的 quorum 时,就判定为客观下线,进而触发故障转移流程

Q:客观下线后,谁来做故障转移?怎么选主?

  • 客观下线后,Sentinel 集群会先选举出一个 Leader Sentinel 来执行故障转移,选举类似 Raft,需要获得多数票且达到 quorum;然后 Leader 从从节点中挑选新主节点,优先级依次是:slave-priority 最高的、复制偏移量 offset 最大的(数据最新)、runid 最小的;选中后向该从节点发送 SLAVEOF NO ONE 将其提升为主节点,再让其他从节点复制新主节点,并通知客户端更新主节点地址

Q:哨兵集群节点数量为什么建议是奇数?

  • 因为 Sentinel 判定客观下线和选举 Leader 都需要超过半数的同意,奇数个节点更容易达到多数,避免平票,同时在容错能力和成本之间更优;比如 3 个节点允许挂 1 个,4 个节点虽然多了一个但多数仍是 3,挂 2 个就失去多数,所以奇数个更划算

Q:哨兵模式能解决写压力吗?

  • 不能。哨兵 + 主从复制主要解决的是高可用性,即主节点故障时自动切换;写操作仍然只能在主节点执行,从节点默认只读,增加从节点或哨兵并不能分担写压力。要解决写压力,需要引入分片集群,比如 Redis Cluster

3. Redis Cluster 集群:海量数据的终极解法

3.1 数据分片算法:哈希槽

Redis Cluster 引入多组 Master/Slave,每组存一部分数据,实现分布式存储

  • 哈希槽算法:hash_slot = crc16(key) % 16384。将所有数据映射到 16384 个槽位
  • 为什么是 16384?
    • 节点间心跳包需要携带槽位信息(位图)。16384 个槽位使用 16384 / 8 = 2048 字节 (2KB) 的位图即可表示;如果使用 65536,则需要 8KB。频繁的心跳包中,2KB 的开销是可接受的,8KB 则过大
    • Redis 作者建议集群节点不应超过 1000 个,16384 个槽位足够 1000 个节点分配
  • 不用一致性哈希: 一致性哈希容易产生数据倾斜,且扩容时较难均匀分配
  • 不用简单哈希求余:扩容时 N 变化,几乎所有的 Key 都需要重新映射,数据迁移成本极高

3.2 集群故障判定与迁移

  • 故障判定:
    • 节点间周期性 PING/PONG
    • 若 A 连不上 B,A 标记 B 为 PFAIL(主观下线)
    • A 向其他节点八卦,若超过半数主节点认为 B 是 PFAIL,则 B 标记为 FAIL(客观下线)
    • 集群宕机条件:某个分片的主从全挂 / 某分片主挂且无从 / 超过半数的主节点挂掉
  • 故障迁移:
    • 从节点检查自身是否有资格(与主节点断连时间未超阈值)
    • 休眠时间计算:500ms + 0, 500ms 随机时间 + rank * 1000ms(rank 与 offset 相关,offset 越大,rank 越小,休眠越短,越容易先拉票)
    • 先醒来的从节点向所有主节点拉票,获得半数以上投票后,晋升为新 Master,接管原 Master 的槽位

3.3 集群扩容

  • **扩容:**add-node 加入新主节点 -> reshard 重新分配槽位(从旧节点搬运部分槽位给新节点) -> add-node --cluster-slave 为新主添加从节点
  • **重定向机制:**客户端访问 Key 不在当前节点时,会收到 MOVED 重定向。如果正在发生槽位迁移,则可能收到 ASK 重定向(临时重定向,客户端需先发送 ASKING 命令)。客户端必须使用 -c 参数启动
  • **Hash Tag:**如果业务需要多个 Key 原子的操作(如事务、Lua 脚本),必须让这些 Key 落在同一个槽位。可以使用 {user:1000}:name 和 {user:1000}:age,Redis 只计算 {} 内的内容,确保它们落在同一个分片

3.4 Q&A

Q:数据量暴增,单机内存扛不住了,怎么办?

  • 官方方案是 Redis Cluster,它把整个数据集划分为 16384 个哈希槽,每个节点负责一部分槽位,客户端根据 key 计算槽位并路由到对应节点;Redis Cluster 是官方原生支持、去中心化的,能同时解决容量和写压力问题

Q:一致性哈希有什么缺陷?Redis 怎么分片?

  • 一致性哈希虽然能在节点增减时只影响相邻数据,但存在数据倾斜问题,节点少时容易分布不均,需要引入虚拟节点来平衡,而且实现和运维相对复杂;Redis 没有采用一致性哈希,而是用哈希槽分片:对 key 做 CRC16 计算,然后对 16384 取模得到槽位,每个节点负责一部分槽位,槽位可以在节点间迁移,扩容缩容时只需移动部分槽位,客户端通过集群协议获取槽位映射,实现去中心化路由

Q:为什么是 16384 个槽位?

  • 主要权衡了心跳包大小和集群规模:Redis Cluster 节点间通过 Gossip 协议交换信息,心跳包里会携带槽位位图,16384 个槽位用位图表示是 2KB,而 65536 个槽位是 8KB,心跳包太大会浪费带宽;同时集群节点数通常不超过 1000 个,16384 个槽位足够均匀分配,槽位少也便于压缩、传播和迁移,所以 16384 是带宽、规模和效率之间的最佳平衡点

Q:Cluster 集群怎么判定节点故障?怎么扩容?

  • 节点间通过 Gossip 协议定期发送 PING/PONG,如果某节点超过 cluster-node-timeout 未响应,其他节点先标记它为 PFAIL(疑似下线);当多数主节点都认为该节点 PFAIL 时,就升级为 FAIL(客观下线),然后触发故障转移,从节点发起选举,获得多数主节点投票后提升为新主节点。扩容时先用 redis-cli --cluster add-node 把新节点加入集群,再用 reshard 把部分槽位从旧节点迁移到新节点,迁移过程中槽位有 MIGRATING 和 IMPORTING 状态,客户端访问时通过 ASK 重定向保证数据正确

4. 选型对比

架构模式 解决的核心问题 核心优势 致命缺点 / 边界
主从复制 数据热备份、读性能扩展 简单、易配置、读写分离 主节点宕机需人工介入; 写/存储受单机限制
哨兵机制 主从架构的自动化故障转移 高可用(HA),无需人工干预,客户端透明 未解决写压力与存储容量; 配置略复杂
Cluster 集群 海量数据存储、高并发写入 分布式分片,水平扩展(加机器即可);高可用 架构复杂;客户端需支持重定向;跨槽位操作受限
相关推荐
hweiyu004 小时前
Redis命令:HPERSIST
redis·缓存
hweiyu004 小时前
Redis命令:HPEXPIRE
redis·缓存
ShineWinsu8 小时前
对于Redis:string类型的解析
java·c++·redis·分布式·缓存·面试·string
CoLiuRs10 小时前
电商价格是怎样算出来的
数据库·redis·缓存
天衍四九-13 小时前
Docker Compose企业实战系列(四):Redis生产级部署|密码加固、持久化、内存优化完整方案
redis·docker·容器
喜欢的名字被抢了14 小时前
08-Redis 性能优化篇:快在哪、BigKey、HotKey、慢查询与内存
数据库·redis·性能优化
青山木15 小时前
秒杀系统设计(一):需求拆解与流量治理
java·数据库·redis·后端·架构
hweiyu001 天前
Redis命令:HMGET
redis·缓存