目录
一、主从复制(Replication):备份,但不能自动顶上
数据怎么分片?—— CRC16 + 16384 个槽(slot)

Redis 单机跑着挺爽,但一旦挂了,服务就瘫了。老板问:“你这系统高可用吗?”你只能低头说:“……它很脆。”
所以,得搞集群。但 Redis 的集群不是一种,而是 三种演进形态:主从 → 哨兵 → Cluster。下面一个个掰开讲。
一、主从复制(Replication):备份,但不能自动顶上
是啥?
简单说:一个老大(主节点,Master),多个小弟(从节点,Slave)。
主负责读写,小弟只负责“抄作业”——主干了啥,小弟就照着干一遍。
比如你执行:
SET user:1001 "张三"
主节点写完后,会把这条命令发给所有从节点,从节点也执行一遍,数据就同步了。
有啥用?
- 读写分离:读请求打到从节点,减轻主的压力(但 Redis 读本来就快,这招用得不多)。
- 数据备份:主挂了,至少数据还在从节点上,不至于全丢。
- 故障恢复基础:后面哨兵和 Cluster 都靠它。
怎么配?(超简单)
从节点启动时加一行配置:
slaveof 192.168.1.10 6379 # 跟着谁干
或者运行时动态指定:
redis-cli -h 192.168.1.11 -p 6380
> SLAVEOF 192.168.1.10 6379
底层怎么同步的?
分两步:
1. 全量同步(第一次 or 主从断开太久)
- 从节点说:“老大,我要跟你混!”
- 主节点 fork 一个子进程,生成 RDB 快照(全量数据)
- 主一边生成快照,一边把新来的写命令缓存到 复制缓冲区(replication buffer)
- 快照生成完,发给从节点
- 从节点清空自己,加载 RDB
- 主再把缓存的命令发过去,从节点执行 → 数据一致
⚠️ 坑点:如果主内存很大(比如 20GB),fork 子进程会卡主线程几百毫秒!线上慎用全量同步。
2. 增量同步(日常)
主每执行一个写命令,就追加到 复制积压缓冲区(repl_backlog_buffer)(一个固定大小的环形队列)。
从节点断线重连后,告诉主:“我上次同步到 offset=12345”。
主一看,12345 还在 backlog 里,就从那开始发增量命令;如果不在了,只能全量同步。
✅ 优化建议:
- 调大
repl-backlog-size(默认 1MB),避免频繁全量同步- 网络不稳的环境,这个值至少设成几秒的写入量
缺点很明显:
- 主挂了,不会自动切换!你得手动把某个从节点
SLAVEOF NO ONE变成主,再通知所有客户端改地址。 - 运维累死,半夜主挂了,你得爬起来救火。
所以,主从只是基础,真正高可用得靠哨兵。
二、哨兵模式(Sentinel):给主从加个“监工”
是啥?
哨兵 = 一群独立的 Redis 进程,专门盯着主从集群,自动发现故障、自动选主、自动通知。
比如:主挂了 → 哨兵们开会投票 → 选一个从当新主 → 通知所有客户端“主换地址了”。
核心功能就三件事:
- 监控:不断 ping 主和从,看它们还活着没。
- 通知:出问题了,能发邮件、调 webhook(但一般靠客户端重连)。
- 自动故障转移:主挂了,自动提拔从节点上位。
怎么搭?(最少 3 个哨兵)
配置文件 sentinel.conf:
# 监控一个叫 "mymaster" 的主,IP 端口,至少 2 个哨兵同意才算它挂了
sentinel monitor mymaster 192.168.1.10 6379 2
# 主挂了多久算真挂?(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时时间
sentinel failover-timeout mymaster 180000
启动:
redis-sentinel sentinel.conf
哨兵怎么选新主?
不是随便选!有一套规则:
- 排除不健康的从节点(比如和主失联太久)
- 优先级高的先上:从节点配置
slave-priority 10(值越小优先级越高) - 复制偏移量大的优先:谁的数据最新,谁上
- Run ID 最小的:实在分不出,就按 ID 排(避免随机性)
💡 实战建议:
- 给你最信任的从节点设
slave-priority 1,其他设 100,确保它优先上位- 哨兵数量必须 ≥3,且部署在不同机器,避免“哨兵自己挂了没人管”
客户端怎么知道主换了?
哨兵不直接转发请求! 它只提供“主地址查询服务”。
客户端(比如 Jedis、Lettuce)启动时连的是哨兵,问:“现在主是谁?”
哨兵返回当前主的 IP:Port。
客户端缓存这个地址,直接连主干活。
如果主挂了,客户端下次请求失败,就重新问哨兵要新主地址。
⚠️ 坑点:
- 客户端必须支持 Sentinel!别用老掉牙的 Jedis 2.x
- 切换期间会有几秒不可用(哨兵检测 + 选主 + 客户端重连)
哨兵的局限性
- 还是单主架构:所有写请求压在一个主上,扛不住高并发写。
- 数据量不能太大:主内存超过 20GB,RDB 快照和复制压力山大。
- 运维复杂:要管 Redis + 哨兵两套进程。
所以,当业务大到单主扛不住时,就得上 Cluster。
三、Redis Cluster:真正的分布式数据库
是啥?
Cluster 把数据 分片(sharding) 存到多个主节点上,每个主带若干从。
比如 6 个节点:3 主 3 从,数据自动分 3 份,每份一个主负责写,一个从备份。
核心目标:水平扩展 + 自动故障转移 + 数据分片
数据怎么分片?—— CRC16 + 16384 个槽(slot)
- Redis 把整个 key 空间分成 16384 个槽(0 ~ 16383)
- 每个主节点负责一部分槽(比如 node1 负责 05460,node2 负责 546110922……)
- 客户端对 key 做
CRC16(key) % 16384,算出它属于哪个槽,就知道该打哪个节点
为啥是 16384?
- 太少:分片不均
- 太多:节点间心跳包太大(每个节点要广播自己负责哪些槽)
- 16384 是作者实测的平衡点
怎么搭?(官方推荐 6 节点起步)
- 启动 6 个 Redis 实例(3 主 3 从),配置开启 cluster:
cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 15000 - 用
redis-cli --cluster create自动分配槽和主从关系:redis-cli --cluster create \ 192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 \ 192.168.1.13:6380 192.168.1.14:6380 192.168.1.15:6380 \ --cluster-replicas 1
客户端怎么用?
- 必须用支持 Cluster 的客户端(如 Lettuce、Jedis 3.x+)
- 客户端连任意节点,如果 key 不在该节点,会返回
MOVED重定向指令,客户端自动跳转 - 高级客户端会缓存 slot → node 映射,后续直接打正确节点,无重定向开销
故障转移怎么工作?
- 每个主节点的从节点会监控主
- 主挂了,从节点发起选举(类似哨兵投票)
- 选出来的新主会广播“我接管了这些槽”
- 其他节点更新路由表
✅ 优势:
- 不需要哨兵!Cluster 自带故障检测和转移
- 写能力线性扩展:3 主就能扛 3 倍写压力
坑和限制(血泪经验)
1. 不支持多 key 操作跨槽
MGET user:1001 user:1002 # 如果两个 key 在不同槽,直接报错!
解决办法:
- 用 Hash Tag 强制 key 落到同一槽:
user:{1001}:profile和user:{1001}:order的{1001}会被 CRC16,保证同槽 - 或者业务层拆成多次请求
2. 不支持事务跨槽
MULTI/EXEC 里的命令必须在同一个节点,否则失败。
3. 运维复杂
- 扩容要 reshard(迁移槽),期间部分 key 不可用
- 缩容要先迁移数据,再下线节点
- 监控要盯 6 个节点 + 集群状态
但值得!
当你单机 Redis 内存超 20GB、QPS 超 10万、写压力大到主从扛不住时,Cluster 是唯一出路。
总结:怎么选?
| 场景 | 推荐方案 |
|---|---|
| 小项目,数据量小,能接受手动恢复 | 主从复制 |
| 中等规模,要求自动故障转移,写压力不大 | 哨兵模式 |
| 大规模,高并发写,数据量大(>50GB) | Redis Cluster |
最后一句大实话:
别为了“高大上”硬上 Cluster!
很多业务用哨兵 + 读写分离 + 缓存预热,完全够用。
先压测,再扩容,别让架构提前复杂化。
1468

被折叠的 条评论
为什么被折叠?



