news 2026/9/10 18:29:28

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Valkey 集群原子槽迁移(Atomic Slot Migration)设计解析:从 `SYNCSLOTS` 协议到源码实现

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/placeholderkv

Atomic Slot Migration(ASM)是 Valkey 集群中用于在节点间迁移哈希槽(hash slot)的一套原子化机制,它取代了传统CLUSTER SETSLOT IMPORTING/MIGRATINGMIGRATE组合的逐键搬迁方式。本文以 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 IMPORTINGCLUSTER 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 节):

  1. 快照传输(Snapshot Transfer):源节点 fork 一个子进程,遍历并序列化该槽的所有 key,将数据以AOF(Append Only File)格式——即一串命令流——发送给目标节点。目标主节点与目标副本重放这些命令以恢复槽的状态。
  2. 增量更新(Incremental Updates):传输初始快照期间,源节点仍在服务业务请求。源节点记录这段时间内对槽 key 的变更,并在快照传输完成后以增量更新的方式发送给目标节点。
  3. 暂停(Pause):增量更新发送完毕后,源节点暂停对迁移槽的写入,拒绝针对这些槽的后续业务请求。暂停确保目标节点与源节点保持完全一致的状态。
  4. 故障转移(Failover):源节点暂停后,目标节点执行接管(takeover),成为该槽的主节点。
  5. 清理(Clean Up):目标节点成为槽主节点后,源节点通过集群拓扑更新获知这一变化,随即解除暂停并完成槽迁移。目标端失败的迁移会通过删除不再属于本节点的 key 进行清理。

值得注意的是,快照采用 AOF 命令流格式传输,而非 RDB 二进制格式,这使目标主节点与目标副本都能以命令重放方式独立恢复槽状态。

3.2 CLUSTER SYNCSLOTS:三方协调协议

CLUSTER SYNCSLOTS是 ASM 的内部协调命令,源节点、目标节点与目标副本通过它同步握手状态。其命令定义见 src/commands/cluster-syncslots.json:该命令是内部系统命令(SYSCMD),标记了ADMINNO_ASYNC_LOADINGSTALEMAY_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.c):

  • clusterCommandSyncSlotsEstablish(第 544 行)发起ESTABLISH,建立导入 job;
  • clusterCommandSyncSlotsSnapshotEof(第 658 行)在收到快照结束标记后发送REQUEST-PAUSE,并将状态推进到SLOT_IMPORT_WAITING_FOR_PAUSED
  • clusterCommandSyncSlotsPaused(第 686 行)确认源端已暂停,随即发送REQUEST-FAILOVER
  • clusterCommandSyncSlotsFailoverGranted(第 709 行)由源端授予最终故障转移授权;
  • clusterCommandSyncSlotsFinish(第 733 行)在目标端接管并完成清理后发出FINISH
  • clusterCommandSyncSlotsAck(第 2601 行)处理周期心跳。

设计文档提示可查看 src/cluster_migrateslots.c 的代码注释获取详细状态机。源码中确实定义了完整的状态枚举(第 16-43 行),分为三组:

  • 导入状态(Importing)SLOT_IMPORT_WAIT_ACKSLOT_IMPORT_RECEIVE_SNAPSHOTSLOT_IMPORT_WAITING_FOR_PAUSEDSLOT_IMPORT_FAILOVER_REQUESTEDSLOT_IMPORT_FAILOVER_GRANTEDSLOT_IMPORT_FINISHED_CLEANING_UPSLOT_IMPORT_OCCURRING_ON_PRIMARY
  • 导出状态(Exporting)SLOT_EXPORT_CONNECTINGSLOT_EXPORT_SEND_AUTHSLOT_EXPORT_READ_AUTH_RESPONSESLOT_EXPORT_SEND_ESTABLISHSLOT_EXPORT_READ_ESTABLISH_RESPONSESLOT_EXPORT_WAITING_TO_SNAPSHOTSLOT_EXPORT_SNAPSHOTTINGSLOT_EXPORT_STREAMINGSLOT_EXPORT_WAITING_TO_PAUSESLOT_EXPORT_FAILOVER_PAUSEDSLOT_EXPORT_FAILOVER_GRANTED
  • 终态(Terminal)SLOT_MIGRATION_JOB_FAILEDSLOT_MIGRATION_JOB_CANCELLEDSLOT_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 节):

  1. 源节点与目标节点之间的链路断开;
  2. 源节点或目标节点崩溃、停机或发生网络分区;
  3. 源节点或目标节点上发生故障转移;
  4. 目标节点发生内存不足(OOM)错误;
  5. 源节点的客户端输出缓冲区(client output buffer)过大;
  6. 管理员在源节点或目标节点上执行了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 命令(如GETSETDELINCR等)都会被拒绝并返回-MOVED错误,强制客户端转向正确的主节点。
  • 无 key 的读命令:节点会过滤SCANKEYS这类无 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 243(9.0 版本引入)。对应的保存与加载函数为 src/cluster_migrateslots.c 中的clusterRDBSaveSlotImports(第 363 行)与clusterRDBLoadSlotImport(第 393 行)。

