Redis 高可用:sentinel vs cluster 怎么选

起因

Redis 单实例够用阶段过了:

  • 数据量逼近单机 RAM
  • 单点故障 = 整服务挂
  • 写入 / QPS 接近单机极限

两个官方 HA 方案:

  • Sentinel:master-replica + 自动 failover(数据仍单 master)
  • Cluster:sharded,多 master,自动分片 + failover

下面对比哪种适合哪种场景。

Sentinel

[client]
   ↓ (asks sentinel)
[sentinel × 3] → 监控 master / replica
   ↓
[master] ←── async replication ──→ [replica × 2]
  • 1 master 服务读写
  • N replica 异步复制
  • 3+ sentinel 监控,master 挂自动选 replica 升 master

部署

sentinel.conf

port 26379
sentinel monitor mymaster 127.0.0.1 6379 2   # 2 票 = 多数
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

3 个 sentinel 跑在不同机器 → 任意 2 个同意才能 failover。

客户端连接

from redis.sentinel import Sentinel

sentinel = Sentinel([
    ('sentinel1', 26379),
    ('sentinel2', 26379),
    ('sentinel3', 26379),
])

master = sentinel.master_for('mymaster')
replica = sentinel.slave_for('mymaster')

master.set('key', 'val')        # 写
replica.get('key')              # 读(可能略 stale)

client 问 sentinel 当前 master 是谁 → 直连。
failover 时 sentinel 推新 master → client 重连。

优势

  • 简单(仍是单 master 模型)
  • 数据完整性强(无分片复杂性)
  • 支持所有 Redis command(包括 MULTI/EXEC、Lua、cluster 不支持的)

劣势

  • 单 master 写 QPS 上限(10w/s 量级)
  • 单机 RAM 上限(200 GB 算极限)
  • failover 期间(10-60s)短暂不可写

Cluster

[client]
   ↓ (knows slot → node mapping)
[node1: slot 0-5460]   ←→ [node2: slot 5461-10922]   ←→ [node3: slot 10923-16383]
   ↓                       ↓                              ↓
[replica1]              [replica2]                    [replica3]
  • 16384 个 hash slot 分配到 master 节点
  • key 哈希到 slot → slot 在哪个节点
  • 每 master 自带 replica 做 failover
  • 无 sentinel(cluster 节点之间 gossip)

部署

需要至少 3 master + 3 replica = 6 节点:

redis-cli --cluster create \
    127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 \
    127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 \
    --cluster-replicas 1

redis.conf

cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

客户端

from redis.cluster import RedisCluster

rc = RedisCluster(host='node1', port=7001, decode_responses=True)
rc.set('key', 'val')
rc.get('key')

client 知道 slot 映射 → 直接连到对应节点(无 sentinel proxy)。
MOVED redirect 让 client 学新映射。

优势

  • 水平扩展:6 节点撑 60w QPS,3 TB RAM
  • 自动 sharding(hash slot)
  • failover 同样自动

劣势

  • multi-key 操作受限(必须同 slot,hash tag {...}
  • pub/sub 不跨节点(cluster 模式下 pub/sub 是 broadcast 到所有节点)
  • 客户端要支持 cluster protocol
  • 运维复杂(add/remove node 时 reshard)

关键区别

Sentinel Cluster
数据分片 否(全在 master) 是(16384 slot)
容量上限 单机 RAM 累加
写 QPS 上限 单 master 累加
节点数 1m + N replica + 3 sentinel 3+ master + 3+ replica
failover 控制 sentinel 投票 gossip + 选举
multi-key 完全支持 必须同 slot ({tag})
pub/sub 正常 节点间不传
复杂度

怎么选

  • 数据 < 50 GB + 中等 QPS(< 50k) → Sentinel
  • 数据 > 100 GB + 高 QPS → Cluster
  • 多 key transaction / Lua 复杂 → Sentinel
  • 缓存场景(多数 key 独立) → Cluster
  • AWS / GCP / managed:用 ElastiCache / MemoryStore(背后就是这两个)

我们的实际:90% 项目 Sentinel 够。极少几个超大缓存项目用 Cluster。

hash tag (cluster multi-key)

cluster 默认每 key hash 到不同 slot → MGET/MSET 跨 slot 失败。
{...} 强制 key 同 slot:

rc.set('{user:42}:profile', '...')
rc.set('{user:42}:settings', '...')
rc.mget(['{user:42}:profile', '{user:42}:settings'])   # OK,同 slot

{user:42} 部分用来 hash。所有 {user:42}:* 在同节点。

设计 key 时考虑:相关 key 用同 tag → 减少跨节点操作。

failover 实测

Sentinel:master kill → 5-10 秒 detect + 选新 master + 客户端重连。
期间写失败 + 读 replica 可用。

Cluster:master kill → 类似 5-15 秒 detect + replica 提升。
该 slot 短暂不可写,其它 slot 正常。

两者都不是"零停机",但都是"短暂不可写"级别。

ProxySQL-like proxy?

Redis 没像 ProxySQL 那么常见的官方 proxy。
第三方:

  • twemproxy(Twitter,老)
  • codis(豌豆荚,老)
  • predixy(Cluster proxy,仍维护)

加 proxy 让 client 不需要懂 sentinel/cluster,但多一跳 + 单点。
非必要不引入。

监控

key 指标:

  • connected_clients
  • used_memory / maxmemory
  • instantaneous_ops_per_sec
  • evicted_keys(开 maxmemory-policy 时)
  • master_link_status(replica)
  • cluster_state(cluster)

Prometheus redis_exporter 一行装。

持久化

appendonly yes + appendfsync everysec → 最多丢 1 秒数据。
save 900 1 RDB 备份基础。

混合(aof + rdb)是默认推荐。
HA 也不替代持久化(脑裂 / 整集群挂)。

踩过的坑

  1. Sentinel quorum 配错:2 sentinel + quorum 2 → 任意 sentinel 挂
    → 没法 failover。最少 3 sentinel。

  2. cluster reshard 慢:迁移大 slot 几小时。期间客户端 MOVED redirect
    多 → latency 抖。计划好低峰期。

  3. client 不支持 cluster:老版本 jedis / lettuce / redis-py 没
    cluster 支持。升级 client。

  4. pub/sub in cluster:消息只在该 channel 所在节点发布。redis
    7+ 引入 sharded pub/sub SPUBLISH 改善但兼容性问题。

  5. 跨 DC:Redis 不为跨数据中心同步设计。延迟 > 几十 ms 时 replica
    lag 严重。跨 DC 用应用层方案(Kafka mirror / 应用双写)。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。