Redis Cluster 把键分到不同的槽位
Redis Cluster 把键的落点与机器身份分成两层:键先映射到一万六千三百八十四个固定槽之一,再由集群元数据描述各槽的主节点和副本。增加机器不会改变槽哈希函数,运维需要重新分配槽,客户端则发现当前拓扑并处理路由变化。槽、分片、主节点与副本不是可以相互替代的概念。 键选择槽,不要求机器持有连续区间 普通映射使用键的 CRC16/XMODEM 值对一万六千三百八十四取模。如果第一个左花括号与其后第一个右花括号之间存在非空标签,则只哈希这部分。例如 profile:{42} 和 quota:{42} 的完整键名不同,却位于同一个槽。标签只是数据放置规则,不是权限控制或租户隔离机制。 一个主节点可以拥有多个不连续的槽段。拓扑稳定时,一个槽有权威主节点;整个键属于该槽,大 hash 或有序集合不会被自动拆到多台机器。CLUSTER SHARDS 能显示分片成员及其槽段。尤其不能把“同一主节点”误当成“同一个槽”:前者是当前机器分配关系,后者才是多键操作需要的条件。 客户端也参与路由 支持集群的客户端维护槽映射,并连接拓扑中公布的节点。访问错误的主节点可能收到带目标地址的 MOVED,而不是得到键不存在。MOVED 要求更新路由;ASK 是迁移期间的临时重定向,需要先向目标发送 ASKING 再发送被重定向的命令,不能因此把该槽永久改归目标节点。 迁移也不是所有参与方瞬间同步更新地图。不同客户端可能暂时持有不同拓扑,多键涉及的数据在迁移期间分散到两端时,还可能得到 TRYAGAIN。应使用维护中的集群客户端,不能假设随便连一个入口就会自动代理所有命令。公布的地址不仅要让 Redis 节点互相可达,也必须能从应用所在网络访问。 放置关系不等于事务范围 MSET 这类服务端多键命令要求所有键属于同一个槽,仅仅处在同一物理主节点上仍不够。哈希标签可以满足同槽条件,但把所有租户都放进同一个标签又会集中负载,削弱分布能力。某个客户端方法如果拆成多个独立命令执行,也不能被当成一个原子的多键命令。 分片分配数据归属,复制则为一个分片提供副本。复制是异步的,所以副本读取可能落后。故障转移提升的是受影响分片的副本,并不是把整个集群作为不可分割的一组一起切换。发生故障时仍可能丢失已经确认的写入;连接中断也可能让调用者无法确定某条写操作最终有没有执行。 坏掉的样子 槽覆盖不完整或可达主节点不足,都可能阻止服务。在 cluster-require-full-coverage yes 下,一个分片不可用会使其他仍健康的主节点也拒绝键命令。三个没有副本的主节点能够展示数据分布,却没有能力从根本不存在的副本中恢复故障节点的数据,不能据此宣布已经具备高可用。 应一起检查槽覆盖、集群状态、副本健康、地址通告和客户端重定向错误。只增加节点不会自动搬迁已有数据,也不会自动拆开单个热键;重新分片、副本放置与客户端重试语义分别需要设计。应测试准备容忍的具体故障,而不是把节点握手成功当成高可用验收结果。 快速验证 原有实验记录使用 macOS、Python 3.14.4、Redis 8.10.1 和 redis-py 8.1.0;本轮审阅没有重新执行服务实验,下面的结果说明保留原有观察范围。准备 POSIX 环境、C 编译器、make、curl、tar 与 Python 3.10 或更新版本。安装步骤仅用 libc 构建 Redis 核心,并把客户端装入临时虚拟环境。 ...