IPFS原理初探

什么是IPFS

IPFS(InterPlanetary File System 星际文件系统) 是一个旨在创建持久且分布式存储和共享文件的网络传输协议。它是一种内容可寻址的对等超媒体分发协议。IPFS网络中的节点将构成一个分布式文件系统(类似BitTorrent)。

IPFS协议利用比特币区块链协议网络基础设施的优势来存储不可更改的数据,移除网络上的重复文件,以及获取存储节点的地址信息——用以搜索网络中的文件。

IPFS是一个对等的分布式文件系统,它尝试为所有计算设备连接同一个文件系统。在某些方面,IPFS类似于万维网,但它也可以被视作一个独立的BitTorrent群、在同一个Git仓库中交换对象。因此,IPFS被认为在未来有可能取代HTTP协议。

最简单的总结就是,它是一个分布式文件存储项目,同时也是一个底层协议。IPFS当前的一个实现采用Go和JavaScript,并有Python的实现正在发展。

IPFS的特征

IPFS = HTTP + git + BitTorrent

其显著特性有:

  1. 永久的、去中心化保存和共享文件 (区块链模式下的存储Distributed HashTable)
  2. 点对点超媒体:P2P 保存各种各样类型的数据(BitTorrent)
  3. 版本化:可追溯文件修改历史(Git - Merkle DAG默克尔有向无环图))
  4. 内容可寻址:通过文件内容生成独立哈希值来标识文件,而不是通过文件保存位置来标识。相同内容的文件在系统中只会存在一份,节约存储空间 (区块链模式)

IPFS是一个版本化的分布式文件系统(类似git)

具有git等分布式版本控制系统的特性:提供上传下载文件等管理功能、能跟踪文件版本的变化且自动删除重复的文件版本的理解:对同一个文件修改,提交到ipfs后产生的是新的文件,旧的文件还会存在,这样,在ipfs库里就记录了两个版本(旧版和新版),记录了多个版本,自然就方便不同的版本的切换。

我们常用的版本控制软件比如svn ,git。

  • svn是c/s架构,s端(服务端)出现问题,那么意味着svn就不能用了
  • git有个最大的好处是每个开发者的电脑即是客户端也是服务器(P2P网络),就不存在单点故障的问题(服务器出现故障就不能访问的问题)

同时,IPFS的版本化特征还有一个好处就是自动去重,比如有两个目录,a和b ,a目录里有文件a1 b目录里也有a1 ,在ipfs只会记录一个a1

IPFS的数据存储

IPFS的数据存储
  • 存储方式: 它是分布式存储的, 为了方便传输,文件被切分成多个block, 每个block 通过hash运算得到唯一的ID, 方便在网络中进行识别和去重。 考虑到传输效率, 同一个block 可能有多个copy, 分别存储在不同的网络节点上。
  • 内容寻址方式: 每个block都有唯一的ID,我们只需要根据节点的ID 就可以获取到它所对应的block。

IPFS可溯源的保存与共享文件是利用了区块链系统的;内容可寻址则是利用了区块链的中的Merkle DAG,与RLP编码快速验证重复内容以及快速定位内容特性有点相似。简单来说, 就是2种数据结构merkle 和DAG(有向无环图)的结合

  1. 内容寻址: 使用hash ID来唯一识别一个数据块的内容
  2. 防篡改: 可以方便的检查哈希值来确认数据是否被篡改
  3. 去重: 由于内容相同的数据块哈希是相同的,可以很容去掉重复的数据,节省存储空间

IPFS的数据分发

如何把数据分发到不同的网络节点上, 达到分布式存储和共享的目的? 我们先思考一下, 通过网络,比如HTTP, 访问某个文件的步骤,

  1. 首先我们要知道存储这个文件的服务器地址,
  2. 然后我们需要知道这个文件对应的ID,
  3. 比如文件名。前者我们可以抽象成网络节点寻址,
  4. 后者我们抽象成文件对象寻址;

很多P2P网络的实现都采用DHT分布式哈希表的方式实现查找,其中Kademlia(简称Kad)算法由于其简单性、灵活性、安全性成为主流的实现方式,其结构与字典树有些相似。在IPFS中,这两种寻址方式使用了相同的算法: KAD

image

通过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 解决数据如何传输的问题。

IPLD(InterPlanetary Linked Data)描述数据

通过hash 值来实现内容寻址的方式在分布式计算领域得到了广泛的应用, 比如区块链, 再比如git repo。 虽然使用hash 连接数据的方式有相似之处, 但是底层数据结构并不能通用, IPFS 是个极具野心的项目, 为了让这些不同领域之间的数据可互操作, 它定义了统一的数据模型IPLD, 通过它, 可以方便地访问来自不同领域的数据。

数据的逻辑结构是用merkledag表示的, 那么它是如何实现的呢? 围绕merkledag作为核心, 它定义了以下几个概念:

  • merkle link 代表dag 中的边
  • merkel-dag 有向无环图
  • merkle-path 访问dag节点的类似unix path的路径
  • IPLD data model 基于json 的数据模型
  • IPLD serialized format 序列化格式
  • canonical 格式: 为了保证同样的logic object 总是序列化为一个同样的输出, 而制定的确定性规则

围绕这些定义它实现了下面几个components

  • CID 内容ID
  • data model 数据模型
  • serialization format 序列化格式
  • tools & libraries 工具和库
  • IPLD selector 类似CSS 选择器, 方便选取dag中的节点
  • IPLD transformation 对dag 进行转换计算

