# 归档中心设计和实现 ## 概述 随着区块链的运行,存储区块数据的文件会逐渐增长,占用大量的磁盘空间.为减少`冷数据(低频使用的旧的区块数据)`的磁盘占用,`长安链·归档中心`v1.0_alpha版本提供了数据归档备份,归档数据数据查询,已归档数据扫描清理一整套解决方案 ## 设计 ### 整体流程 - 用户使用`CMC`工具,发送归档命令.该指令从链上查询出区块,将该区块数据通过GRPC传送到`归档中心`(对应下图步骤1,2) - 用户可以通过`CMC`工具在`归档中心`查询已经归档数据(如步骤3),也可以通过http接口查询(如步骤4) - 用户使用`扫描工具`,该工具根据已经归档高度,扫描区块文件,输出已经归档的文件的扫描信息(CSV文件),用户可根据CSV文件自行将已扫描文件删除,或转移到别的地方做备份(如图步骤5) - 用户使用`SDK`进行区块/交易查询时,`SDK`会自动先去归档中心查询,查不到数据会到链上查询(如图步骤7) - 为进一步压缩已经归档到归档中心的文件数据,归档中心提供了压缩数据的功能(如图步骤6)
归档中心整体流程
### 归档区块的逻辑 - 比较`待归档区块`的块高度和`归档中心已经归档的高度`,如果该区块与已归档的区块连不上,则报错.否则,检查该区块是否已经归档过.如该区块已经归档,则校验该区块hash是否和已归档的hash一致,如果一致则跳过,若不一致,则报错.若该区块尚未归档,则校验该区块hash是否正确,校验该区块指向的前一个区块hash是否正确.若正确则写入该区块数据,否则,报错.
归档区块逻辑
### 归档中心查询数据的逻辑 - 根据查询条件,首先获取数据存储的索引信息.根据索引信息中的高度和`归档中心`已压缩数据的高度做比较.若低于压缩高度,说明已压缩,检查是否解压过,若未解压,则解压,然后取出数据即可;若大于压缩高度,则直接从文件中读取数据即可
归档中心查询数据逻辑
### 扫描工具的逻辑 - 根据配置的已经归档高度,调用归档中心的查询区块接口.输出已归档高度下的所有的配置区块块高 - 扫描区块链节点上存储区块的文件路径,根据文件名来确定起始区块高度,终止区块高度.输出文件信息列表 - 遍历文件信息列表,确定是否含有创世区块(块高为0),或配置区块,输出该文件的信息到CSV文件中(文件命名格式为stub[year][month][day][hour][minute][second].csv),该文件内容如下图.第一列为扫描的区块文件名;第二,三列分别为文件中的起始,结束块高;第4列为是否可以清理(如果含有配置块或创世块为"n"代表不可清理,其他为"y"代表可以清理);第5列为文件中出现的配置区块的块高,用;进行分割. 同样的扫描工具也提供了根据扫描出的结果直接删除文件的功能,工具会根据上文生成的csv(需要在配置中配置一下)来进行清理所有第四列为"n"的文件数据
扫描工具运行逻辑
扫描工具扫描输出csv文件示意图
扫描工具根据CSV删除文件后输出存根结果
## 代码整体目录结构 ```bash ├── 操作文档.md ├── bfdb-clean-tools # 扫描工具 │   ├── config.yml # 扫描工具的配置文件 │   ├── stub20221021151245.csv # 根据配置文件运行扫描工具后输出的CSV文件 │   └── stub20221021151245.csv.result # 根据生成的CSV删除文件后的存根 ├── configs # 归档中心服务配置文件夹 │   ├── config.yml # 归档中心服务配置 │   ├── server_cert # 如果开启GRPC的TLS,为归档中心的证书和私钥 │   │   ├── archive-server.key # 归档中心的私钥 │   │   └── archive-server.pem # 归档中心的证书 │   └── trust_list # 如果开启了GRPC的TLS,为连接归档中心的CMC所使用的根证书 │   └── baec-client-root.pem # 签发CMC的根证书 ├── src # 归档中心服务源码 │   ├── archive_utils # 公共utils代码 │   ├── httpserver # http接口服务及处理 │   ├── interfaces # 归档中心存储的接口约定 │   ├── logger # 归档中心日志模块 │   ├── main.go # 归档中心入口 │   ├── process # 归档中心的业务处理模块 │   ├── rpcserver # rpc服务接口及处理 │   ├── serverconf # 解析配置文件 │   └── store │   ├── filestore # 封装的存储,读取区块的底层文件系统实现 │   └── levelkv # 封装的底层levelkv数据库操作 └── ut_cover.sh # ut脚本 ``` ## [详细使用见文档](../dev/%E5%BD%92%E6%A1%A3%E4%B8%AD%E5%BF%83%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md)