尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TigerBeetle State Sync 状态同步协议深度解析:落后副本如何追赶健康集群

TigerBeetle State Sync 状态同步协议深度解析:落后副本如何追赶健康集群 TigerBeetle State Sync 状态同步协议深度解析落后副本如何追赶健康集群【免费下载链接】tigerbeetleThe financial transactions database designed for mission critical safety and performance.项目地址: https://gitcode.com/GitHub_Trending/ti/tigerbeetle导读State Sync状态同步是 TigerBeetle 中让落后副本lagging replica追赶健康集群的核心机制。当某个副本因宕机、网络分区或运行缓慢而落后过多导致其日志与集群当前日志不再相交、无法通过 WAL repair 追上进度时State Sync 会以**检查点checkpoint**为单位把超级块、网格grid、LSM 表数据与客户端应答整体同步到集群的最新状态。读完本文你将掌握State Sync 的触发条件与 WAL repair 的取舍边界、由四个子协议组成的完整同步流程、sync_op_min/sync_op_max/sync_tables_op_range等关键状态字段的语义以及同步副本在复制协议中的特殊地位与存储确定性保证。本文基于 docs/internals/sync.md 展开并结合 src/vsr/replica.zig 与 src/vsr/superblock.zig 的源码实现进行验证与深化。State Sync 的定位WAL repair 之外的兜底协议State Sync 解决的是这样一类问题落后副本的日志与集群当前日志不再相交WAL repair 无法再将其追赶上来。这里的不相交意味着无论怎么按 WAL 逐条补齐副本都无法从自己的历史日志延续到集群的最新进度——它的历史已经断开了。在 Viewstamped Replication 的术语里这一机制被称作 state transfer但 TigerBeetle 为了避免与项目中的业务转账transfers混淆将其命名为State Sync。状态具体指什么在 State Sync 语境下状态由四部分构成超级块superblock中的vsr_state.checkpoint网格grid中的 manifest、free set 与 client sessions 块网格中的 LSM 表数据仅指已获取的块acquired blocks客户端应答client replies。与之对应State Sync 由四个子协议组成一一对应上述四类状态Sync Superblock——同步第 1 项对应 Protocol: Request ViewRepair Grid——同步第 2 项对应 Protocol: Repair GridSync Forest——同步第 3 项对应 Protocol: Sync ForestSync Client Replies——同步第 4 项对应 Protocol: Sync Client Replies。从 src/vsr/superblock.zig 中可以看到CheckpointState结构体正是围绕这几类状态组织校验和的它携带 checkpoint 的header该检查点提交到状态机的最后一条 prepare启动时从此处重放日志、free set 的blocks_acquired/blocks_released校验和、client_sessions块校验和、manifest_oldest/manifest_newest校验和等。这一结构体会原样嵌入view消息由主节点发送给同步中的副本见 src/vsr/replica.zig 的view_message_checkpoint()。两个关键性质同步目标是最新检查点。superblock-sync 的目标是健康集群的最新检查点当落后副本追赶到最新检查点或非常接近它时就可以过渡回健康状态。同步是懒惰lazy的。从逻辑上讲一旦超级块同步完成整个 State Sync 就算完成了——新超级块所指向的数据可以在后续按需on-demand传输。这大大降低了同步的峰值带宽与延迟成本。状态与 WAL 原子更新。新检查点状态superblock与 WAL 的更新是原子的——view消息同时携带两者保证副本不会出现超级块是新检查点、但 WAL 还是旧内容的错乱中间态。术语表同步副本与检查点副本角色Replica roles同步副本syncing replica正在执行 superblock-sync 的副本即处于同步算法第 1–5 步中的副本健康副本healthy replica未执行 superblock-sync 的副本是活跃集群的组成部分。检查点Checkpoints检查点标识checkpoint id / checkpoint identifier唯一标识某个特定检查点并且可以在不同副本上**可重现地reproducibly**生成。它是整个状态CheckpointState的哈希持久检查点durable checkpoint其状态至少在复制法定人数replication quorum个不同副本上都已存在的检查点。检查点标识会被附加到多种消息类型上详见下文存储确定性一节正是依赖它集群才能跨副本验证状态是否一致。同步算法六个步骤的完整流程整体算法可概括为以下步骤第 0 步判定是否需要同步见触发场景第 1 步响应view消息触发同步见触发方式第 2 步中断进行中的提交流程等待写操作完成取消可能停滞的读操作参见Grid.cancel()等待取消完成第 3 步将新检查点及匹配的 headers 安装进超级块将vsr_state.checkpoint.header提升为同步目标 header将vsr_state.checkpoint.parent_checkpoint_id提升为早于同步目标的那个检查点 id注意它不是我们自己的上一个检查点提升replica.commit_min将vsr_state.sync_op_min设为尚未修复的最小 op将vsr_state.sync_op_max设为尚未修复的最大 op若replica.sync_tables_op_range尚未设置则设置它见下文第 4 步修复数据修复在vsr_state.sync_op_{min,max}区间内创建的应答、free set / client sessions / manifest 块并修复在replica.sync_tables_op_range区间内创建的表块第 5 步收尾作为下一个检查点的一部分更新超级块sync_op_min 0、sync_op_max 0。两条重要的恢复规则如果副本启动时发现vsr_state.sync_op_max ≠ 0直接跳到第 4 步继续修复这正是启动时恢复未完成的同步如果同步旧目标的过程中收到新的同步目标replica.sync_tables_op_range不会立即更新——必须先完成旧同步范围内的全部表同步才开始同步新范围。这就是文档中强调的state sync ratchet状态同步棘轮避免反复重做同步工作。源码中的体现位于 src/vsr/replica.zig若已有sync_tables_op_range则继续沿用旧区间op_range.max sync_op_max只有在新启动同步时才从trigger 1开始设置新区间。为什么第 3 步要设置parent_checkpoint_id为早于同步目标的那个检查点这一步看起来反直觉但很关键State Sync 是跳到目标检查点的而不是一步步走过去的。如果我们把parent_checkpoint_id设成自己上一个检查点那么新旧检查点之间就存在一条本副本并未实际经历的路径而把 parent 指向集群中确实存在于同步目标之前的那个检查点才能保证检查点链在集群范围内是真实、一致的。sync_op_min/sync_op_max的精确语义这两个字段持久化在超级块的VSRState中。源码注释给出了精确定义src/vsr/superblock.zig当sync_op_max为零时表示所有网格块与应答都已同步完成此时sync_op_min也必为零当sync_op_max非零时表示必须修复在sync_op_min到sync_op_max含两端之间提交过程中本应写入的网格块与客户端应答——这些数据因 State Sync 跳过了这段日志而没有被正常写入。这两个字段同样暴露为 trace gaugereplica_sync_op_min/replica_sync_op_max见 src/vsr/replica.zig便于观测同步进度。第 0 步何时需要 State Sync需要同步的两类典型场景副本长时间宕机 / 分区 / 缓慢集群其余部分持续前进落后副本落后过多已无法通过 WAL repair 追赶新副本刚格式化并加入集群通过重配置加入同样落后过多无法通过 WAL repair 追赶。WAL repair 与 State Sync 的取舍边界决定走哪条路的判据以检查点为参照物若副本比主节点落后超过一个检查点必须使用 State Sync若副本与主节点处于同一检查点只能走 WAL repair若副本恰好落后一个检查点则两种方案都可能需要谨慎判断只用 State Sync 是错误的如果下一个检查点只有单一其他副本拥有那么那个超前副本的状态本身可能就是损坏的不能作为同步来源只用 WAL repair 是错误的如果所有可达的对等副本都已经环绕wrap了它们的日志把前一个检查点中的部分 prepares 驱逐了则 WAL 修复拿不到数据结论只要下一个检查点是持久的即已在复制法定人数的副本上完成复制落后副本最终必须走 State Sync。这一判断背后的逻辑是State Sync 要求目标检查点足够可信而持久检查点durable checkpoint恰好满足这一要求反之当检查点不持久时数据来源可能不可靠只能退而求其次用 WAL repair 补日志。第 1 步触发方式与超时兜底主动触发当副本收到携带更先进检查点的view消息时即触发 State Sync。view消息正文中嵌有完整的CheckpointState见 src/vsr/replica.zig 的view_message_checkpoint()同步副本据此得知目标检查点。被动兜底超时触发如果副本因为某个网格块或 prepare 长时间无法修复导致提交无法推进它会主动发送get_view来发起同步——这就是repair_sync_timeout的作用。源码实现位于 src/vsr/replica.zigon_repair_sync_timeout()中副本会记录commit_min的推进情况若检测到repair_stuck()修复停滞则记录告警日志on_repair_sync_timeout: request sync; lagging behind cluster并向主节点发送get_view请求。同步副本在复制协议中的特殊地位同步副本并不是被隔离起来的它们正常参与复制——可以追加 prepares、可以提交、有资格成为主节点。特别地同步副本可以在正常提交流程中推进自己的检查点。唯一限制是同步副本不计入自己检查点的复制法定人数。也就是说要让集群整体推进检查点必须至少有复制法定人数的健康副本。发现足够复制持久的检查点的机制依赖prepare_ok消息发送prepare_ok表明该副本已经完整同步了最近一个检查点。因此观察到某个commit_max充分领先于某检查点即可推断该检查点已经持久。正因如此同步副本会扣留withholdprepare_ok直到commit_max确认自己的检查点已在法定人数的不同副本上完整复制为止——相关字段为op_prepare_max、op_prepare_ok_max与op_repair_min。这一机制保证检查点是否持久的判断依据是客观的复制进度而不是某个副本的单方面声明。第 5 步为何要等到下一个检查点才收尾一个值得深究的设计问题是为什么sync_op_{min,max}的复位要等到下一个检查点而不是像视图变更view change那样立即更新文档给出了一个非常具体的故障场景数字编号为原文顺序开始同步到检查点X在检查点X之上继续提交但还没走完到下一个检查点Y在 opXa处一次提交或压缩compaction使用了表t。此时表t即将被同步但尚未完成修复走的是grid.read_global_queue在 opXb处作为压缩的一部分表t被释放release。假设这发生在t完成同步之前同步完成此时仍处在X与Y之间崩溃重启在X之上重放提交。尽管同步已完成、存储也没有损坏我们却丢失了表t。需要说明的是经由read_global_queue的修复通常会写回网格但并不保证如此例如当GridBlocksMissing已满时修复可能不会落盘。因此不能依赖修复一定会持久化这一假设。还有一个该场景的变体未来支持快照snapshots后将可能在从未需要表t的情况下就释放它即省略第 3 步。这种情况下重启瞬间重放之前超级块会声称数据文件是干净的没有待处理的 state sync但实际上却缺失了被引用的块。结论正是为了避免同步已完成但表块缺失这种悬挂状态才必须等到下一个检查点才把sync_op_{min,max}复位为零。在这之前同步范围仍然记录在超级块中重启后可恢复未完成的同步回到第 4 步。检查点标识与存储确定性检查点标识的附加位置checkpoint id是超级块CheckpointState的哈希被附加在以下消息类型上commandcommit携带发送方当前的检查点 idcommandping携带发送方当前的检查点 idcommandprepare携带的是该 prepare 最初被准备时所在检查点的 idcommandprepare_ok携带的是该 prepare 最初被准备时所在检查点的 id。这种prepare 携带其出生检查点 id的设计使得集群能在复制过程中追溯每个操作所属的检查点世代为下述确定性校验提供依据。存储确定性不一致即 panic在一切正常的情况下TigerBeetle 的存储是确定性的同一检查点的CheckpointState在任何副本上哈希结果都应一致。如果通过检查点 id 不匹配检测到非确定性检测到不匹配的副本会 panic。这是一个刻意的fail-fast设计——静默继续运行只会放大数据损坏。文档明确提示运维人员一旦出现这种 panic应当进行调查并进行人工干预。这也解释了为什么本文开头强调 checkpoint id可重现地reproducibly生成——可重现是确定性校验的前提。从源码看同步的实际执行链路为了让上述算法与真实代码对应起来这里梳理一下 src/vsr/replica.zig 中同步状态机的关键函数函数名与行号可自行在仓库中检索核对sync_start_from_committing()src/vsr/replica.zig从正常提交过渡到同步中根据当前commit_stage决定是直接取消网格操作还是等待不可中断的提交步骤完成sync_dispatch()src/vsr/replica.zig每次同步状态机迁移的枢纽负责在SyncStage各状态间切换如.canceling_commit、.canceling_grid、.updating_checkpoint、.idlesync_cancel_grid_callback()src/vsr/replica.zig网格取消完成后回调断言各类队列read_queue、read_global_queue、write_queue均已清空、IO 计数归零随后提取view消息中的检查点并进入.updating_checkpointsync_superblock_update_start()src/vsr/replica.zig执行第 3 步——重置状态机、free set、client sessions计算sync_op_max基于目标检查点 op 的 trigger并设置/沿用sync_tables_op_rangesync_superblock_update_finish()src/vsr/replica.zig断言新检查点已就位、commit_min已对齐随后打开网格、恢复消息接收并以日志sync: ops{}..{}/{}..{}输出同步范围src/vsr/replica.zigsync_content()src/vsr/replica.zig在第 4 步之后遍历森林forest统计待同步的表数量按 LSM 层级分布并记录sync: {} tables (by level: {any})日志随后将缺失的 LSM 表块入队修复sync_content_done()src/vsr/replica.zig、sync_client_replies_done()、sync_grid_done()分别判定内容同步、客户端应答同步与网格同步是否完成驱动第 5 步的收尾sync_enqueue_tables()/sync_reclaim_tables()src/vsr/replica.zig / src/vsr/replica.zig将待同步表入队、并在完成后回收/推进sync_tables_op_range。此外sync_tables_op_range字段在 src/vsr/replica.zig 声明其与sync_tables的成对关系sync_tables_op_range null当且仅当sync_tables null在多个断言中反复校验如 src/vsr/replica.zig可见同步中的表与其 op 范围是强绑定的。小结State Sync 的关键设计要点要点说明适用条件副本落后超过一个检查点或日志已与集群不相交WAL repair 无法追赶同步单位检查点checkpoint目标为健康集群的最新持久检查点四大子协议Sync Superblock、Repair Grid、Sync Forest、Sync Client Replies原子性新检查点状态superblock与 WAL 一起通过view消息原子更新懒惰性逻辑上超级块同步完成即算同步完成其余数据按需传输持久化范围sync_op_min/sync_op_max持久化在超级块中重启后从第 4 步续传棘轮约束收到新同步目标时不立即更新sync_tables_op_range先完成旧区间法定人数同步副本不参与自己检查点的复制法定人数prepare_ok反映检查点持久性确定性检查点 id 是CheckpointState的哈希跨副本不一致即 panic需人工介入对运维与开发者而言理解 State Sync 有助于判断副本落后时该修日志还是整状态读懂 replica 日志中sync: ops.../...与sync: N tables (by level: ...)的输出以及在遭遇检查点 id 不匹配导致 panic时第一时间意识到这是存储确定性受损的信号而非普通故障。更完整的协议细节可继续阅读 docs/internals/vsr.md特别是 Repair Grid / Sync Forest / Sync Client Replies 一节与 docs/internals/ARCHITECTURE.md。【免费下载链接】tigerbeetleThe financial transactions database designed for mission critical safety and performance.项目地址: https://gitcode.com/GitHub_Trending/ti/tigerbeetle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表