跳到主要内容

Redis 集群整体架构

我来为你详细整理 Redis 集群架构的完整笔记,通过图表和场景化例子来说明各种部署模式和核心机制。

Redis 集群部署模式对比

三种模式核心原理详解

1. 主从复制原理

主从复制是Redis最基础的高可用方案,通过数据冗余来提升读取性能和数据安全性。

主从复制核心机制

  1. 复制ID和偏移量:每个Redis实例都有一个复制ID,主从之间通过偏移量来确定数据同步位置
  2. 复制缓冲区:主节点维护一个固定大小的缓冲区,记录最近的写命令,用于增量复制
  3. 心跳检测:从节点每秒向主节点发送REPLCONF ACK <offset>命令报告复制进度
  4. 异步复制:主节点执行写命令后立即返回给客户端,然后异步将命令发送给从节点

2. 哨兵模式原理

哨兵模式在主从复制基础上增加了自动故障发现和故障转移能力,解决了主节点单点故障问题。

哨兵模式核心机制

  1. 三种定时任务

    • 每1秒向所有实例发送PING命令检查可达性
    • 每2秒通过发布订阅检查哨兵集群状态
    • 每10秒向主从节点发送INFO命令获取拓扑信息
  2. 故障判断流程

    • 主观下线(SDOWN):单个哨兵判断节点不可达
    • 客观下线(ODOWN):多个哨兵确认节点不可达
    • Quorum机制:需要达到配置的quorum数量才触发故障转移
  3. Leader选举:使用Raft算法在哨兵集群中选出leader执行故障转移

  4. 从节点选择策略

    • 过滤不健康的从节点
    • 选择复制偏移量最大的从节点(数据最完整)
    • 选择runid最小的从节点(启动最早)

3. 集群模式原理

Redis Cluster通过分片技术实现数据的水平扩展,每个节点只存储部分数据,多个节点组成一个完整的集群。

集群模式核心机制

  1. 哈希槽分片

    • 整个数据库被分为16384个哈希槽
    • 每个key通过CRC16算法计算后对16384取模确定槽位
    • 每个节点负责一定范围的槽位
  2. 集群通信协议

    • Cluster Bus:节点间通过专用端口(默认+10000)进行通信
    • Gossip协议:节点定期交换集群状态信息
    • 故障检测:通过PING/PONG消息检测节点状态
  3. 客户端路由

    • MOVED重定向:槽位已确定分配给其他节点
    • ASK重定向:槽位正在迁移过程中
    • 智能客户端:缓存槽位表,直接访问正确节点
  4. 槽位迁移

    • 原子迁移:每次迁移一个key,保证数据一致性
    • 状态标记:MIGRATING和IMPORTING状态确保迁移过程可控
    • 渐进式rehash:避免一次性迁移造成阻塞

三种模式对比总结

特性主从复制哨兵模式集群模式
数据分布全量复制到每个节点全量复制到每个节点分片存储到不同节点
扩展性只能垂直扩展只能垂直扩展可水平扩展
故障转移手动自动自动
一致性最终一致性最终一致性最终一致性
运维复杂度简单中等复杂
适用场景读多写少高可用要求大数据量场景

场景化选择

1. 主从复制 - 适合读多写少场景

# 场景:新闻网站,大量用户读取文章,少量编辑发布
# 配置示例
# 主节点配置
redis-server --port 6379 --bind 0.0.0.0

# 从节点配置
redis-server --port 6380 --replicaof 192.168.1.100 6379 --replica-read-only yes

# 应用层读写分离
class NewsService {
private RedisTemplate masterRedis; // 写操作
private RedisTemplate slaveRedis; // 读操作

public void publishArticle(Article article) {
masterRedis.set("article:" + article.getId(), article);
}

public Article getArticle(String id) {
return slaveRedis.get("article:" + id); // 从节点读取
}
}

2. 哨兵模式 - 适合高可用要求

# 场景:电商购物车,不能因主节点故障影响用户体验
# 哨兵配置
sentinel monitor mymaster 192.168.1.100 6379 2 # 2个哨兵同意才故障转移
sentinel down-after-milliseconds mymaster 5000 # 5秒无响应认为下线
sentinel failover-timeout mymaster 10000 # 故障转移超时时间

3. 集群模式 - 适合海量数据场景

# 场景:社交平台用户数据,需要水平扩展
# 优势:支持PB级数据存储
# 劣势:不支持跨节点事务

2. 主从复制原理详解

实际场景演示

# 场景:电商系统商品缓存同步
# 主节点操作
127.0.0.1:6379> SET product:1001 '{"name":"iPhone15","price":5999}'
OK

# 从节点自动同步(异步)
127.0.0.1:6380> GET product:1001
'{"name":"iPhone15","price":5999}'

# 网络断开重连后的增量复制
# 主节点继续写入
127.0.0.1:6379> SET product:1002 '{"name":"iPad","price":3999}'
127.0.0.1:6379> SET product:1003 '{"name":"MacBook","price":12999}'

# 从节点重连时,只需同步新增的两条命令,而不是全量RDB

3. Redis Cluster 分片原理

实际操作示例

# 场景:用户会话数据分片存储
# 用户user:12345的数据存储位置计算
key = "user:12345"
hash = CRC16("user:12345") = 31665
slot = 31665 % 16384 = 15281
# slot 15281 属于节点3,所以数据存储在节点3

# 集群扩容演示
# 1. 添加新节点
redis-cli --cluster add-node 192.168.1.104:6379 192.168.1.101:6379

