P2P系统的索引:信息到节点位置(IP地址+端口号)的映射
在文件共享(如电驴中):利用索引动态跟踪节点所共享的文件的位置、节点需要告诉索引它拥有哪些文件、节点搜索索引从而获知能够得到哪些文件
在即时消息(如QQ中):索引负责将用户名映射到位置、当用户开启IM应用时需要通知索引它的位置、节点检索索引确定用户的IP地址
- 集中式索引:
内容和文件传输是分布式的,但是内容定位是高度集中式的。节点加入时,通知中央服务器IP地址、内容
缺点:单点失效问题、性能瓶颈、版权问题
- 洪泛式查询: Query flooding
完全分布式架构。每个节点对它共享的文件进行索引,且只对它共享的文件进行索引
节点X与Y之间如果有TCP连接,那么构成一个边(虚拟链路),所有的活动节点和边构成覆盖网络(overlay network),每个结点邻居数一般少于10个
查询消息通过已有的TCP连接发送,如果查询未命中则节点转发查询消息、如果查询命中则利用反向路径发回查询节点
![](https://images2018.cnblogs.com/blog/1424868/201808/1424868-20180803170803637-186202036.png)
- 层次式覆盖网络
介于集中式索引和洪泛查询之间的方法。每个节点或者是一个超级节点,或者被分配一个超级节点
超级节点负责跟踪子节点的内容。节点和超级节点间、某些超级节点对间维持TCP连接。
![](https://images2018.cnblogs.com/blog/1424868/201808/1424868-20180803170812720-993367597.png)
一、即时通信
以Skype为例说明,其使用私有应用层协议,以下为大致原理
本质上是P2P的:用户/节点对之间直接通信
采用层次式覆盖网络架构,分布在超级节点上的索引负责维护用户名与IP地址间的映射
![](https://images2018.cnblogs.com/blog/1424868/201808/1424868-20180803170824497-274521616.png)
二、文件分发
BitTorrent协议是一种用于文件分发的P2P协议
参与一个特定文件分发的所有节点集合被称为一个洪流(torrent)。在一个洪流中的节点彼此下载等长度的文件块(Chunk),典型的块长度为256KB。
每个洪流具有一个基础设施结点,称为追踪器(tracker),当一个节点加入某洪流时,它向追踪器注册自己,并周期性地通知追踪器它仍在该洪流中。
追踪器跟踪正参与在洪流中的节点。当一个新的节点加入该洪流时,追踪器随机地从参与节点集合中选择一部分,并将这些节点IP地址发送给它 。节点收到这张节点列表后,会试图与该列表上的所有节点创建并行的TCP 连接。
所有和其成功地创建了TCP 连接的节点称为临近节点,临近节点是随时间而波动的。
节点通过TCP连接周期性地询问每个邻近节点它们所具有的Chunk列表。每有一个不同的邻居,就获得一个块列表。随后节点将通过TCP连接,对当前还没有的Chunk发出请求 。当它下载Chunk时,也为其他邻居上载Chunk。
最稀缺优先(rarest first) 技术:针对自身没有的块在邻居中决定最稀缺的块(即邻居中副本数量最少的块),并首先请求那些最稀
缺的块。这样,最稀缺块得到更为迅速的重新分发,每个Chunk在洪流中的副本数量可以得到均衡。
节点会对于每个邻居持续地测量接收到比特的速率,并确定以最高速率流入的4个邻居节点,它只会向正在向其发送Chunk且速率最快的4个邻居发送Chunk,每10秒重新评估top 4;每过30 秒,她也要随机地选择另外一个邻居发送Chunk,这样新加入的节点也能得到Chunk。
一且某节点获得了整个文件,它也许(自私地)离开洪流,或(大公无私地)留在该洪流中并继续向其他节点上载Chunk。
三、分布式散列表DHT
DHT是一种分布式数据库,其为每一个节点(对等方)分配一个n比特标识符,标识符是0~2^n范围内的整数。
通过散列函数把每个键映射成标识符范围内的一个整数。
- 存储
存储键值对时,如果初始键的散列值等于某个节点的标识符,则将该键存在这个节点;否则存在最邻近右继节点;
若初始键的散列值大于所有节点的标识符,则使用模2^n规则,在具有最小标识符的节点存储键值对。
- 查询
为了查询键值对,可以把节点组成环形DHT
节点组成抽象逻辑网,在覆盖网络中的链路不是物理链路,而仅是节点对之间的虚拟联络(该网存在于由物理链路、路由器和主机组成的“底层”计算机网络之上)
假如每个节点只知道直接后继和直接前驱,为了找到负责的键,在最差的情况下DHT中的所有N个结点将必须绕环转发该报文,在平均情况下需要发送N/2条报文。
因此可以该环形覆盖网络为基础,增加捷径,使每个节点不仅联系它的直接后继和直接前任,而且联系分布在环上的少量捷径节点,当某节点接收到一条查询一个键的报文时,它向最接近该键的邻居(后继邻居或捷径邻居之一)转发该报文。
- 节点离开
每个节点都知道自己的第一个后继节点和第二个后继节点的标识符和IP地址,并周期性的要求它们证明自己还活着(例如发送ping并要求回应)
如果某节点的第一个后继节点离开了,它可以直接把第二个后继节点改成第一个,再向其询问下一个后继节点的标识符和IP地址。
- 节点加入:
假如一个标识符为13的节点要加入该DHT,在加入时,它仅知道节点1存在于该DHT之中。
节点13将先要向节点1发送一条报文,问它的前任和后继是什么。该报文将通过DHT到达节点12,而它认识到自已将是13的前任节点,并且它的当前后继节点15将成为13的后继节点。
节点12向节点13发送它的前任和后继信息。
节点13此时能够加入DHT,标识它的后继节点为节点15,并通知节点12将其直接后继改为13 。
BitTorrent使用Kademlia DHT来产生一个分布式跟踪器。
在BitTorrent中,其键是洪流标识符而其值是当前参与洪流的所有节点的IP地址,
一个新到达的BitTorrent节点通过用某洪流标识符来查询DHT,确定负责该标识符(即在洪流中跟踪节点)的节点。在找到该节点后,到达的节点能够向它查询在洪流中的其他节点列表。