在分布式系统架构中,缓存层的高可用性直接决定了整个系统的稳定性。作为内存数据库的标杆,Redis提供了三种典型的高可用方案:主从复制、哨兵模式和集群模式。我在过去五年的大型电商系统架构实践中,这三种方案都曾根据不同的业务场景被采用过。
主从复制是Redis高可用的基础形态,通过数据冗余实现故障转移;哨兵模式在此基础上增加了自动故障检测和主从切换能力;而集群模式则通过数据分片(Sharding)同时解决了高可用和横向扩展问题。选择哪种方案,需要综合考虑数据一致性要求、故障恢复时间、运维复杂度以及硬件成本等因素。比如在金融交易场景中,我们更关注数据强一致性,而在社交feed流场景中,则更看重系统的横向扩展能力。
Redis主从复制采用异步复制机制,其核心流程可以分为以下几个阶段:
在实际生产环境中,我们遇到过因网络抖动导致复制中断的情况。此时从节点会尝试部分重同步(PSYNC),通过复制偏移量和运行ID来恢复中断的复制流。如果复制积压缓冲区(repl-backlog-buffer)足够大,通常可以避免全量同步的开销。
以下是一组经过生产验证的主从配置参数示例:
bash复制# 主节点配置
repl-backlog-size 512mb # 复制积压缓冲区大小
repl-backlog-ttl 3600 # 断开连接后保留缓冲区的时长
min-replicas-to-write 1 # 至少N个从节点在线才允许写入
# 从节点配置
replica-read-only yes # 从节点默认只读
repl-ping-replica-period 10 # 从节点ping主节点间隔
repl-timeout 60 # 复制超时时间
重要提示:repl-backlog-size需要根据业务写入量合理设置。我们曾遇到因缓冲区过小导致频繁全量同步的情况,最终根据QPS测算调整为当前值。
虽然主从复制实现简单,但在实际运维中我们发现几个典型问题:
在2021年的618大促期间,我们的商品详情页缓存就曾因为主节点宕机导致30分钟的服务降级。这次事故促使我们开始评估更自动化的高可用方案。
哨兵模式通过引入监控节点实现了自动故障转移。我们建议至少部署3个哨兵实例(最好是奇数个),并采用跨机架/可用区的分布策略。以下是典型的哨兵配置:
bash复制sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
这些参数表示:
哨兵系统的工作流程可以分为以下几个阶段:
在实际操作中,我们发现down-after-milliseconds参数对系统敏感性影响很大。设置过短会导致误判,而设置过长又会延长故障恢复时间。经过多次压测,我们最终将电商核心业务设置为5000ms,非核心业务设置为10000ms。
应用程序需要通过哨兵获取当前主节点信息。以下是Java客户端的典型集成方式:
java复制JedisSentinelPool pool = new JedisSentinelPool(
"mymaster",
Set.of("sentinel1:26379", "sentinel2:26379"),
jedisPoolConfig
);
try (Jedis jedis = pool.getResource()) {
// 业务操作
}
我们封装了更健壮的客户端组件,实现了以下特性:
Redis集群采用虚拟槽(slot)分片机制,将16384个槽位分配到各个节点。每个键通过CRC16算法计算后取模确定所属槽位:
code复制slot = CRC16(key) % 16384
我们在数据设计时采用hash tag确保相关数据分布在相同节点。例如:
code复制{user1000}.profile
{user1000}.orders
这样相同用户的数据总是路由到同一节点,避免跨节点事务问题。
生产环境部署建议:
bash复制# 集群节点配置
cluster-enabled yes
cluster-node-timeout 15000
cluster-migration-barrier 1
cluster-require-full-coverage no
我们使用的集群部署拓扑如下:
| 节点角色 | 所在可用区 | 规格配置 |
|---|---|---|
| 主节点1 | AZ-A | 16C32G |
| 从节点1 | AZ-B | 16C32G |
| 主节点2 | AZ-B | 16C32G |
| 从节点2 | AZ-C | 16C32G |
| 主节点3 | AZ-C | 16C32G |
| 从节点3 | AZ-A | 16C32G |
日常运维中最常用的集群命令包括:
bash复制# 查看集群状态
redis-cli --cluster check 127.0.0.1:6379
# 添加新节点
redis-cli --cluster add-node new_node:port existing_node:port
# 重新分片
redis-cli --cluster reshard 127.0.0.1:6379
# 故障转移
redis-cli --cluster failover --force
在去年双11前,我们通过reshard命令将热点商品的slot迁移到专属节点,有效解决了数据倾斜问题。
根据我们在多个项目的实施经验,总结出以下选型指南:
| 评估维度 | 主从复制 | 哨兵模式 | 集群模式 |
|---|---|---|---|
| 数据规模 | <10GB | <50GB | >50GB |
| 写入QPS | <5k | <10k | >10k |
| 可用性要求 | 中等 | 高 | 极高 |
| 扩展性需求 | 无 | 有限 | 强 |
| 运维复杂度 | 低 | 中 | 高 |
| 典型应用场景 | 报表系统 | 订单系统 | 用户画像 |
在具体实施时,我们通常会考虑以下因素:
在网络分区场景下可能出现双主节点的情况。我们通过以下策略降低风险:
去年我们遇到的一个典型案例:两个数据中心之间网络中断,导致出现两个主节点同时接受写入。最终通过以下命令修复:
bash复制redis-cli --cluster fix 127.0.0.1:6379
针对Redis高可用架构的性能优化要点:
我们常用的性能基准测试命令:
bash复制redis-benchmark -h 127.0.0.1 -p 6379 -t set,get -n 100000 -c 100
完善的监控应该包括以下核心指标:
| 指标类别 | 具体指标 | 报警阈值 |
|---|---|---|
| 可用性 | 节点状态 | 任何节点不可用 |
| 性能 | 每秒操作数 | 超过容量80% |
| 容量 | 内存使用率 | >90% |
| 复制 | 主从延迟(秒) | >10 |
| 集群 | 迁移中槽位数量 | >0持续5分钟 |
我们使用Prometheus+Grafana构建的监控看板包含这些关键指标,并设置了分级报警策略。
随着业务规模扩大,我们正在评估以下方向:
在最新的测试中,Redis 7.0的多线程IO表现出色,我们在考虑将其应用于高吞吐场景。同时,客户端缓存(Client-side caching)特性也显著降低了数据库负载。