ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FASTER Sum Store 示例全解析:用 RMW 操作与检查点验证并发正确性和崩溃恢复

FASTER Sum Store 示例全解析:用 RMW 操作与检查点验证并发正确性和崩溃恢复 数据库缓存KV存储【免费下载链接】FASTERFast persistent recoverable log and key-value store cache, in C# and C.项目地址https://gitcode.com/gh_mirrors/fa/FASTER点击查看免费下载Sum Store 是 FASTERC# 版官方 playground 中的一个自包含示例程序它以广告点击计数为业务场景用一组多线程 RMWRead-Modify-Write操作演示 FASTER 的并发写入、CPRConcurrent Persistent Recovery检查点与恢复能力。通过本文你将掌握 SumStore 的两种运行模式concurrency_test与recovery_test、全部命令行参数的含义、底层 FASTER API 的调用链如NewSession/ResumeSession、TryInitiateFullCheckpoint、Recover并能直接复现写入—崩溃—恢复—一致性校验的完整实验流程。一、Sum Store 示例解决了什么问题Sum Store 建模的场景非常直观数据库里存放着一批广告 IDAdId每个广告对应一个点击量计数器NumClicks。一组线程持续对同一个adId执行点击 1操作最后验证每个广告的计数是否与理论期望值一致。这个看似简单的场景恰好覆盖了 FASTER 最核心的两个能力多线程并发 RMW多个线程同时对同一把 key 做增量更新需要 FASTER 的索引hash index与混合日志hybrid log机制保证操作的原子性和正确性检查点与崩溃恢复CPR测试过程中周期性地做全量检查点full checkpoint允许在任何时刻杀死进程再从最新或指定检查点恢复并校验数据与 FASTER 报告给客户端线程的 CPR 序列号serial number简称 sno一致。示例本身不引入任何外部依赖全部数据由 SumStoreTypes.cs 中定义的结构体承载是理解 FASTER 编程模型最直接的可运行代码。二、运行前的准备工作1. 项目结构SumStore 位于仓库的cs/playground/SumStore/目录下核心文件包括Program.cs命令行入口解析测试模式与参数ConcurrencyTest.cs并发正确性测试实现RecoveryTest.cs恢复测试实现populate / continue / recoverSumStoreTypes.cskey/value/input/output 类型与Functions回调实现SumStore.csproj项目文件目标框架为net7.0通过ProjectReference直接引用..\..\src\core\FASTER.core.csproj因此每次构建都会编译当前仓库的 FASTER 核心源码。2. 构建与运行在cs/playground/SumStore/目录下执行dotnet build -c Release dotnet run -c Release -- 参数或直接运行构建产物Windows 下为SumStore.exeSumStore.exe concurrency_test 2示例运行时会使用当前目录下的logs/子目录存放混合日志logs/hlog与检查点数据。这些路径来自 ConcurrencyTest.cs 与 RecoveryTest.cs 中的Devices.CreateLogDevice(logs/hlog)和CheckpointSettings { CheckpointDir logs }。测试前请确保该目录可写恢复测试中检查点目录需要持久存在跨进程存活。三、命令总览两种模式与全部参数Program.cs 在无参数运行时打印完整用法Usage: Concurrency Test: SumStore.exe concurrency_test #threads Recovery Test: SumStore.exe recovery_test #threads populate SumStore.exe recovery_test #threads continue SumStore.exe recovery_test #threads recover SumStore.exe recovery_test #threads recover single_guid SumStore.exe recovery_test #threads recover index_guid hlog_guid各参数的语义如下表命令参数含义concurrency_test#threads并发正确性测试。用指定数量的线程执行 RMW完成后校验所有 key 的最终计数recovery_test#threads populate恢复测试第一阶段多线程执行 RMW同时后台线程周期性做全量检查点recovery_test#threads continue恢复后继续从最新检查点恢复并用ResumeSession续跑原先每个线程的会话sno 从上次提交点继续递增recovery_test#threads recover恢复到最新检查点然后做一致性校验recovery_test#threads recover single_guid恢复到指定 GUID 对应的检查点index 与 log 共用同一个 tokenrecovery_test#threads recover index_guid hlog_guid分别指定 index 检查点 GUID 与 hybrid log 检查点 GUID 进行恢复#threads是一个正整数表示并发执行 RMW 的工作线程数量。Program.cs中的参数解析逻辑Program.cs遵循以下规则single_guid场景会调用test.Recover(version, version)即把同一个 GUID 同时当作 index token 和 log token两个 GUID 场景调用test.Recover(indexGuid, hybridLogGuid)未知的task或参数数量不匹配都会抛出Invalid test/Invalid input异常。四、模式一Concurrency Test并发正确性测试1. 工作原理ConcurrencyTest的默认规模定义在 ConcurrencyTest.csconst long numUniqueKeys (1 22); // 约 419 万条不同 key const long keySpace (1L 14); // hash index 桶数量 const long numOps (1L 20); // 每个线程准备 100 万条输入 const long completePendingInterval (1 12); // 每 4096 次操作刷新一次 pending整个流程分为Prepare、Populate、Test三个阶段PrepareConcurrencyTest.cs每个线程预先构造长度为numOps的输入数组inputArray[i].adId i % numUniqueKeys每次点击数为 1。输入数组放入BlockingCollection供消费线程领取PopulateConcurrencyTest.cs每个工作线程先调用Native32.AffinitizeThreadRoundRobin((uint)threadId)做 CPU 亲和性绑定然后fht.NewSession(new Functions())注册会话接着执行numOps / 2次session.RMW操作TestConcurrencyTest.cs用新的只读会话对所有numUniqueKeys执行session.Read把读回的结果与按线程操作次数累加出来的期望数组逐项比较全部一致则输出Test successful。2. RMW 的正确性校验逻辑RMW 场景下 FASTER 会按记录的归属调用三种更新回调定义在 SumStoreTypes.csInitialUpdaterkey 首次写入时value input.numClicks直接初始化计数InPlaceUpdatervalue 在内存中时用Interlocked.Add(ref value.numClicks, ...)原子累加CopyUpdatervalue 已落盘read-only region时把旧值拷贝到新记录再累加newValue.numClicks oldValue.numClicks ...。三种回调各司其职共同保证读-改-写在内存/磁盘两种状态下语义一致。3. 关键调用点PopulateWorker里最值得注意的两处调用ConcurrencyTest.csvar status session.RMW(ref inputArray[i].adId, ref inputArray[i], Empty.Default, i); if (!status.IsCompletedSuccessfully) throw new Exception(); if (i % completePendingInterval 0) { session.CompletePending(false); } ... session.CompletePending(true); // 结束时强制排空所有 pending其中RMW的第 4 个参数是单调递增的序列号i——FASTER 的 CPR 机制正是靠每个客户端操作携带的 serial number 来记录提交点。CompletePending(false)表示能完成多少算多少CompletePending(true)表示等待全部完成。4. 执行结果验证测试结束后会输出Test successful若存在计数偏差则会打印每个 key 的期望值/实际值并按差值分布汇总counts字典与差值之和sum方便定位是哪些 key 发生了重复/丢失更新。这是判断 FASTER 多线程 RMW 是否原子、是否丢失更新的最直接依据。五、模式二Recovery Test检查点与崩溃恢复测试RecoveryTest的规模更大、流程更完整RecoveryTest.csconst long numUniqueKeys 1 23; // 约 838 万条 key const long indexSize 1L 20; const long numOps 4 * numUniqueKeys; const long refreshInterval 1 8; // 每 256 次操作 Refresh 一次 const long completePendingInterval 1 12; const int checkpointInterval 10 * 1000; // 每 10 秒一个检查点1. Populate写入 周期性检查点Populate()调用Run(false)RecoveryTest.cs内部启动两条执行路径一个后台检查点线程PeriodicCheckpointsRecoveryTest.cs每10_000毫秒执行一次fht.TryInitiateFullCheckpoint(out Guid token, CheckpointType.Snapshot); fht.CompleteCheckpointAsync().AsTask().GetAwaiter().GetResult();并打印Completed checkpoint {token}其中的 token 就是后续recover可用的 GUIDthreadCount 个写入线程RunThreadGenerateClicks每个线程用命名会话NewSessionFunctions(threadId.ToString())执行无限循环的 RMWkey 按sno % numUniqueKeys轮转同时每refreshInterval次调用session.Refresh()刷新 epoch每completePendingInterval次调用session.CompletePending(false)每numUniqueKeys次调用session.CompletePending(true)RecoveryTest.cs。由于写入是无限循环populate 阶段应跑一段时间后主动结束或杀掉进程这正是为验证崩溃恢复准备的。2. Continue从检查点恢复并续跑Continue()RecoveryTest.cs先调用fht.Recover()恢复到最新检查点再调用Run(true)。RunThread中continueSession true时执行关键恢复逻辑RecoveryTest.csdo { session fht.For(new Functions()).ResumeSessionFunctions(threadId.ToString(), out CommitPoint cp); sno cp.UntilSerialNo; } while (sno -1); Console.WriteLine(Session {0} recovered until {1}, threadId, sno); sno;ResumeSession是 FASTER 针对崩溃恢复提供的会话续接 API按会话名此处为线程 ID 字符串找回该会话上次持久化的提交点CommitPoint.UntilSerialNo新操作从sno 1继续。如果返回-1说明该会话在检查点中尚未提交任何操作需要重试。随后GenerateClicks(session, sno)从恢复的序列号继续点击 1从而验证跨崩溃继续写入不会丢数据也不会重复计数。3. Recover恢复并校验一致性两种 recover 形式最终都执行Test()RecoveryTest.cs校验逻辑分为四步对每个线程 ID 调用ResumeSession收集各自恢复到的CommitPoint.UntilSerialNo即 FASTER 为该会话报告的最后持久化序列号用新会话对所有 key 执行Read读出实际计数根据每个会话的sno累加计算期望值对会话_sno0.._sno之间每个i % numUniqueKeys的 key 各 1逐项比对全部一致输出Test successful。这里的核心思想是恢复后数据库内容必须与 FASTER 报告给客户端的 CPR 序列号严格一致——凡是被报告为已持久化的操作其效果必须体现在恢复后的数据中。这正是对 FASTER 持久化保证的直接检验。4. 底层 Recover API 对应关系RecoveryTest 使用的三种Recover重载与 FASTER 核心 API 的对应关系定义见 FASTER.cs示例调用FASTER API行为test.RecoverLatest()→fht.Recover()Recover(int numPagesToPreload -1, bool undoNextVersion true, long recoverTo -1)从最新有效检查点恢复test.Recover(version, version)Recover(Guid fullCheckpointToken, ...)用同一个 token 同时定位 index 与 log 检查点test.Recover(indexGuid, hybridLogGuid)Recover(Guid indexCheckpointToken, Guid hybridLogCheckpointToken, ...)分别指定 index 与 hybrid log 检查点 token此外FASTER 还提供对应的异步版本RecoverAsync(...)以及TryRecoverLatest构造参数见 FASTER.cs可供生产代码在FasterKV构造时自动尝试恢复最新检查点。六、Checkpoint 类型与 Settings 补充说明SumStore 使用的CheckpointType.Snapshot只是 FASTER 支持的两种全量检查点之一。枚举定义见 CheckpointSettings.csSnapshot默认对日志的内存部分单独做快照检查点期间日志可以继续追加磁盘占用相对可控FoldOver把当前日志整体 flush 到尾部实现增量式检查点但日志增长更快。TryInitiateFullCheckpoint的源码实现FASTER.cs会根据枚举选择不同的后台任务FoldOver对应FoldOverCheckpointTaskSnapshot对应SnapshotCheckpointTask然后通过状态机FullCheckpointStateMachine启动检查点若当前正有其他操作如正在执行另一轮检查点或索引扩容则会启动失败并返回falsetoken 为default。SumStore 构造FasterKV时传入的CheckpointSettings只设置了CheckpointDir logs本地存储目录。完整的CheckpointSettingsCheckpointSettings.cs还包含字段默认值说明CheckpointManagernull自定义检查点管理器如 Azure 设备场景为空时使用本地目录CheckpointDirnull本地存储检查点目录RemoveOutdatedfalse是否自动清理过期检查点ThrottleCheckpointFlushDelayMs-1检查点磁盘 IO 节流延迟毫秒-1 表示不节流CheckpointVersionSwitchVersionBarrierfalse是否用 barrier 保证线程不会同时处于两个检查点版本七、快速实验清单可直接照做并发正确性dotnet run -c Release -- concurrency_test 2观察输出Test successful可增大线程数如 8、16重复验证写入 检查点dotnet run -c Release -- recovery_test 2 populate运行约 30 秒后观察周期性的Completed checkpoint {GUID}输出模拟崩溃并续跑在 populate 运行期间直接终止进程如 CtrlC 或 kill然后执行dotnet run -c Release -- recovery_test 2 continue观察每个会话打印Session N recovered until {sno}并继续写入恢复最新并校验再次终止后执行dotnet run -c Release -- recovery_test 2 recover最终输出Test successful即表示恢复后的数据与 CPR 序列号完全一致恢复到指定检查点把第 2 步打印出的 GUID 作为参数执行dotnet run -c Release -- recovery_test 2 recover GUID单 token 场景或... recover index_guid log_guid双 token 场景验证 FASTER 能恢复到任意历史一致性点。八、从示例到生产可迁移的编程模式SumStore 虽然是一个测试程序但它把 FASTER 生产环境中最关键的三组 API 用法完整示范了出来命名会话 RMW 序列号NewSession(..., name)给会话命名RMW(..., serialNo)携带单调序列号这是 CPR 提交点追踪的前提周期性全量检查点TryInitiateFullCheckpointCompleteCheckpointAsync的发起—等待完成两段式调用可用于任何需要持久化保障的服务崩溃恢复三连Recover()最新/Recover(token)指定恢复存储ResumeSession(name, out CommitPoint)续接客户端会话并从cp.UntilSerialNo继续配合读回校验即可验证恢复一致性。在迁移到自己的业务时只需替换 SumStoreTypes.cs 中的AdId/NumClicks/Input/Output与Functions的四个回调实现其余会话管理与检查点编排逻辑可以直接沿用。更多 FASTER 编程模型与恢复细节可参考仓库文档 docs/20-fasterkv-basics.md 与 docs/25-fasterkv-recovery.md。赞分享数据库缓存KV存储【免费下载链接】FASTERFast persistent recoverable log and key-value store cache, in C# and C.项目地址https://gitcode.com/gh_mirrors/fa/FASTER点击查看免费下载相关推荐大麦自动抢票工具 ticket-purchase5 步快速跑通自动抢票流程大麦自动抢票工具 ticket purchase5 步快速跑通自动抢票流程 ticket purchase 是一款支持 Web 端与手机 APP 双端的大麦自GUI 自动化RPAMangle验证系统程序正确性和安全性检查Mangle验证系统程序正确性和安全性检查 概述 Mangle是一个用于演绎数据库编程的编程语言它扩展了Datalog语言支持聚合、函数调用和可选类型检查编程语言数据库5分钟彻底掌握Open-Shell让Windows找回熟悉的开始菜单5分钟彻底掌握Open Shell让Windows找回熟悉的开始菜单 还在为Windows 10/11那令人困惑的全屏开始菜单而烦恼吗Open Shell桌面应用上一篇Windows远程桌面多用户终极指南RDP Wrapper完整配置教程下一篇如何解锁Windows远程桌面多用户功能RDP Wrapper完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表