加载语义如下:

  • 无论从磁盘还是主同步过程中加载包含槽导入 section 的 RDB 文件,系统都会新增一个迁移 job 来跟踪该导入;
  • 如果该 Valkey 节点在加载 RDB 后成为主节点,它会取消该槽迁移;
  • 加载该 opcode 是强制性的:若无法识别该 opcode,RDB 加载将直接失败,因为加载失败会造成一致性问题。

在主节点上加载这些跟踪状态,可以确保部分同步(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 AOF

Valkey 会将ESTABLISHFINISH命令传播到 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.json(since 9.0.0)。语法为:

CLUSTER MIGRATESLOTS SLOTSRANGE <start-slot> <end-slot> [SLOTSRANGE <start-slot> <end-slot> ...] NODE <node-id>
  • SLOTSRANGE后可跟一个或多个start-slot end-slot闭区间(含端点),一次可迁移多个槽范围;
  • NODE后跟 40 字符的十六进制目标节点 ID(^[0-9a-fA-F]{40}$);
  • 复杂度为 O(N),其中 N 是所有start slotend slot参数之间槽的总数;
  • 返回OK,标记为ADMINDANGEROUSSLOW类命令。

示例:将槽 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_name
operationIMPORTEXPORT
slot_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_AUTHSLOT_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 won't migrate the functions"(第 452 行)确认槽迁移不会迁移 Lua 函数库,函数需单独处理。

6. 总结

Atomic Slot Migration 以"槽级复制 + 原子故障转移 + 严格键隔离 + 持久化感知"四层设计,为 Valkey 集群提供了比逐键MIGRATE更优雅的槽迁移路径:

  • 对外原子:所有权交接仿照手动故障转移,切换点明确、无中间态可见;
  • 对内可靠SYNCSLOTS全状态机驱动,任何异常都会触发自动回滚,由主节点负责清理孤槽数据;
  • 持久化一致:RDB opcode 243(RDB_OPCODE_SLOT_IMPORT)与 AOF 中的ESTABLISH/FINISH配对语义保证了重启、全量同步与部分同步场景下迁移状态不丢失。

设计文档的完整状态机细节可继续阅读 src/cluster_migrateslots.c 中的代码注释与状态转换逻辑,边界场景可对照 tests/unit/cluster/cluster-migrateslots.tcl 中六十余个测试用例逐一验证;该特性自 Valkey 9.0.0 起随CLUSTER MIGRATESLOTSCLUSTER GETSLOTMIGRATIONSCLUSTER 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 18:26:08

2026年AI学术写作工具全景指南与效率提升

1. 学术写作的数字化革命&#xff1a;2026年AI工具全景指南在实验室熬到凌晨三点改论文格式的日子该结束了。去年帮导师整理文献时&#xff0c;我发现用传统方法分析200篇参考文献需要两周&#xff0c;而新一代AI工具把这个过程压缩到了37分钟。这不是未来幻想——2026年的学术…

作者头像 李华
网站建设 2026/9/10 18:25:19

2026亲测:专业降AI率工具选它准没错

2026 年降 AIGC 工具已从“机械式语句调整”进化为多维度智能优化系统&#xff0c;核心评测指标涵盖 AI 生成痕迹清除效率、学术表达准确性、格式结构完整性、长篇内容逻辑性、降重兼容性以及高校检测合规性。本次测评涵盖 5 款主流工具&#xff0c;测试范围包括中英文论文处理…

作者头像 李华