# 2. 重新分片,每个老节点贡献部分槽位给新节点
redis-cli --cluster reshard 192.168.1.101:6379
# 输入:4096 (新节点分配4096个槽位)
# 输入:新节点ID
# 输入:all (从所有节点均匀分配)

# 3. 槽位分配变化
# 节点1: 0-4095 (原来0-5460,减少1365个槽)
# 节点2: 4096-8191 (原来5461-10922,减少1365个槽)
# 节点3: 8192-12287 (原来10923-16383,减少1364个槽)
# 节点4: 12288-16383 (新节点,获得4096个槽)

4. 哨兵模式故障转移

配置示例

# sentinel.conf 配置
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
sentinel parallel-syncs mymaster 1

# 应用程序连接哨兵
@Configuration
public class RedisConfig {
@Bean
public JedisConnectionFactory connectionFactory() {
RedisSentinelConfiguration config = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("192.168.1.101", 26379)
.sentinel("192.168.1.102", 26379)
.sentinel("192.168.1.103", 26379);
return new JedisConnectionFactory(config);
}
}

5. 数据一致性保证机制

实际应用场景

# 场景1:普通缓存场景,允许短暂不一致
SET session:user123 "login_data"
# 主节点立即返回,从节点异步同步
# 可能损失:主节点宕机时丢失最近几秒的数据

# 场景2:重要业务数据,需要强一致性
SET account:user123:balance 1000
WAIT 2 1000 # 等待至少2个从节点确认,超时1秒
# 确保数据已同步到多个节点才返回成功

# 场景3:集群模式下的分布式锁
SET lock:order:123 "locked" EX 30 NX
# 在集群中,该锁只存在于特定节点,其他节点访问会重定向

6. 集群扩缩容详细流程

实际扩容操作

# 场景:双11前夕,预估流量增长10倍,需要扩容
# 当前:3主3从,每个主节点约5461个槽位
# 目标:6主6从,每个主节点约2731个槽位

# 1. 启动新的Redis实例
redis-server --port 7001 --cluster-enabled yes --cluster-node-timeout 5000
redis-server --port 7002 --cluster-enabled yes --cluster-node-timeout 5000
redis-server --port 7003 --cluster-enabled yes --cluster-node-timeout 5000

# 2. 添加新主节点到集群
redis-cli --cluster add-node 192.168.1.104:7001 192.168.1.101:6379
redis-cli --cluster add-node 192.168.1.105:7002 192.168.1.101:6379
redis-cli --cluster add-node 192.168.1.106:7003 192.168.1.101:6379

# 3. 重新分配槽位
redis-cli --cluster reshard 192.168.1.101:6379 --cluster-slots 2730 --cluster-to <新节点ID> --cluster-from all

# 4. 添加从节点
redis-cli --cluster add-node 192.168.1.104:7004 192.168.1.104:7001 --cluster-slave

# 5. 验证集群状态
redis-cli --cluster info 192.168.1.101:6379
# 输出显示:6个主节点,每个约2731个槽位,数据均匀分布

7. 脑裂问题解决方案

脑裂预防配置

# Redis主节点配置防止脑裂
min-slaves-to-write 1 # 至少1个从节点在线才能写入
min-slaves-max-lag 10 # 从节点延迟不超过10秒
min-slaves-max-lag 3 # 或者配置更严格的3秒

# 哨兵配置
sentinel monitor mymaster 192.168.1.100 6379 2 # 需要2个哨兵同意
# 确保哨兵数量为奇数,如3个或5个

# 场景模拟:网络分区发生
# 分区A:有2个哨兵,但原主节点因为没有从节点连接,拒绝写入
# 分区B:只有1个哨兵,无法达到quorum,不会选举新主节点
# 结果:避免了双主情况,保证数据一致性

8. 不同场景下的架构选择

具体选择指南

小型应用 (< 10万用户)

# 推荐:主从复制
# 场景:企业官网、小型电商
# 配置:1主2从
redis-server --port 6379 # 主节点
redis-server --port 6380 --replicaof 127.0.0.1 6379 # 从节点1
redis-server --port 6381 --replicaof 127.0.0.1 6379 # 从节点2

中型应用 (10万-100万用户)

# 推荐:哨兵模式
# 场景:在线教育、中型电商
# 配置:3哨兵 + 1主2从
# 优势:自动故障转移,运维简单

大型应用 (> 100万用户)

# 推荐:Redis Cluster
# 场景:大型社交平台、电商平台
# 配置:6主6从起步,可扩展到数百节点
# 优势:水平扩展,支持PB级数据

特殊场景优化

# 金融系统:强一致性要求
# 使用WAIT命令 + 哨兵模式
SET balance:account123 10000
WAIT 2 1000 # 确保写入2个从节点

# 游戏系统:低延迟要求
# 使用本地缓存 + Redis集群
# 热点数据缓存在应用本地,Redis作为二级缓存

# 大数据分析:批量写入场景
# 调整持久化策略,关闭AOF,使用RDB快照
save 900 1 # 15分钟内至少1次修改才保存
save 300 10 # 5分钟内至少10次修改才保存
save 60 10000 # 1分钟内至少10000次修改才保存

总结

Redis集群架构选择的核心考虑因素:

  1. 数据量:< 100GB用主从,> 100GB用集群
  2. 可用性:需要自动故障转移用哨兵或集群
  3. 扩展性:需要水平扩展用集群模式
  4. 一致性:强一致性用WAIT命令,最终一致性用异步复制
  5. 运维能力:简单运维用哨兵,复杂运维可选集群

记住:架构选择要基于实际业务需求,不要过度设计!