IPFS怎样存储你的文件?
阿牛哥 Lv4

从某种意义上说,IPFS就是一个文件系统,你向IPFS提交的文件都会存储在这个分布式文件系统内。为方便理解,我们可以将它和Windows的NTFS文件系统做一些类比。

从存储的角度看文件

一个文件从存储的角度看可以分为两部分,一是文件的内容,即文件中包含的数据,二是文件的元信息,比如文件名、创建日期、修改日期等等,这类信息本身不属于文件内容,而是关于文件内容的描述性信息。

文件系统要解决的就是如何存储文件内容和文件元信息。

NTFS如何存储文件?

先看看NTFS如何存储文件:

NTFS将硬盘空间划分为一个一个的“簇”,每个簇4KB大小,存储文件时,文件被按照4KB大小分割,假设需要存储一个32KB的文件,那么文件将被分为8个簇写到硬盘上,簇的在磁盘上位置被称为“索引”。

这是文件数据的存储方式,它的元信息,文件簇的位置(索引)、文件名、创建日期、修改日期等将存储到它所在目录中。目录本身也是一个文件,也包含元信息和内容部分,而内容部分被用来存储这个目录下所有的文件的元信息,而目录自身的元信息(目录的索引、目录名、创建时间等等)再由它的上一层目录存储,存储于后者的内容部分,以此类推便形成了整个文件系统的树形结构。

当我们打开一个目录时,Windows先读取目录的内容部分,得到该目录下所有文件的元信息,从而就能列出所有的文件名和创建时间,当打开一个文件时,就从根据索引找到文件内容。

IPFS如何存储文件?

IPFS的文件存储方式和NTFS十分类似,也区分文件和目录。

文件

首先,IPFS也要将文件分割为多个块。在IPFS中,一个块的大小默认是256KB,假如有一个1M的文件,那么它将被分割为4个块,接下来的过程要用到我们上一篇文章讲的默克尔树的知识。

还以1M文件为例:

  1. 分割为4个256K的块
  2. 计算出每个块的SHA256哈希值,并将结果以base58编码,得到4个base58编码的字符串
  3. 然后再将这4个字符串拼在一起计算SHA256哈希值,对得到的值再做一次base58编码,所得结果即该文件的索引。

ipfs的文件存储方式

可见,只要文件内容相同,那么最终得到的索引也是完全相同的。在IPFS中,索引就相当于NTFS中簇的位置。当我们需要从IPFS中下载一个文件时,只要知道文件的索引,就可以定位到这个文件,并把文件通过ipfs get下载下来,像这样:

1
ipfs get Qm....

目录

我们希望IPFS也能像本地硬盘一样有树形结构,这样不光是为了组织文件,还可以在目录中存储文件名等元信息。

具体过程是:

  1. 为目录下的每一各文件的”文件名+索引”构建为一个IPFS Link对象
  2. 把目录下的所有IPFS Link拼接为一个数组
  3. 计算数组的SHA256哈希,得到的哈希值就是目录的索引。

ipfs的目录存储方式

可见,只要知晓了目录的哈希值,就能获知目录下每个文件的文件名和内容。但目录自身却不包含目录名数据,除非它还有上层目录,由上层目录描述它的元信息。

一些误解

  1. IPFS浪费空间

之前已经讲过,文件会被分割成若干个256K的块,如果IPFS里有两个块的哈希(SHA256值)一样,那么说明这两个块的内容完全一致,在节点里只要存储一份即可。

从这个江都讲,IPFS是懂得节省空间的。

  1. IPFS的文件内容可以像硬盘上文件一样修改

从某种意义上说,IPFS只能模拟出“修改”的效果,因为已经存储到IPFS上的数据是没法变更的。所谓修改,其实是在IPFS上新增了一个同名的文件。

所以,IPFS上的数据只能新增,不能变更。比如你通过ipfs add ...命令上传了一个文档,然后你需要对之前的文档做一些修改,那么你需要再次上传文件。

之所以不支持修改文件,主要原因是在一个分布式系统中,修改文件会带来很多问题,比如文件的同步、一致性等等,开发复杂度也会相当大,所以分布式文件系统一般都不支持文件修改。

  1. 上传的文件会永久存在于IPFS网络中吗?

这要看有多少节点保存了文件的副本。在IPFS中,单个节点并不包含所有的文件,只包含整个IPFS的部分数据,如果一个文件之前通过ipfs add命令存储在某个节点上,而这个文件从未被其他节点同步,那么一旦该节点下线,该文件将从IPFS网络中消失。

当你从IPFS网络中下载文件时,通过ipfs get下载下来的文件也只是暂存在你的节点上,除非你通过命令“固定”它,否则过一段时间就会被IPFS清理掉。因此,文件并不是永久存储在IPFS中的。

总结

本文介绍了IPFS的文件存储方式,可见IPFS构造的文件系统并不复杂,设计思想和常见的硬盘文件系统有几分相似,区别在于IPFS是一套分布式的文件系统,这决定了它存储上的一些特点,比如哈希索引、不可修改等等。