IPFS 和区块链有着非常紧密的联系, 随着区块链的不断发展,对数据的存储需求也越来越高, 由于性能和成本的限制,现有的区块链设计方案大部分都选择了把较大的数据存储在链外,通过对数据进行加密, 哈希运算等手段来防止数据被篡改, 在区块链上只引用所存数据的hash 值, 从而满足业务对数据的存储需求。 本文从IPFS 的底层设计出发, 结合源代码, 分析了IPFS 的一些技术细节。 由于IPFS还在不断更新中, 文中引用的部分可能和最新代码有所出入。
什么是IPFS?
维基百科上是这样解释的:是一个旨在创建持久且分布式存储和共享文件的网络传输协议。
上面的解释稍显晦涩, 我的理解是:
1. 首先它是一个FS(文件系统)
2. 其次它支持点对点传输
既然是文件系统, 那它和普通的文件系统有什么区别呢? 有以下几点区别:
存储方式: 它是分布式存储的, 为了方便传输,文件被切分成多个block, 每个block 通过hash运算得到唯一的ID, 方便在网络中进行识别和去重。 考虑到传输效率, 同一个block 可能有多个copy, 分别存储在不同的网络节点上。
内容寻址方式: 每个block都有唯一的ID,我们只需要根据节点的ID 就可以获取到它所对应的block。
那么问题来了, 既然文件被切分成了多个block,如何组织这些block 数据,组成逻辑上的文件呢? 在IFPS中采用的merkledag, 下面是 merkledag的一个示意图:
简单来说, 就是2种数据结构merkle 和DAG(有向无环图)的结合, 通过这种逻辑结构, 可以满足:
内容寻址: 使用hash ID来唯一识别一个数据块的内容
防篡改: 可以方便的检查哈希值来确认数据是否被篡改
去重: 由于内容相同的数据块哈希是相同的,可以很容去掉重复的数据,节省存储空间
确定了数据模型后, 接下来要做的事: 如何把数据分发到不同的网络节点上, 达到分布式存储和共享的目的? 我们先思考一下, 通过网络,比如HTTP, 访问某个文件的步骤,首先我们要知道存储这个文件的服务器地址, 然后我们需要知道这个文件对应的ID, 比如文件名。前者我们可以抽象成网络节点寻址, 后者我们抽象成文件对象寻址; 在IPFS(www.ipfsfirst.com )中, 这两种寻址方式使用了相同的算法, KAD, 介绍KAD算法的文章很多,这里不赘述, 只简单说明一下核心思想:
KAD 最精妙之处就是使用XOR 来计算ID 之间的距离,并且统一了节点ID 和 对象ID的寻址方式。 采用 XOR(按比特异或操作)算法计算 key 之间的“距离”。
这种做法使得它具备了类似于“几何距离”的某些特性(下面用 ⊕ 表示 XOR)
(A ⊕ B) == (B ⊕ A) XOR 符合“交换律”,具备对称性。
(A ⊕ A) == 0 反身性,自身距离为零
(A ⊕ B) > 0 【不同】的两个 key 之间的距离必大于零
(A ⊕ B) + (B ⊕ C) >= (A ⊕ C) 三角不等式
通过KAD算法,IPFS 把不同ID的数据块分发到与之距离较近的网络节点中,达到分布式存储的目的。
通过IPFS获取文件时,只需要根据merkledag, 按图索骥,根据每个block的ID, 通过KAD算法从相应网络节点中下载block数据, 最后验证是否数据完整, 完成拼接即可。
下面我们再从技术实现的角度做更深入的介绍。
IPFS的系统架构
我们先看一下IPFS的系统架构图, 分为5层:
一层为naming, 基于PKI的一个命名空间;
第二层为merkledag, IPFS 内部的逻辑数据结构;
第三层为exchange, 节点之间block data的交换协议;
第四层为routing, 主要实现节点寻址和对象寻址;
第五层为network, 封装了P2P通讯的连接和传输部分。
站在数据的角度来看, 又可以分为2个大的模块:
IPLD( InterPlanetary Linked Data) 主要用来定义数据, 给数据建模;
libp2p解决的是数据如何传输的问题。
发表评论 评论 (0 个评论)