同时,数据是多样性的,为了给不同的数据建模, 我们需要一种通用的数据格式, 通过它可以最大程度地兼容不同的数据, IPFS 中定义了一个抽象的集合, multiformat, 包含multihash、multiaddr、multibase、multicodec、multistream几个部分。具体每个数据设计不赘述,我们把目光放回IPFS是如何定义数据的

IPLD 是IPFS 的数据描述格式, 解决了如何定义数据的问题

下面这张图是结合源代码整理的一份逻辑图,我们可以看到上面是一些高级的接口, 比如file, mfs, fuse 等。 下面是数据结构的持久化部分,节点之间交换的内容是以block 为基础的, 最下面就是物理存储了。比如block 存储在blocks 目录, 其他节点之间的信息存储在leveldb, 还有keystore, config 等。

源代码逻辑

lipP2P 传输数据

libP2P 是个模块化的网络协议栈,和socket传输数据类似

  1. 获取目标服务器地址
  2. 和目标服务器建立连接
  3. 握手协议
  4. 传输数据
  5. 关闭连接

libP2P将其进行模块化,定义了通用的接口, 可以很方便的进行扩展。
分别是:

  1. Peer Routing 路由
  2. Swarm (传输和连接)
  3. Distributed Record Store 记录存储
  4. Discovery 发现
Peer Routing

libP2P定义了routing 接口,目前有2个实现,分别是KAD routing 和 MDNS routing

ipfs 中的节点路由表是通过维护多个K-BUCKET来实现的

  • 每次新增节点, 会计算节点ID 和自身节点ID 之间的common prefix,
  • 根据这个公共前缀把节点加到对应的KBUCKET 中, KBUCKET 最大值为20,
  • 当超出时,再进行拆分

更新路由表的流程如下:


更新路由表的流程

除了KAD routing 之外, IPFS 也实现了MDNS routing, 主要用来在局域网内发现节点, 这个功能相对比较独立, 由于用到了多播地址, 在一些公有云部署环境中可能无法工作。

Swarm(传输和连接)

swarm 定义了以下接口:

  • transport 网络传输层的接口
  • connection 处理网络连接的接口
  • stream multiplex 同一connection 复用多个stream的接口

动态协商stream protocol,和socket的三次握手相似,多出了协议部分内容

  1. 默认先通过multistream-select 完成握手
  2. 发起方尝试使用某个协议, 接收方如果不接受, 再尝试其他协议, 直到找到双方都支持的协议或者协商失败。

另外为了提高协商效率, 也提供了一个ls 消息,用来查询目标节点支持的全部协议。

Distributed Record Store

record 表示一个记录, 可以用来存储一个键值对,比如ipns name publish 就是发布一个objectId 绑定指定 node id 的record 到ipfs 网络中, 这样通过ipns 寻址时就会查找对应的record, 再解析到objectId, 实现寻址的功能。

Discovery

目前系统支持3种发现方式, 分别是:

bootstrap 通过配置的启动节点发现其他的节点
random walk 通过查询随机生成的peerID, 从而发现新的节点
mdns 通过multicast 发现局域网内的节点

bootstrap与repo仓库的关系

当要向ipfs申请数据时,ipfs先会去本地的repo目录下去查找需要的数据,repo目录里的数据分两部分,一部分是metadata(元数据)一部分是block数据(真正的内容)。metadata想像成是商店的账本,账本上记录了所有商店的产品清单(目录),而block就是摆放在商店里的具体的内容。

如果ipfs只是通过自己的仓库查找数据,那就太狭隘了,ipfs还会根据bootstrap 列表,了解网络上其他节点的对等体列表,如果自己的仓库里没有需要的数据,就通过bootstrap列表,查到其它的节点是否有需要的数据。 IPFS自带有默认的受信任对等列表。

总的来说

总的来说,IPFS实现的协议如下图:


IPFS实现的协议

从下到上分为5个层次:

  • 最底层为传输层, 主要封装各种协议, 比如TCP,SCTP, BLE, TOR 等网络协议
  • 传输层上面封装了connection连接层,实现连接管理和通知等功能
  • 连接层上面是stream 层, 实现了stream的多路复用
  • stream层上面是peer routing路由层
  • 最上层是discovery, messaging以及record store 等

本文从定义数据和传输数据的角度分别介绍了IPFS的2个主要模块IPLD 和 libP2P:

  • IPLD 主要用来定义数据, 给数据建模
  • libP2P 解决数据传输问题

IPFS的远景目标就是替换现在浏览器使用的 HTTP 协议, 目前项目还在迭代开发中, 一些功能也在不断完善。为了解决数据的持久化问题, 引入了filecoin 的token激励机制,和区块链中的token一样,其根本作用是 通过token激励,让更多的节点加入到网络中来,从而提供更稳定的服务。

附录

本文引用:

美图技术团队: 从数据的角度带你深入了解IPFS
https://zhuanlan.zhihu.com/p/37455540 2018-05-31

百度百科: 星际文件系统IPFS https://baike.baidu.com/item/%E6%98%9F%E9%99%85%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/22695381?fr=aladdin 2019-08-18

xutaotao: 通过三大机制揭秘IPFS的工作原理 //www.greatytc.com/p/e4703ad30f65 2018-05-26

xutaotao: HTTP+git+BitTorrent=IPFS //www.greatytc.com/p/74d5b11cc365 2018-05-24

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,250评论 6 530
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,923评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,041评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,475评论 1 308
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,253评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,801评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,882评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,023评论 0 285
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,530评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,494评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,639评论 1 366
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,177评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,890评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,289评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,552评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,242评论 3 389
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,626评论 2 370

推荐阅读更多精彩内容