免责声明:本出版物的所有图片都是由协议实验室的Dirk从这张令人惊叹的幻灯片中摘录的。
当我们考虑P2P网络(如IPFS)中的内容交换时,我们首先想到的是分布式哈希表(DHT)。直觉告诉我们,如果我们想要检索通过散列(IPF中的CID)标识的内容块,那么QmPAwR(…)。,我们的对等点必须做的是转到他的分布式哈希表,并触发查找操作,以找到存储我们想要的信息的特定对等点。在IPFS中,这是正确的,只要Bitexchange在查找块的职责上已经失败(稍后将详细介绍)。
我们对IPF的初步了解是,它使用使用分布式哈希表映射的三种类型的键值对:
将数据标识符(即多散列CID)映射到已通告其拥有并愿意提供内容的对等方的提供商记录(这就是我们上面提到的分布式哈希表,我们将在本出版物中对其表示兴趣)。
将对等ID映射到一组可访问对等的多地址的对等记录。这是我们发现网络中的节点并开始与它们连接的方式。
将IPNS密钥(公钥的散列)映射到IPNS记录的IPNS记录。
由此,我们预计要在网络中找到任何内容,我们只需在提供商记录DHT中进行查找,以找到可以为我们提供此内容的对等点。然而,事实是,在这样做之前,IPFS节点实现一个交换接口,在不得不求助于DHT之前尝试并加速这个过程(顺便说一句,如果您想更深入地挖掘DHT以及IPF是如何利用它们的,我强烈推荐IPFS博客中的这篇文章)。
在深入研究如何请求内容之前,我们将快速绕道了解信息是如何存储在IPFS网络中的。IPFS使用Merkle DAG结构来表示数据。当您请求将文件存储到网络时,您的节点会将文件拆分成块。数据块彼此链接,并且每个数据块都使用其唯一的CID(内容的散列)进行标识。将文件拆分为块意味着每个块存储在不同的节点中,并且当您请求文件时,文件的不同部分来自不同的源,可以快速进行身份验证。
使用Merkle DAG存储内容还解决了网络中内容冗余的问题。如果您在网络中存储两个类似的文件,则它们将共享Merkle DAG的部分内容,即它们共享不一定需要存储两次的块。但是这种以块为单位的数据分离也意味着,当我们想要访问由几个块组成的特定内容时,我们需要找到存储这些块的所有节点,并请求它们的传输。这就是IPF中存在位交换的原因。
Bitexchange是IPFS的数据交易模块。它管理向网络中的对等点请求数据块和从网络中的对等点发送数据块。因此,正如我们预期的那样,位交换有两个主要任务:获取客户端从网络请求的块;以及帮助其他节点向它们发送我们可能拥有而其他节点想要的块。那么,位交换究竟是如何工作的呢?
假设我们正在搜索一个由以下三个块组成的文件:{CID1,CID2,CID3},并且其根块(即允许我们查找文件其余块的DAG根)为CID1。要获取此文件,我们将在节点中触发“获取CID1;#39;#39;操作”。这是位交换发挥作用的时刻。位交换通过向其所有连接的对等体发送WANT消息来开始他的操作,请求CID1的块。如果此请求没有响应,则位交换的工作完成。我们的节点将转到分布式哈希表来查找存储CID和故事结尾的节点(没有实现对标准分布式哈希表内容发现的加速)。
但是,如果我们的一些连接的节点响应此请求,说他们有这个块并将其发送给我们,会发生什么呢?然后,我们将记住这些节点,并将它们添加到该CID1的同一会话中。这些节点具有用于CID1的块这一事实意味着它们可能具有剩余的块用于文件(CID2和CID3)。我们希望记住会话中的节点的原因是,在下一轮中,我们可以缩小搜索范围,而不是盲目地向所有连接的对等点询问DAG的下一个CID,从而使我们的请求充斥网络。
现在设想一下,不是获取一个您不知道其余块的CID的特定文件,而是希望恢复Merkle DAG的一部分,您预先知道该部分的CID。在这种情况下,位交换将发送WantList,即CID的Want列表,而不是从您的节点发送单个Want。每个节点将记住从其他对等体接收的Wantlist,直到它们被取消,从而如果请求节点在获得块之前被具有WantList的对等体看到,则它可以将其转发给请求者。因此,WantList的接收者一旦拥有任何请求的块,就会将其转发回去。
最后,从请求节点中的WantList接收到块会向WantList被发送到的其余节点触发一条取消消息,以便用信号通知它们该块已经收到并且不再需要。
对我来说,Bitexchange的一些最紧迫的限制是它对带宽的低效使用,以及块的发现是盲目执行的事实(从这个意义上说,Bitexchange只与他的直接连接的对等体交谈)。幸运的是,为了解决这些问题,已经提出并实现了一些位交换扩展,例如:
使用额外的WANT-HAVE、WANT-BLOCK和HAVE消息,这样,如果我们连接的许多对等点都有块,那么我们就会首先使用这些新的位交换消息来表达我们想要块的愿望,然后再实际请求其传输,而不是直接向每个对等点请求块(如果我们连接的许多对等点都有块,这可能会导致重复的块交换)。这可能会增加获取数据块所需的RTT数量,但会降低协议的带宽要求。
会话中的智能节点选择算法。当节点告诉我们它有我们请求的块时,我们会将它们添加到会话中。对特定CID的后续请求与相应会话中的所有节点交换,但此交换被盲目广播给所有节点。为了使该协议更有效,已经提出了一些建议来智能地选择会话中的对等体,以便减少在网络中交换的消息数量,请求将被广播到该对等体。因此,这些请求将仅发送到会话中具有“最高分数”的节点(即具有我们所请求的块的最高概率的节点)。
此外,在Bitexchange中,我们只能通过块(或WantList中的一组块)的CID来请求块,而不能请求例如DAG的完整分支或完整子图。为了解决这个问题,在IPFS生态系统中实现了另一个类似于位交换的内容交换协议Graphsync。Graphsync利用IPLD(Merkle DAG结构的标准表示)和IPLD选择器(对这些结构执行查询的一种方式)的数据模型,因此请求中包含了IPLD选择器,而不是向对等体发送平面WANT请求。此选择器指定的是针对DAG结构的查询,因此它不是询问特定的块,而是询问其他人“嘿,伙计们,如果有人在DAG中有任何满足此查询的块,请将它们发送给我”。很聪明,对吧?我喜欢把Graphsync看作是“批处理Bitwsap请求”。
目前的Bitexchange实施已经显示出令人印象深刻的结果-与“传统的”分布式哈希表内容查找,甚至与集中式基础架构相比,它加快了发现和交换内容的速度(我强烈推荐阅读这篇文章,其中描述了IPF和Netflix团队如何利用IPF作为对等CDN,让Netflix基础架构内的节点协作并将公共片段播种到相邻节点,从而帮助提高容器分发的速度。难以置信,对吧?而这种改进的责任之一就是位交换)。
所有这一切并不意味着BitSwap不能进一步改进。我的感觉是,为了能够更好地实现Bitswp目前出色的实现,我们需要做的第一件事是了解协议的开销是什么,以及是什么阻碍了我们在IPF中更快地交换内容。是数据块的发现还是它们的实际传输?我们是否可以设计出更好的方式在网络中存储数据,以简化内容发现?更重要的是,我们将IPF用于大量的用例,这些用例可能需要交换几个小文件,也可能需要下载大型数据集。Bitexchange在这些场景下的性能是否相同,或者我们是否应该考虑实现“用例感知”的内容交换算法?
在这个意义上,在接下来的几周里,我计划构建一个测试环境来帮助我们回答这些问题,以便一起理解,并考虑到这一分析的结果,我们可以将P2P网络中的位交换和文件共享发挥到理论极限。
简而言之,围绕Bitexchange正在发生很多令人兴奋的事情。我可以多写几个小时,但我想把这个放在系列文章的第一部分,定期分享一些更新和知识药丸会更有意义。敬请关注!