做存储系统的人大概都被compaction折磨过某开源LSM引擎跑着跑着突然写停顿后台线程瞬间打满磁盘IO像心电图一样疯狂波动。我读这篇名为FPGA-Accelerated Compactions for LSM-based Key-Value Store的论文时最大的感受是它把compaction这个脏活从CPU搬到了FPGA上并且在一套真实KV存储引擎上验证了可行性。这篇笔记会从问题起源、硬件卸载的设计取舍、系统关键技术模块、实验结论、工程落地难度几个层面拆解适合做数据库内核、存储引擎加速、硬件计算卸载的同学参考。1. 论文要解决的问题LSM compaction为什么值得FPGA“插手”1.1 LSM树的工作方式与compaction的角色凡是接触过现代存储引擎的人一定听过LSM TreeLog-Structured Merge Tree这套设计。它的核心哲学是把随机写变成顺序写。新数据先追加到内存里的有序结构MemTable写满后再刷成不可变的有序文件SSTable。磁盘上会同时存在多层SSTable层号从0开始递增每层有容量上限层内文件有序层与层之间可能有key范围重叠。为了让读路径不会因为层次太多而恶性退化也为了让删除的旧数据真正释放空间后台必须周期性执行compaction把若干旧SSTable读出来做归并排序生成新的更紧凑的SSTable。compaction按作用范围可以分两类。MemTable刷盘也叫minor compaction它只是把内存有序结构落盘代价不大真正消耗资源的是major compaction也就是跨层合并。常见的合并策略有Leveled Compaction与Size-Tiered Compaction。前者每层维护不重叠的sorted run读放大受控但写放大明显后者鼓励在层内形成大run写放大较小但读路径会退化。无论采用哪种策略compaction本质上都是N路有序文件归并、过滤旧数据、重写出新文件的过程。数量化地看Leveled Compaction的写放大通常能达到10到30倍。用户每写入1字节后台可能额外搬动10到30字节。这个放大倍数在写入密集场景下就是磁盘吞吐和CPU周期的直接消耗。很多线上系统跑得吃力并不是正常读写逻辑多复杂而是后台compaction经常把稀缺资源抢得太凶直接拖低整体吞吐和延迟稳定性。1.2 CPU做compaction的开销到底花在哪要理解论文为什么敢把compaction卸载到FPGA得先拆开一次major compaction在CPU上究竟做了什么。我用一次跨层合并举例假设要合并L1的5个文件与L2的3个文件每个文件包含若干16KB或32KB的数据块块内有序块间也存在某种排序关系。第一步是读取准备。每个文件要先解析Footer、Block Index、Bloom Filter等元数据再按块读取数据第二步是校验很多SSTable格式会在块尾部写CRC校验值CPU需要用CRC32指令逐块计算第三步是K路归并维护一个最小堆不断从多个输入run中弹出最小key再从对应文件补充新key第四步是数据重写把归并后的有序流按目标块大小切分重建索引与Bloom Filter计算新校验和并写盘。这四步里单纯比较key本身并不贵一次memcmp可能只有几个周期。真正的开销藏在内存访问模式里。K路归并的数据来源是N个不同文件块它们分散在内存各处CPU需要在多个输入流之间随机跳跃反复经历Cache Miss分支预测器面对哪个流更小这种高度依赖数据的判断也会频繁预测失败最小堆的push/pop又引入了控制依赖把流水线打得支离破碎。更不用说在软件层面一次compaction job要由多个后台线程调度线程切换、锁竞争、IO等待会进一步放大抖动。我自己的经验是在一套写入压力很大的系统上曾把合并线程从默认的8个降到4个写入吞吐反而变好了。原因很简单线程多了以后磁盘和CPU互相抢资源compaction与前端写入彼此打断p99延迟直接失控。这种由compaction引发的写停顿是LSM系统最难调的问题之一。只有真正理解CPU在compaction上烧掉了多少资源才能理解为什么要考虑把这条路搬到另一套硬件上去执行。2. 核心设计思路为什么选FPGA以及到底卸载什么2.1 为什么不是GPU不是ASIC而是FPGA聊硬件加速很多人第一反应是GPU。但compaction这个负载和图像处理很不一样。GPU的强项是大量无依赖的并行计算而K路归并有很强的数据依赖每个输出key都依赖前一个最小key的比较结果本质是流式顺序处理。GPU在处理这种依赖强、分支多的逻辑时效率不高而且无论计算多快数据都要经PCIe往返延迟天然比FPGA高。几十GB的compaction任务瓶颈往往不在纯计算而在数据移动和归并调度GPU并不占优。ASIC确实能做得更快但存储引擎的数据格式、合并策略、压缩方式都在不断演进。一旦算法变化ASIC只能重新流片成本巨大。FPGA的价值在于可以在逻辑层重新配置。它能为特定数据路径定制深度流水线把归并比较、CRC校验、索引重建全部做成并行数据流同时保持较低的待机功耗。还有一个常被忽略的优势FPGA能在数据移动路径上直接做计算。数据从DMA进来处理完再DMA出去中途不需要经过CPU Cache和内存层这是卸载最理想的形态。当然FPGA也有显著代价板卡贵开发效率远低于写C调试工具链也不友好。论文选它不代表它在所有维度上都最强而是它在可开发性、流水线并行度、功耗、延迟这个组合里平衡得最好。工程上一贯如此不是找绝对最优的硬件而是找约束条件下最顺手的工具。2.2 论文的卸载边界只卸载compaction的数据面设计硬件加速器时最容易犯的错误是贪多求全想加速读路径想加速索引扫描想加速压缩解压结果硬件复杂度爆炸反而拖垮主流程。这篇论文的取舍非常克制并没有把整个KV Store塞进FPGA而是只把compaction执行当作加速目标其他逻辑全部留在Host CPU上。Host侧依然负责WAL写入、MemTable维护、Manifest更新、读路径的Bloom Filter过滤、版本管理、缓存管理等。FPGA只承担一件事接收一组源SSTable执行块解析、校验、归并、过滤与重新打包产出一组新SSTable。这个划分很聪明因为compaction是LSM里最可批处理的环节。它不像读请求那样要求微秒级响应也不像写日志那样强调低延迟它是后台批量任务天然适合被流水线化与并行化。在工程上这个边界还带来一个隐含好处失败模型变得清晰。如果FPGA在处理中途出错Host端可以判定当前compaction job失败丢弃临时文件稍后重新调度。LSM树的版本结构、Manifest一致性等逻辑完全不受硬件执行过程影响。因为硬件只处理数据块不参与任何元数据决策即便FPGA设计有缺陷最坏情况只是产出损坏的SSTableHost侧完整性校验依然能够兜底。这种有限职责的卸载接口是实现低侵入集成的关键。3. 系统架构与关键实现细节3.1 总体数据通路数据怎么从Host到FPGA再落盘从论文的架构描述以及我接触加速卡的经验来看这类方案普遍采用PCIe作为互连链路。FPGA开发板插在主机PCIe插槽上通过DMA与Host内存交互。Host启动compaction时会构造一个job描述符写入FPGA端的job队列。描述符里包含源文件列表、目标Level、块大小、比较规则等。FPGA轮询该队列拿到任务后通过Host Memory DMA读取源数据块。这里有一个设计选择要特别说明FPGA读取源数据既可以走Host先读SSD到内存再DMA给FPGA也可以让FPGA直接接管NVMe设备。论文及大多数同类原型系统选择前者。理由很现实直接接管NVMe意味着要重写驱动和地址映射机制工作量爆炸兼容性也差。走Host内存通路最大好处是可以利用成熟的内核存储栈、文件系统和设备驱动开发成本低很多。坏处是数据多经过一次内存拷贝带宽开销翻倍。所以论文一定会把批量处理和流水线设计放在重要位置尽量把多次小DMA合并成大块连续搬运减少链路切换开销。新SSTable的写回路径与读路径对称。FPGA把生成好的块通过DMA写回Host内存再由Host端的异步IO线程落盘。这样做Host仍然掌握最终写盘调度权能限速、能处理故障也避免了FPGA去和文件系统做复杂交互。从整体看这是一条CPU下发job、FPGA处理数据面、CPU管理元数据的闭环链路职责边界非常干净。3.2 硬件compaction引擎内的关键模块把这类引擎拆开看通常会包含四个核心模块。第一是块解析与校验模块。SSTable有固定Footer和Header结构硬件解析器需要识别块偏移、块大小以及校验字段再对每个读入的块执行CRC32校验。这个模块在CPU上很费指令周期在FPGA上却是天然的高吞吐数据流操作多个校验单元可以并行工作吞吐远超软件逐块计算。第二是K路归并器也就是整个引擎的心脏。CPU做K路归并使用最小堆每产生一个输出都要做logK次比较。FPGA不需要复刻这种串行逻辑它能构造一个并行比较器网络每个时钟周期同时比较多个输入流头部key用组合逻辑选出最小值再从对应流推入下一个key。在流水线设计理想的情况下每个周期都能推进一个key等效吞吐远高于CPU上的堆操作。还有一点很关键FPGA可以把比较器宽度定制得比CPU一次比较更宽把多个key的解析合并到同一个时钟周期完成。第三是过滤器与索引重建模块。当归并输出积累到目标块大小时这块数据要封装成新SSTable的Data Block同时需要基于块内所有key计算新的Bloom Filter并在索引块中记录最小key与偏移。这些逻辑也都能流水线化。Bloom Filter的多个Hash函数对应多条并行计算路径在硬件上比CPU逐key执行哈希快很多。第四是写回打包模块。它负责按目标格式补上块尾校验写Footer、Index、Meta块形成可以直接在文件系统中落盘的标准SSTable。在新块生成期间硬件还要维护输入源的推进状态也就是记录每个输入文件还剩多少key。这部分是状态机逻辑最容易出Bug也是整个工程里最见功力的地方。读论文时如果能抓住这四块的边界和交互基本就掌握了这套硬件的核心。3.3 与KV Store主流程的协同一致性、失败处理、元数据更新compaction job不能像普通计算任务那样算完就结束它有严格的一致性约束。在成熟LSM引擎里一次compaction完成后要把新SSTable加入层级元数据、删除旧文件引用并把这次变化写入Manifest。这个步骤属于逻辑决策只适合CPU完成FPGA不应该碰。论文的标准做法是FPGA只负责生成新SSTable的临时数据文件Host拿到结果后校验文件完整性再走正常的Manifest更新流程。这里最关键的细节是原子性。要么整个compaction结果被接受要么整体被丢弃。如果一个job在FPGA上执行一半超时或出错Host要能安全回收临时文件重新调度任务。从系统层面看FPGA其实是一个异步数据生成器它不持有任何全局状态也没有版本概念。这种设计是它能低侵入嵌进成熟KV引擎的根本原因。Host如何感知FPGA完成任务一般两种方式轮询与中断。轮询实现简单、延迟稳定适合批量任务中断能减少Host空转但驱动复杂度更高。论文方案属于原型性质用轮询加异步IO回调完全合理。在工程化时很多人会忽略驱动层DMA Buffer的分配与生命周期管理而这恰恰是这类系统落地时最常见的暗坑之一。4. 实验评估解读性能提升到底在哪4.1 实验环境与基准都测了什么不看背景先看实验。论文的实验设置可以归纳成三个点硬件平台、测试负载、对比基线。硬件平台一般是某款主流中高端FPGA开发板加一个普通CPU主机存储设备用NVMe SSD或SSD阵列测试负载多为合成数据集key采用定长二进制序列方便硬件处理对比基线则是同一KV引擎在纯CPU模式下执行compaction。重点观察的指标有两类。一类是纯compaction吞吐单位常用MB/s或GB/s衡量FPGA每秒能归并并写出多少数据另一类是端到端指标包括写入密集基准下用户请求的延迟与吞吐、后台线程CPU占用、写停顿事件次数等。只盯着第一类不够因为硬件加速的最终价值要看前端工作的平滑性与稳定性有没有改善。4.2 结果解读看到一个克制的收益从论文呈现的总体趋势看FPGA对compaction的收益表现在两个方面。第一是compaction吞吐相对CPU多线程有明显提升量级大致在1.5倍上下具体数字随负载、块大小、key长度浮动第二是同等负载下CPU用于compaction的占用大幅下降后台线程基本被释放出来。这意味着同一个CPU可以承接更多用户请求与查询端到端写入场景的稳定性得以改善。不过这里要泼一盆冷水单纯compaction加速并不直接等于整个系统变快。如果磁盘本身已经饱和比如SSD顺序写带宽被占满FPGA生成数据再快最终落盘速度仍受存储介质限制。端到端收益能拉开差距前提是磁盘带宽有余量瓶颈确实在CPU计算与调度上。这一点决定了方案适用场景CPU已经被compaction打满、磁盘IO利用率却还没到上限的部署。下面用表格简单对比两种实现维度CPU compactionFPGA加速compaction归并比较最小堆依赖Cache与分支预测流水线比较网络时钟级推进校验计算占用CPU指令周期专用硬件单元并行执行内存带宽数据经CPU Cache多次搬运DMA直达不占用内核态内存CPU占用2到4个核跑满后台线程几乎空闲灵活性策略变更只需改代码数据格式变化需要改硬件逻辑成本没有额外硬件开销板卡昂贵开发周期长4.3 功耗与工程经济性值不值得这个成本论文里一般会给出功耗评估。FPGA在运行时的功耗通常处于一个相对可控的范围相比连续跑满的CPU核并不夸张。如果按每GB数据的能耗来算卸载之后通常能看到一定改善。但功耗只是其中一面另一面是采购与开发成本。一块高端FPGA开发板本身不便宜配套的逻辑开发、驱动开发、验证环境都需要远超普通软件项目的投入。这种投入只有在系统规模足够大、且compaction持续成为瓶颈时才值得考虑。从工程经济性角度我的观点是这类研究只适合作为最后的手段。如果项目里compaction有压力第一反应应该是调Level大小、调线程数、换用更合适的合并策略甚至是换盘。做完这些软优化仍然不够再评估硬件卸载才是理性路径。论文这类研究存在的价值恰恰是为未来大规模部署准备好可选项而不是让每个团队都马上去买板卡。5. 我的读后思考与工程落地视角5.1 这篇论文最值得学习的地方我最欣赏的一点是它没有把FPGA加速做成纯炫技项目而是严格遵循瓶颈在哪里加速就放在哪里的思路。它选了一个非常具体且足够疼的环节compaction定义了一个清晰的数据面边界保留Host侧对元数据和一致性的全部控制权。这种offload方法论可以迁移到很多场景压缩解压卸载、加密卸载、索引扫描卸载思路完全一致先量化成本比例再冻结数据格式然后在数据移动路径上插入专用处理单元。另一个亮点是它对工程复杂度的诚实。论文没有声称FPGA会取代CPU而是通过实验说明端到端收益受存储介质和PCIe带宽制约。这种有边界的结论比性能翻倍式的论文更有参考价值。读完之后读者能清楚判断哪些部署适合这个方案哪些不适合不会被带进盲目加速的坑里。5.2 局限性为什么还没有被广泛商用围绕FPGA加速compaction论文之外仍然存在几条硬伤。第一是PCIe链路绕行带来的带宽翻倍问题源数据从SSD搬到Host内存再从Host内存DMA进FPGA处理完再反向回去。真实部署中这个开销很容易吞掉一部分收益。第二是硬件逻辑与存储引擎的数据格式耦合太深。一旦引擎改了块格式、压缩算法、比较规则FPGA逻辑都要跟着动这对快速迭代的软件团队是沉重负担。第三是FPGA开发人才稀缺大部分存储团队不具备长期维护硬件逻辑的能力。这几条决定了它目前只适合特大规模基础设施去养不适合普通企业拿来即用。5.3 顺着这篇论文可以继续玩的方向我认为最有潜力的延续路线是把compaction计算搬进SSD控制器或计算型存储设备。这样做的好处是数据不用绕道PCIe和Host内存直接在设备内部完成合并与写回能省掉大半数据搬运开销。如果再叠加开放通道SSD或ZNS这类技术让设备感知LSM的分层结构compaction的时序与顺序写特性还能被进一步利用。只是这条路对设备厂商和存储引擎的协作要求很高短期仍然处于学术试验阶段。还有一类更软的方向把论文里的卸载接口抽象成compaction service。Host下发job描述硬件执行回调完成。这套接口一旦标准化后端无论是FPGA、专用ASIC、远程计算节点还是智能网卡都可以替换。从这个角度看论文真正留下的资产不是那一块FPGA逻辑而是一个被验证过的任务划分方式。我个人读完这篇论文最大的启发反而落在软件侧。我回去重新看了项目里compaction的调度代码把任务分割得更细给不同Level配了独立处理队列虽然没有引入FPGA但确实缓解了写停顿。硬件加速从来不是银弹但如果它能让你换个角度重新审视软件资源分配这论文的价值就已经超出一块板卡了。最后补一句选型建议如果团队完全没有FPGA开发背景别急着上板卡。先把手头LSM引擎的Compaction优先级、线程模型、Level大小跑明白大部分场景靠参数就能救回来。等真的到了CPU全烧在归并上、磁盘还闲着的阶段再回来看这篇论文你会发它里面画的每条数据通路都写着你的问题。