资讯动态

Valkey 集群原子槽迁移(Atomic Slot Migration)设计解析:从 `SYNCSLOTS` 协议到源码实现

发布时间:2026/9/10 18:29:28 来源:尧图企业网站定制
Valkey 集群原子槽迁移Atomic Slot Migration设计解析从SYNCSLOTS协议到源码实现【免费下载链接】placeholderkvA flexible distributed key-value database that is optimized for caching and other realtime workloads.项目地址: https://gitcode.com/GitHub_Trending/pl/placeholderkvAtomic Slot MigrationASM是 Valkey 集群中用于在节点间迁移哈希槽hash slot的一套原子化机制它取代了传统CLUSTER SETSLOT IMPORTING/MIGRATING与MIGRATE组合的逐键搬迁方式。本文以 design-docs/atomic-slot-migration.md 为核心骨架结合 src/cluster_migrateslots.c 源码与 tests/unit/cluster/cluster-migrateslots.tcl 测试用例完整解析 ASM 的核心机制、CLUSTER SYNCSLOTS握手协议、自动回滚、键包含Key Containment以及 RDB/AOF 持久化语义。读完本文你将理解 Valkey 如何在不停服、逐槽原子切换的前提下完成数据搬迁以及如何通过CLUSTER MIGRATESLOTS等命令在生产中触发与观测槽迁移。1. 概述为什么需要原子槽迁移在经典 Valkey 集群运维中槽迁移需要管理员手动编排CLUSTER SETSLOT IMPORTING、CLUSTER SETSLOT MIGRATING并通过MIGRATE命令逐 key 搬迁数据整个过程复杂、易错且非原子。ASM 提供了一种**无缝seamless、原子atomic**的槽迁移方法它以槽为粒度完成数据搬迁与所有权转移完全替代上述手动流程。从源码角度看该特性由slotMigrationJob见 src/cluster_migrateslots.c 第 53-92 行驱动每个迁移在源端与目标端各持有一个 job迁移期间通过专用客户端连接协同推进状态机。2. 核心机制借用复制与故障转移原语ASM 并不逐 key 搬迁数据而是通过改造既有的复制Replication与故障转移Failover原语实现槽级操作基于槽的复制Slot-Based Replication物理数据迁移借用了主从复制机制但严格将复制范围限定在正在迁移的特定槽上而不是整库同步。原子所有权转移Atomic Ownership Transfer槽所有权的最终交接通过一个类似手动故障转移Manual Failover的协调流程完成保证切换的原子性。流量处理Traffic Handling整个迁移过程中源节点始终保留数据并持续服务业务请求只有在原子转移完成后系统才将流量干净利落地切换到目标节点。这三条原则决定了 ASM 的对外表现对业务方透明、无长时间不可用窗口。3. 实现细节3.1 高层流程五阶段快照-增量-切换一次完整的 ASM 迁移按以下五个阶段推进详见设计文档 3.1 节快照传输Snapshot Transfer源节点 fork 一个子进程遍历并序列化该槽的所有 key将数据以AOFAppend Only File格式——即一串命令流——发送给目标节点。目标主节点与目标副本重放这些命令以恢复槽的状态。增量更新Incremental Updates传输初始快照期间源节点仍在服务业务请求。源节点记录这段时间内对槽 key 的变更并在快照传输完成后以增量更新的方式发送给目标节点。暂停Pause增量更新发送完毕后源节点暂停对迁移槽的写入拒绝针对这些槽的后续业务请求。暂停确保目标节点与源节点保持完全一致的状态。故障转移Failover源节点暂停后目标节点执行接管takeover成为该槽的主节点。清理Clean Up目标节点成为槽主节点后源节点通过集群拓扑更新获知这一变化随即解除暂停并完成槽迁移。目标端失败的迁移会通过删除不再属于本节点的 key 进行清理。值得注意的是快照采用 AOF 命令流格式传输而非 RDB 二进制格式这使目标主节点与目标副本都能以命令重放方式独立恢复槽状态。3.2 CLUSTER SYNCSLOTS三方协调协议CLUSTER SYNCSLOTS是 ASM 的内部协调命令源节点、目标节点与目标副本通过它同步握手状态。其命令定义见 src/commands/cluster-syncslots.json该命令是内部系统命令SYSCMD标记了ADMIN、NO_ASYNC_LOADING、STALE、MAY_REPLICATE等标志并不面向普通用户直接调用。设计文档给出了完整的时序图Source Target Target Replica | | | |------------ SYNCSLOTS ESTABLISH --------------| | | |----- SYNCSLOTS ESTABLISH ------| |-------------------- OK ----------------------| | | | | |---------------- SYNCSLOTS ACK ----------------| | | | | |~~~~~~~~~~~~~~ snapshot as AOF ~~~~~~~~~~~~~~~~| | | |~~~~~~ forward snapshot ~~~~~~~~| |----------- SYNCSLOTS SNAPSHOT-EOF ------------| | | | | |----------- SYNCSLOTS REQUEST-PAUSE -----------| | | | | |~~~~~~~~~~~~ incremental changes ~~~~~~~~~~~~~~| | | |~~~~~~ forward changes ~~~~~~~~~| |--------------- SYNCSLOTS PAUSED --------------| | | | | |---------- SYNCSLOTS REQUEST-FAILOVER ---------| | | | | |---------- SYNCSLOTS FAILOVER-GRANTED ---------| | | | | | (performs takeover | | propagates topology) | | | | | |------- SYNCSLOTS FINISH -------| (finds out about topology | | change marks migration done) | | | | |整个迁移期间源节点与目标节点会周期性地交换SYNCSLOTS ACK消息来监测操作的健康状况与进度若在复制超时replication timeout内未收到确认迁移将被中止。从源码看这一协议由一系列命令处理函数逐状态推进见 src/cluster_migrateslots.cclusterCommandSyncSlotsEstablish第 544 行发起ESTABLISH建立导入 jobclusterCommandSyncSlotsSnapshotEof第 658 行在收到快照结束标记后发送REQUEST-PAUSE并将状态推进到SLOT_IMPORT_WAITING_FOR_PAUSEDclusterCommandSyncSlotsPaused第 686 行确认源端已暂停随即发送REQUEST-FAILOVERclusterCommandSyncSlotsFailoverGranted第 709 行由源端授予最终故障转移授权clusterCommandSyncSlotsFinish第 733 行在目标端接管并完成清理后发出FINISHclusterCommandSyncSlotsAck第 2601 行处理周期心跳。设计文档提示可查看 src/cluster_migrateslots.c 的代码注释获取详细状态机。源码中确实定义了完整的状态枚举第 16-43 行分为三组导入状态ImportingSLOT_IMPORT_WAIT_ACK、SLOT_IMPORT_RECEIVE_SNAPSHOT、SLOT_IMPORT_WAITING_FOR_PAUSED、SLOT_IMPORT_FAILOVER_REQUESTED、SLOT_IMPORT_FAILOVER_GRANTED、SLOT_IMPORT_FINISHED_CLEANING_UP、SLOT_IMPORT_OCCURRING_ON_PRIMARY导出状态ExportingSLOT_EXPORT_CONNECTING、SLOT_EXPORT_SEND_AUTH、SLOT_EXPORT_READ_AUTH_RESPONSE、SLOT_EXPORT_SEND_ESTABLISH、SLOT_EXPORT_READ_ESTABLISH_RESPONSE、SLOT_EXPORT_WAITING_TO_SNAPSHOT、SLOT_EXPORT_SNAPSHOTTING、SLOT_EXPORT_STREAMING、SLOT_EXPORT_WAITING_TO_PAUSE、SLOT_EXPORT_FAILOVER_PAUSED、SLOT_EXPORT_FAILOVER_GRANTED终态TerminalSLOT_MIGRATION_JOB_FAILED、SLOT_MIGRATION_JOB_CANCELLED、SLOT_MIGRATION_JOB_SUCCESS。每个slotMigrationJob结构体第 53-92 行记录迁移类型SLOT_MIGRATION_EXPORT/SLOT_MIGRATION_IMPORT、创建与最近更新时间、最近 ACK 时间、源/目标节点名、job 唯一名称40 字符十六进制串、对端连接、槽范围列表、手动故障转移结束时间mf_end、快照 fork 期间的写时复制字节数stat_cow_bytes等字段是整条迁移链路的任务档案。3.3 自动回滚失败场景与清理以下场景都会导致槽迁移失败设计文档 3.3 节源节点与目标节点之间的链路断开源节点或目标节点崩溃、停机或发生网络分区源节点或目标节点上发生故障转移目标节点发生内存不足OOM错误源节点的客户端输出缓冲区client output buffer过大管理员在源节点或目标节点上执行了FLUSHDB。在这些情况下ASM 会自动回滚迁移。回滚时序如下Source Target Target Replica | | | |------------ SYNCSLOTS ESTABLISH --------------| | | |----- SYNCSLOTS ESTABLISH ------| |-------------------- OK ----------------------| | ... ... ... | | | | FAILURE | | | | | (performs cleanup) | | | ~~~~~~ UNLINK key ... ~~~~~~~| | | | | | ------ SYNCSLOTS FINISH -------| | | |测试用例对上述失败路径有系统覆盖见 tests/unit/cluster/cluster-migrateslots.tcl例如OOM on target aborts migration第 1202 行Connection drop during import causes failure第 1769 行FLUSH on target during import第 1565 行与 FLUSH on source during export第 1605 行Import cancelled when source hangs第 1642 行与 Export cancelled when target hangs第 1679 行Slot export failed on failover第 1285 行Migration cannot connect to target第 2320 行3.3.1 清理Cleanup集群会自动清理失败或取消的槽迁移。主节点primary单独负责清理不再属于它的槽迁移期间被降级的主节点不会清理先前激活的槽导入。被提升的副本负责两件事清理该槽并发送SYNCSLOTS FINISH。测试 Partial data in replica removed on failover第 1238 行与 Partial data removed on cancel第 1169 行正是对这一清理语义的验证。3.4 键包含Key Containment迁移期间的访问隔离为保证一致性系统会对迁移期间的键访问进行严格管控带 key 的命令任何在非槽主节点上执行的带 key 命令如GET、SET、DEL、INCR等都会被拒绝并返回-MOVED错误强制客户端转向正确的主节点。无 key 的读命令节点会过滤SCAN、KEYS这类无 key 的读命令避免暴露正在导入的槽数据。目标分片中的每个节点都跟踪槽迁移 job 状态在迁移完成前向终端用户隐藏对该槽的写入。测试用例对键包含有非常细致的验证第 773-897 行包括 DBSIZE 命令排除导入中 key、KEYS/SCAN/RANDOMKEY 命令排除导入中 key、逐出eviction策略排除导入中 key、主动过期active expiration排除导入中 key 等。测试 Blocked clients are sent MOVED after export completion第 1431 行还验证了迁移完成后被阻塞客户端会收到MOVED重定向。3.4.1 全量同步、部分同步与 RDB为保证在导入期间重新同步resync的副本依然感知到导入状态Valkey 将每个进行中的槽导入序列化到 RDB 的一个新 opcode 定义的特殊 section 中编码内容包含 job 名称与正在导入的槽范围。该 opcode 在 src/rdb.h 第 146 行定义为RDB_OPCODE_SLOT_IMPORT 2439.0 版本引入。对应的保存与加载函数为 src/cluster_migrateslots.c 中的clusterRDBSaveSlotImports第 363 行与clusterRDBLoadSlotImport第 393 行。加载语义如下无论从磁盘还是主同步过程中加载包含槽导入 section 的 RDB 文件系统都会新增一个迁移 job 来跟踪该导入如果该 Valkey 节点在加载 RDB 后成为主节点它会取消该槽迁移加载该 opcode 是强制性的若无法识别该 opcodeRDB 加载将直接失败因为加载失败会造成一致性问题。在主节点上加载这些跟踪状态可以确保部分同步partial sync到重启后主节点的副本仍能在复制流中收到SYNCSLOTS FINISH消息。测试用例中 Restart ... during migration第 2033 行与 Failover cancels slot migration in transferred replica第 2219 行均与此相关。此外Migration not cancelled when snapshot takes more time than repl-timeout第 1961 行验证了长时间快照不会误触发超时取消。3.4.2 AOFValkey 会将ESTABLISH与FINISH命令传播到 AOF确保它们在 AOF 加载时能正确重放。与 RDB 类似如果加载后成为主节点时存在尚未配对的ESTABLISH即缺少后续FINISH系统会在加载后将这些 pending 的迁移标记为失败。测试 Replica migration persisted through AOF第 2340 行、Imported keys are persisted through AOF第 2406 行与 AOF maintains consistency through many migrations第 2437 行专门验证了 AOF 在多轮迁移下的持久化一致性。4. 用户侧命令接口虽然CLUSTER SYNCSLOTS是内部命令但用户可以通过三个公开命令发起、查询与取消槽迁移4.1 CLUSTER MIGRATESLOTS发起槽迁移命令定义见 src/commands/cluster-migrateslots.jsonsince 9.0.0。语法为CLUSTER MIGRATESLOTS SLOTSRANGE start-slot end-slot [SLOTSRANGE start-slot end-slot ...] NODE node-idSLOTSRANGE后可跟一个或多个start-slot end-slot闭区间含端点一次可迁移多个槽范围NODE后跟 40 字符的十六进制目标节点 ID^[0-9a-fA-F]{40}$复杂度为 O(N)其中 N 是所有start slot与end slot参数之间槽的总数返回OK标记为ADMIN、DANGEROUS、SLOW类命令。示例将槽 100-200 从当前节点迁移到节点abcd...CLUSTER MIGRATESLOTS SLOTSRANGE 100 200 NODE abcd1234...ef测试用例 Single source import - one shot第 501 行、Multiple slot ranges from same source第 999 行、Import multiple slot ranges with multiple slots第 1082 行、Slots split across shards during import第 1331 行等均覆盖了多范围、多槽的迁移场景。4.2 CLUSTER GETSLOTMIGRATIONS查询当前节点上正在进行或刚结束的槽导入/导出操作状态定义见 src/commands/cluster-getslotmigrations.json。返回一个嵌套数组每个迁移为一个 map包含以下字段字段说明name40 字节随机生成的十六进制字符串代表该迁移测试中亦称link_nameoperationIMPORT或EXPORTslot_ranges槽范围格式为start-end闭区间多个范围以空格分隔target_node/source_node迁移 job 中的目标/源节点名40 字符十六进制create_time/last_update_time/last_ack_time创建时间、最后更新时间、最后 ACK 时间Unix 秒state迁移 job 状态的人类可读字符串即前文状态机名称message带更多细节的人类可读状态消息cow_size槽迁移 fork 期间的写时复制字节数复杂度为 O(N)N 为活跃的槽导入/导出 job 数量。测试 CLUSTER GETSLOTMIGRATIONS command reported fields第 277 行验证了各字段的完整性。4.3 CLUSTER CANCELSLOTMIGRATIONS取消当前所有进行中的槽迁移操作定义见 src/commands/cluster-cancelslotmigrations.json。返回OK复杂度 O(N)N 为被取消的槽迁移操作数。测试 Test CLUSTER CANCELSLOTMIGRATIONS第 413 行与 Export unpauses when cancelled第 1400 行覆盖了取消语义。5. 迁移运行机制补充从源码与测试可以进一步确认几个运行细节ACL 与鉴权迁移连接支持 AUTH。测试 Import with AUTH on第 1716 行与 Import AUTH with WRONGPASS第 1750 行验证了带鉴权与错误密码场景Import with default user having no permission第 2180 行验证了无权限用户的处理。状态机中的SLOT_EXPORT_SEND_AUTH、SLOT_EXPORT_READ_AUTH_RESPONSE正是鉴权阶段。资源保护源端客户端输出缓冲区有强制上限测试 Export client buffer enforcement第 1792 行与 Export client buffer excluded from maxmemory第 1899 行验证了缓冲区与 maxmemory 的交互Slot migration remaining_repl_size on the source node第 2484 行与配置项slot-migration-max-failover-repl-bytes测试第 2527 行验证-1表示禁用限制说明迁移还与复制 backlog 字节数限制联动防止故障转移等待无界延长。与手动迁移互斥测试 Manual and atomic slot migration are mutually exclusive第 373 行表明 ASM 与传统的CLUSTER SETSLOT/MIGRATE手动迁移不可同时进行。并发迁移测试 Simultaneous imports第 897 行、Simultaneous exports第 946 行与 Export all slots from node第 1114 行验证了多 job 并发与整节点迁出的能力。函数Functions排除测试 Slot migration wont migrate the functions第 452 行确认槽迁移不会迁移 Lua 函数库函数需单独处理。6. 总结Atomic Slot Migration 以槽级复制 原子故障转移 严格键隔离 持久化感知四层设计为 Valkey 集群提供了比逐键MIGRATE更优雅的槽迁移路径对外原子所有权交接仿照手动故障转移切换点明确、无中间态可见对内可靠SYNCSLOTS全状态机驱动任何异常都会触发自动回滚由主节点负责清理孤槽数据持久化一致RDB opcode 243RDB_OPCODE_SLOT_IMPORT与 AOF 中的ESTABLISH/FINISH配对语义保证了重启、全量同步与部分同步场景下迁移状态不丢失。设计文档的完整状态机细节可继续阅读 src/cluster_migrateslots.c 中的代码注释与状态转换逻辑边界场景可对照 tests/unit/cluster/cluster-migrateslots.tcl 中六十余个测试用例逐一验证该特性自 Valkey 9.0.0 起随CLUSTER MIGRATESLOTS、CLUSTER GETSLOTMIGRATIONS、CLUSTER CANCELSLOTMIGRATIONS命令对外提供。【免费下载链接】placeholderkvA flexible distributed key-value database that is optimized for caching and other realtime workloads.项目地址: https://gitcode.com/GitHub_Trending/pl/placeholderkv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价