账本文件:blk 与 rev 是一对
比特币节点常被想象成”一条链”,落到磁盘上却是一组分开的文件。Bitcoin Core 官方的文件系统文档把 blocks/ 子目录的结构写得很清楚:真实区块以网络格式连续存放在一串按顺序编号的 blk 文件里,每个文件大约装 128 MiB;与之对应的是同样编号排列的一串 rev 文件;目录里还有一个 xor.dat,保存写数据文件时使用的滚动异或模式。区块索引放在 blocks/index/ 的 LevelDB 数据库中,-blocksdir 参数可以挪走区块数据目录,却挪不走这个索引路径。
关键在配对关系:每写一个 blk 文件,就配一个 rev 文件。区块是”只写不改”的账本,那 rev 文件是干什么的?

比特币的链会重组。节点要把一个已经接进主链的区块摘下来时,不能只删记录就完事——那个区块花掉的输出必须”恢复成未花费”,而恢复需要知道被花输出的金额、脚本和原交易信息。这份信息正是 rev 文件存的东西:节点在接块的同时,把每笔交易输入所花费的输出完整数据记进撤销文件,摘块时才能分毫不差地反向操作。
换句话说,维持”链可回退”这个抽象的代价,是并行的第二本账。区块文件管”发生过什么”,撤销文件管”怎么退回去”,两者成对落盘,缺了任何一半,对应区间的区块就没法干净地断开,只能整库重建索引。
顺序写与文件翻页的逻辑
区块不是一块一个文件,而是追加写进当前文件,写满翻页换下一个编号,周而复始。这种顺序追加的布局直接服务于磁盘使用方式:追加写几乎没有随机寻道,少量大文件也让目录管理、备份和校验都简单。读一个区块时,节点先从区块索引查出它落在哪个文件的哪个偏移,再定位读取——索引数据库只存元数据,不存区块本体。
这个结构也解释了若干运维直觉。其一,节点的数据增长是线性可预期的,新区块永远落在文件序列末尾;其二,远古区块原则上不再变动,校验历史可以按文件为单位做;其三,做数据裁剪时,只有不再用于回退的旧文件段才可能被回收,还牵扯索引与撤销数据的可用边界,裁剪前的检查清单不能省。
重组与排障时在哪里读它
重组发生时,节点从失败的分支逐块断开:查索引定位区块,读 blk 文件取回交易,再用 rev 的撤销数据恢复被花的输出。整个过程不需要重新执行交易,也不需要向网络重新要数据——撤销账在接块那一刻就备好了。
因此当节点报出区块文件读取错误,排查顺序可以从结构本身推出来:先看磁盘和文件系统层面有没有坏(容量写满、卷被回收、坏道是常见嫌疑);再对照 blk 与 rev 的文件编号是否连续,迁移或误删常常只留下半对;最后用 verifychain 一类工具核对索引与数据的一致性。要注意区块索引、区块数据、链上状态数据库是分开的部件,损坏的部位不同,症状和修复代价也不同:索引坏了重建即可,区块文件缺失则直接缩小了可回退的范围。
结构与日常体验的关系
对普通使用者来说,这些文件不会直接见到,但它们决定了几个常见判断:为什么有些”全节点”查不到远古历史——数据被裁剪,归档责任转给了别人;为什么区块浏览器依赖专门的归档节点而不是随便一台全节点;为什么磁盘故障之后,重建往往比修补快。区块文件、撤销文件、索引三者各司其职,支撑起”账本不可篡改、链尖可以回退”这个日常体验。本文是机制说明,不构成任何投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。