Redis - Cluster集群:数据增多了,是该加内存还是加实例

Redis - Cluster集群:数据增多了,是该加内存还是加实例 文章目录引言Redis Cluster 的基本架构为什么是 16384 个槽槽的分配与数据迁移纵向扩展 vs 横向扩展的取舍Hash Tag让相关 key 落在同一个槽Cluster 的高可用实践建议引言当 Redis 单实例的内存不够用时有两条路纵向扩展加内存和横向扩展加实例。纵向扩展简单直接但有天花板——单机内存到 TB 级就很贵了而且实例越大 fork 越慢、RDB 越大、恢复越久。横向扩展是把数据分散到多个实例上每个实例只存一部分这就是切片集群。Redis Cluster 的基本架构Redis 3.0 引入了官方的切片集群方案——Redis Cluster。它的核心设计去中心化没有代理层没有中心节点所有节点地位平等。哈希槽分片把 key 空间划分为 16384 个槽slot每个节点负责一部分槽。客户端直连客户端通过 Smart Client 直接和数据所在的节点通信。一条命令的路由过程客户端 → CRC16(key) mod 16384 → 得到槽号 → 查本地槽位表 → 找到目标节点 → 发送命令如果客户端发错了节点目标节点会返回MOVED重定向告诉客户端正确的节点地址。Smart Client 会缓存槽位映射表减少重定向次数。为什么是 16384 个槽这个数字是精心选择的。节点之间通过 Gossip 协议交换心跳消息每条消息里都带着发送者负责的槽位图bitmap。16384 个槽的位图是 2KB16384 / 8 2048 字节如果用 65536 个槽就是 8KB对心跳消息体积影响很大。同时 16384 对于绝大多数集群规模几十到几百个节点来说粒度已经足够细能保证数据分布均匀。槽的分配与数据迁移集群初始化时需要手动或通过工具把 16384 个槽分配给各节点。比如 3 个节点节点 A槽 0-5460节点 B槽 5461-10922节点 C槽 10923-16383扩容时加入节点 D需要从现有节点迁移一部分槽到 D。迁移过程标记源节点的某个槽为MIGRATING状态。标记目标节点的对应槽为IMPORTING状态。逐个把该槽内的 key 从源节点MIGRATE到目标节点。所有 key 迁移完后更新槽位映射。迁移期间如果客户端访问正在迁移的 keykey 还在源节点正常返回。key 已经迁到目标节点源节点返回ASK重定向。ASK和MOVED的区别MOVED表示槽已经永久转移客户端要更新本地映射ASK表示只是这一次去那边问问下次还来源节点。纵向扩展 vs 横向扩展的取舍维度纵向扩展加内存横向扩展加实例实施难度低改配置重启高需要数据迁移成本曲线指数增长大内存贵线性增长fork 影响实例越大越严重每个实例小fork 快运维复杂度低高多节点管理容量上限单机物理内存理论无限一般建议单实例内存控制在2-6GB如果有 RDB/AOF 需求或10-25GB纯缓存场景超过就该考虑切片。Hash Tag让相关 key 落在同一个槽默认情况下不同 key 大概率落在不同槽不同节点。如果业务需要对多个 key 做原子操作比如 Lua 脚本、事务它们必须在同一个节点上。Hash Tag 机制如果 key 中包含{}Redis 只对花括号内的部分做 CRC16。user:{1000}:name →CRC16(1000)→ 同一个槽 user:{1000}:age →CRC16(1000)→ 同一个槽这样就能保证同一用户的所有 key 落在同一节点支持跨 key 操作。但要注意如果大量 key 用了相同的 Hash Tag会导致数据倾斜。Cluster 的高可用Redis Cluster 自带主从复制和故障转移不需要额外部署哨兵。每个主节点可以有一个或多个从节点。主节点挂了它的从节点会自动选举升级为新主节点。选举过程和哨兵类似从节点发起投票其他主节点投票拿到多数派的从节点升级。实践建议单实例内存不要太大建议 2-6GB保证 fork 快、迁移快。节点数控制在 1000 以内Gossip 通信开销会随节点数增长。合理使用 Hash Tag但要评估数据倾斜风险。每个主节点至少配一个从节点保证高可用。避免跨槽操作多 key 命令MGET、MSET如果 key 分布在不同节点会报错。客户端选择 Smart Client如 JedisCluster、Lettuce避免频繁重定向。切片集群解决了单机容量和吞吐的瓶颈但也引入了数据分布、跨节点操作、集群管理等新问题。理解槽的分配和迁移机制是运维 Redis Cluster 的基本功。