1.3k likes | 1.51k Views
P2P 网络体系 (3). 大纲. 第一代 P2P 网络:混合式 P2P 体系 第二代 P2P 网络:无结构 P2P 体系 第三代 P2P 网络:结构化 P2P 体系(*). 第三代 P2P 网络:结构化 P2P 体系. Chord&CFS CAN Tapestry&OceanStore Pastry&Past Kademlia SkipNet Viceroy Koorde Cycloid. 其他著名结构化 P2P 网络.
E N D
大纲 • 第一代P2P网络:混合式P2P体系 • 第二代P2P网络:无结构P2P体系 • 第三代P2P网络:结构化P2P体系(*)
第三代P2P网络:结构化P2P体系 • Chord&CFS • CAN • Tapestry&OceanStore • Pastry&Past • Kademlia • SkipNet • Viceroy • Koorde • Cycloid
其他著名结构化P2P网络 • 实践系统:,提出更加容错、实用的P2P系统,如Kademlia(2002),路由方式类似Chord,但采用异或的距离量度,并将网络结构配置信息融合到每条消息中;SkipNet(2003)模型,类似Chord,但采用跳表SkipList数据结构,提供结点路由、对象语义两方面的局部性,以前的结构化P2P网络都没有做到 • 理论模型:具有特殊性质的新型结构化P2P模型——常数度P2P网络,其路由、定位、自组织方式与过去的模型区别不大,但每个结点的“度”(即连接数)是固定的,不随网络规模改变,保持路由效率的同时减小了自适应开销,常见模型有Viceroy(2002)、Koorde(2003)、Cycloid(2004)
实践系统 • 一、Kademlia • 二、SkipNet
一、Kademlia:基于异或度量的P2P信息系统 • 由于“异或”是对称的,因此Kademlia结点能从路由消息中获得有用的网络配置信息,这种“捎带更新”方法使得Kademlia以很小的开销获得了很大的自适应性 • Kademlia不像Chord需要严格的路由表,可以发送消息给其路由表任意一段(interval)中的每一个结点,让基于时延选择路由下一跳,甚至让它们发送并行的异步消息
Kademlia的异或度量、结点状态和自组织 • Kademlia结点、对象ID分配、以及索引负责方式同经典的P2P网络 • 设Kad网络中有两个结点,ID分别为x,y,其距离d(x,y)=x⊕y,d(x,y)=d(y,x),具有对称性和三角属性,类似CAN、Tapestry和Pastry,不同于Chord • 与Chord的顺时针环形度量一样具有单向性,保证了所有对相同数据对象的定位最终将会聚于相同的路径,且越往后走会聚的可能性越高
Kademlia的结点状态和自组织 • 每个Kad结点维护一个称为k-buckets的路由表,以采用160位ID为例,对每位i,结点都保存一个链表,称为一个k-bucket,其中记录到自己的异或距离在2i与2i+1之间的一些结点,并按照最近访问时间从尾到头排列 • 每个链表项是形如(IP, UDP port, nodeID)的三元组 • i越大,其链表项越多,并呈指数增长,因此Kad网络给出链表长度上限k
Kademlia概况 ■距离的概念:两个标识符之间位异或的值。 数学依据:1)d(x,x)=0 2)if x!=y, d(x,y)!=0 3)d(x,y)+d(x,z)>=d(x,z) 距离[1,2] ■Kad路由表--K桶 K桶[0] null 0=<i<160,每个节点保存K个离本节点距离为2^i~2^(i+1)的节点信息。 ■Kad表动态更新策略: 当受到来自其他节点的消息时,即更新Kad桶。 发送节点在K桶中,移至列表尾部。 若K桶没满,则移至尾部。 若K桶满,则对列表头节点发送Ping命令。若没回复,则删除节点。 距离[2,4] K桶[1] null K桶[2] null 距离[4,8] K桶[159] Last-recently most-recently
Kademlia的四个远程调用(RPC remote procedure call) ■PING 测试节点是否在线 ■STORE 指示一个节点储存一个<Key,Value>对用于以后的检索 ■FIND_NODE 将目标节点ID作为变量,RPC接受端返回k个它所知道的最接近目标ID的节点信息。 ■FIND_VALUE 同FIND_NODE类似,返回K个所知道的最接近目标键值的节点信息。若接收者拥有这个键的STORE RPC,则只需返回这个已储存的值。
Kademlia:定位节点 输入参数:目标节点ID 得到: 网络中离节点ID最近的K个节点 具体算法: 先从自己的K桶中找出和键值最近的k个节点。向这k个节点发送FIND_NODE请求。接受方在他们的K桶中进行查询,如果发现离目标节点更近的节点,就返回这些节点(最多k个)。消息的请求者根据受到的响应来更新结果列表,这个结果列表保存k个离目标节点最近的节点。 不断地进行上述的过程,直到本次响应得到的结果中无法更新原先的结果列表。 至此,本次查询结束,得到离目标节点最近的k个节点。
Kademlia:定位资源 与定位节点的算法相似,对于以前STORE的消息,储存节点将会有对应STORE所储存的相关资源的信息。定位资源时,如果有一个节点存有相应的资源的值 的时候,它就返回该资源,定位结束。除了该点以外,定位资源与定位离键最近的节点过程相似。 资源的值被储存在多个节点上。储存值的节点将定期地搜索网络中与储存值对应的键值最接近的K个节点并且将值复制在这些节点上。 对于流行的内容, 为了应对更多可能的请求,通过让那些访问值的节点把值储存在附近的一些节点上(不在K个最近节点范围内),来减少储存值的节点的负载。资源的值被储存在离键越来越远的地方,使得流行的搜索搜索可以更快找到资源的储存者。 提供文件的节点会周期性的更新网络上的信息(通过NODE_LOOKUOP和STORE消息)。当存有某个文件的节点都下线了,该文件的相关信息也从网络上消失了。
Kademlia:节点的加入和离开 当节点A要加入网络时,首先要确定一个已经存在于网络中的B。首先,A将B加入自己的K桶中。然后对自己进行一次FIND_NODE操作,并且根据受到的内容更新自己的K桶。然后对K桶进行刷新,在这同时A既更新了自己的K桶,又将自己插入到其他节点的K桶中。(将自己的到来告诉其它结点,以更新它们的状态,即为刷新) 节点的离开不需要发布任何信息。Kademlia要求每个节点必须周期性地发布自己存放<Key,value>对数据,并把这些数据缓存在自己的k个最近邻据节点上,这样存放在实效节点上的数据会很快地被更新到其他新节点上。
Kademlia特点 • 1、当Kad结点收到消息,用消息发送者的nodeID来更新相应的k-bucket,称为“捎带确认”piggy-backing,或捎带更新。 它还能有效地防止DoS攻击,攻击者无法用特定的nodeID填满其它结点的路由表,因为Kad网络只有检测到旧结点失效才会用新结点 • 2、路由主动更新:为保持路由表k-buckets的更新,如果某个路由表的所有结点在一个小时中未被查询,则从中任选一个ID对该结点做结点查询以刷新路由表
3、K个ID邻近复制:保证k个结点存储value,并且此k个结点每过一个小时就重新发布<key, value>对,以保证数据可用;同时还要求最初的发布者S结点每过24小时重新发布<key, value>,否则过期 • 4、为保持存储、查询的一致性,当任何一个结点A发现存在另一个结点B离保留在A上的键值对更近时,A会复制键值对到B,但不删除自己数据库中的键值对
Kademlia Binary Tree Subtrees of interest for a node 0011……
Kademlia Binary Tree • Every node keeps touch with at least one node from each of its subtrees. (if there is a node in that subtree.) Corresponding to each subtree, there is a k-bucket.
Kademlia Search An example of lookup: node 0011 is searching for 1110……in the network
二、SkipNet:基于跳表、提供显式局部性的P2P模型二、SkipNet:基于跳表、提供显式局部性的P2P模型 • SkipNet通过“跳表”(SkipList)数据结构提供显式局部性,体现在两个方面 • 内容局部性,即语义上可控的对象放置,能够显式地指定数据对象的放置位置或放置范围 • 路由局部性,同一个组织中结点间消息路由的路径一定位于该组织内部 • 显式局部性是SkipNet的最大亮点,但也弱化了一致性散列函数的影响,不能提供很好的负载均衡;SkipNet通过折中的办法平衡负载均衡与局部性的矛盾,称为“受限负载均衡”,即数据只在某个范围内而不是全局分布均衡
SkipNet语义局部性能缓解一些在其它系统中非常严重的问题,如“网络分割”问题:Chord, Pastry等网络一旦分割,性能会急剧下降甚至不能正常工作;SkipNet保证同一个组织中结点间消息路由的路径一定位于该组织内,因此可以在隔离的情况下正常工作 • 路由局部性对安全性的影响 • 正面:组织内通信自闭,外界难以监听;便于控制和管理组织 • 反面:一旦被非法控制,影响很大
SkipNet采用两套独立而又相关的ID:NameID(名标识)和NumericID(数值标识)SkipNet采用两套独立而又相关的ID:NameID(名标识)和NumericID(数值标识) • 结点名和对象名被直接映射到NameID,NumericID则是通过“层次化分环”过程获得,与结点名、对象内容无关 • 在折中的方法里,SkipNet将结点名或者内容标识用“!”分成两部分,前一部分直接作为NameID,后一部分的散列值作为NumericID,从而在局部性与随机性之间取得平衡
SkipNet的组织结构 • SkipList是一个有序的链接表,其中一些指针指向跳表中距离很远的结点,每个指针有它的层level,层越高指的越远 • 在一个“完全跳表”中,第h层指针指向距离2h的结点,通常每隔2i个结点才会有一个i层指针(最底层为第0层)。完全跳表支持O(logN)跳的关键码搜索 • 完全跳表过于严格,不适应网络的动态性,SkipNet采用“概率跳表”,每个结点按照概率选取自己具有哪层指针。0层必选,选择第i层 指针的概率为1/2h。仍支持O(logN)跳的关键码搜索
SkipNet 完全跳表 概率跳表
SkipNet中将跳表头尾相接成一个环,并且每个指针变为双向,因此结点路由表(R-Table)项数为2logN,其中第h层指针指向距离当前结点2^h跳的两个结点,一个沿顺时针方向,一个沿逆时针方向SkipNet中将跳表头尾相接成一个环,并且每个指针变为双向,因此结点路由表(R-Table)项数为2logN,其中第h层指针指向距离当前结点2^h跳的两个结点,一个沿顺时针方向,一个沿逆时针方向 • 图中,根环上结点之间按照结点名或其数据对象关键码(NameID)来排列
SkipNet环的拆分及A的路由表图示 M O D T A V X Z M D A T O V Z X M O D T A Z V X M D O T A Z V X Ring 100 Ring 101 Ring 110 Ring 111 Ring 000 Ring 001 Ring 010 Ring 011 L = 3 Ring 01 Ring 00 Ring 10 Ring 11 L = 2 Node A’s Routing Table Ring 1 Ring 0 L = 1 Root Ring Level: L = 0 27
图例解释 • 因每层指针隔一个结点指向下一个结点,因此,第i层指针将第(i-1)层环分成两个i层环,而i-1层环中的每个结点以1/2的概率选择加入哪个i层环,导致实际的环拆分可能不等,但这种松散的组织方式有利于插入、删除操作,也能保持O(logN)的定位跳数 • 图中每层环给出了环标识ringID,根环没有环标识,最后一层环的ringID就是NumericID,显然,NumericID的前h位决定了它在第h层的环关系;而NumericID的作用类似于散列函数,是随机的、均匀的;
就ID分布而言,根环上的结点以NameID顺序串成一个环,最高层的单结点环则以NumericID排列就ID分布而言,根环上的结点以NameID顺序串成一个环,最高层的单结点环则以NumericID排列 • 除了R-Table路由表,每个SkipNet结点还维护一个“叶集”L,与Pastry的叶集组成与功能类似,其中L/2个叶集结点是环上顺时针方向离当前结点最近的,另一半在逆时针方向上最近
SkipNet路由 • 两种方式:NameID路由,NumericID路由 • NameID路由与Chord类似,是数值临近路由(可基于skiplist),下一跳总选择路由表中不超过目的结点NameID的最高层结点,直到两个NameID最近,路由跳数通常为O(logN) • NumericID路由与Pastry类似,首先查找根环,直到发现一个结点与目的结点的NumericID匹配第一位,此时通过该结点“爬升”到它的1层环,再在1层环上查找与目的结点NumericID匹配的前两位的结点。依此类推,每次上升一层多匹配一位,直到不能匹配到更多位,又不能找到NumericID更接近的结点为止,此时到达的就是目的结点,路由跳数通常也为O(logN)
Routing By Name ID Like search in a Skip List Simple Rule: Forward the message to node that is closest to destination, without going too far. Route either clockwise/counterclockwise Terminates when messages arrives at a node whose name ID is closest to destination. Number of hops is O(log N) w.h.p.
Example: Routing from A to V M O D T A V X Z M D A T O V Z X M O D T A Z V X M D O T A Z V X Ring 100 Ring 101 Ring 110 Ring 111 Ring 000 Ring 001 Ring 010 Ring 011 L = 3 Ring 01 Ring 00 Ring 10 Ring 11 L = 2 Ring 1 Ring 0 L = 1 Root Ring Level: L = 0
Example: Routing from A to V M O D T A V X Z M D A T O V Z X M O D T A Z V X M D O T A Z V X Ring 100 Ring 101 Ring 110 Ring 111 Ring 000 Ring 001 Ring 010 Ring 011 L = 3 Ring 01 Ring 00 Ring 10 Ring 11 L = 2 Node T’s Routing Table Ring 1 Ring 0 L = 1 Root Ring Level: L = 0
Example: Routing from A to V M O D T A V X Z M D A T O V Z X M O D T A Z V X M D O T A Z V X Ring 100 Ring 101 Ring 110 Ring 111 Ring 001 Ring 010 Ring 011 Ring 000 L = 3 Ring 01 Ring 00 Ring 10 Ring 11 L = 2 Ring 1 Ring 0 L = 1 Root Ring Level: L = 0
Name ID Routing Algorithm SendMsg(nameID, msg) { if( LongestPrefix(nameID,localNode.nameID)==0 ) msg.dir = RandomDirection(); else if( nameID<localNode.nameID ) msg.dir = counterClockwise; else msg.dir = clockwise; msg.nameID = nameID; RouteByNameID(msg); } Load Balancing // Invoked at all nodes (including the source and // destination nodes) along the routing path. RouteByNameID(msg) { // Forward along the longest pointer // that is between us and msg.nameID. h = localNode.maxHeight; while (h >= 0) { nbr = localNode.RouteTable[msg.dir][h]; if (LiesBetween(localNode.nameID, nbr.nameID, msg.nameID, msg.dir)) { SendToNode(msg, nbr); return; } h = h - 1; } // h<0 implies we are the closest node. DeliverMessage(msg.msg); } Path Locality
Routing By Numeric ID Numeric id’s are random, no ring is sorted by them We can’t route top-down! Bottom-up Routing Routing begins at level 0 ring until a node is found whose numeric ID matches the destination numeric ID in the first digit. Messages forwarded from ring in level h, Rh, to a ring in level h+1, Rh+1, such that nodes in Rh+1 share h+1 digits with destination numeric ID. Terminates when message delivered, or none the nodes in Rh share h+1 digits with destination numeric ID
Example: Routing by Numeric ID Foo.c Ring 100 Ring 101 Ring 110 Ring 111 Ring 000 Ring 001 Ring 010 Ring 011 M O D L = 3 T A V Z X M D Ring 01 Ring 00 Ring 10 Ring 11 A T L = 2 O V Z X M O D Ring 1 Ring 0 T L = 1 A Z V X M D O Root Ring T A Level: L = 0 Z V X
Routing by Numeric ID The same routing tables are used for routing by nameID and numericID The number of message hops is O(log N) whp What sequential data structure does this search resemble?
Routing Algorithm // Invoked at all nodes (including the source and destination nodes) along the routing path. // Initially: msg.ringLvl = -1, msg.startNode = msg.bestNode = null & msg.finalDestination = false RouteByNumericID(msg) { if (msg.numID == localNode.numID || msg.finalDestination) { DeliverMessage(msg.msg); return; } if (localNode == msg.startNode) { // Done traversing current ring. msg.finalDestination = true; SendToNode(msg.bestNode); return; } h = CommonPrefixLen(msg.numID, localNode.numID); if (h > msg.ringLvl) { // Found a higher ring. msg.ringLvl = h; msg.startNode = msg.bestNode = localNode; } else if ( abs(localNode.numID - msg.numID) < abs(msg.bestNode.numID - msg.numID)) { // Found a better candidate for current ring. msg.bestNode = localNode; } // Forward along current ring. nbr = localNode.RouteTable[clockWise][msg.ringLvl]; SendToNode(nbr); }
SkipNet结点加入和离开 • 新结点N首先使用NumericID算法,发送以N为目的地的消息,以找到与其NumericID相应的最高层环;再使用NameID算法找到这层环上自己的邻居;然后通过该邻居,在下一层环上寻找邻居,以此类推,直到根环;完成后,N通知它所在每层环上的邻居结点将N加入路由表;新结点加入时发出的消息数为O(logN) • SkipNet结点的离开、失效算法类似Chord,根环最重要,保证定位的正确性,应及时修正;高层环用来加速定位,类似Chord的Finger Table,对其修正较松散,只要主环正确,可以保证高层环正确修复
SkipNet的背景修复 • 与Chord的Stabilization一样,SkipNet也有类“背景修复”操作,整个过程开始于根环,每个结点周期性地发送消息给根环上自己的叶集中的邻居,检测是否可达,不可达则找新的邻居替换;进而修复1层环邻居,以此类推,每次修复i+1层环都是基于前一步已经修复好的i层环。此外 • 辅助性局部修复方法:某层环内,每个结点周期性地发送送消息给该层的邻居,告诉它“我认为我是你的第n层左(右)邻居”,收到消息的邻居检查到正确则不回复,错误则回复“我的左(右)邻居是XXX,不是你”,产生一个“冲突”,启动一个协作的过程修复状态使其一致
SkipNet的局部性 • 内容局部性、路由局部性,基于NameID标识和NameID路由(具体实现中SkipNet的设计者采用了反向DNS的命名风格,如edu.ustc.wang,以使同一域中的结点拥有共同的前缀) • 受限负载均衡CLB:将数据对象名分成两个部分,第一部分是域名,保留原有DNS名的前缀,也称CLB域,第二部分是原有DNS名后缀的散列值,称CLB后缀,中间隔有“!”这样既保留了局部性,又在域内保持了负载均衡
受限负载均衡机制下数据对象的查询 • 使用NameID路由算法相应CLB域内的任意一个节点 • 然后使用NumericId路由算法在域内寻找带有CLB后缀散列值的结点,这一步要注意,当遇到ID界限(as determined by the name ID prefix boundary)时,查询必须反向走以确保没有结点被漏掉 • 两步加起来路由跳数量级仍为O(logN),但跳数比单纯的两种路由方式更多
SkipNet的拓扑一致性 • SkipNet依靠P-Table(Proximity Table, 临近表)提供物理网局部性(拓扑一致性) • P-Table类似Pastry的邻居集M,但更复杂,它将表分成多个指数级的间隔(interval),每个间隔保存一个邻近结点作为物理邻近的参照 • 当新结点N加入网络时,发送消息(P-Table join message)给物理上离自己很近的一个结点(称为种子结点,seed node),该消息为每个间隔维护一个常数项的链表,能容纳多个候选结点
种子结点收到消息后,使用自己的P-Table项填充消息中的间隔作为候选结点,然后将消息发给自己的P-Table中离N最远的结点作为下一跳,继续填充消息中的间隔,以此类推种子结点收到消息后,使用自己的P-Table项填充消息中的间隔作为候选结点,然后将消息发给自己的P-Table中离N最远的结点作为下一跳,继续填充消息中的间隔,以此类推 • 当消息中每个间隔都有至少一个候选结点后,消息被回送给新结点N以初始化N的P-Table
SkipNet增强机制 • 松散路由表:增加进制分出更多环 • 密集路由表:在R-Table每层两个方向增加额外的邻近结点指针(类似Chord的后继列表) 各有千秋 • 重复指针删除:相邻层的相邻结点指针重复,将其中一个替换成同样符合条件的邻近结点。替换后可改善25%的性能。 • SkipNet对网络分割问题的解决(请自学)
常数度P2P模型:Viceroy、Koorde和Cycloid • 2002,Viceroy • 2003,Koorde • 2004,Cycloid • 无具体应用,理论意义 • 结点的度(连接数)固定,路由、定位、自组织方式与过去的模型区别不大,维持O(logN)的定位效率同时减小系统开销
一、Viceroy:基于蝴蝶结构的常数度P2P模型 • Viceroy:北美的一种蝴蝶,最早的常数度P2P模型 • 蝴蝶拓扑(butterfly topology) • Viceroy还将其覆盖网结点组织成一个与Chord非常相似的环形 • Viceroy的结点、对象ID区间为[0,1) • 每个结点有一个逆时针方向的前驱、一个顺时针方向的后继,每个数据对象(的索引)由其后继负责
Viceroy思维 • We start at xsearching for y • Path from x to y : 1/2i + 1/2j + 1/2k + … • The problem is to find a node with the right long-range link • Chord/Tapestry: Each node has all log(n) links • Viceroy: • Each node has one long-range link out of: 1/2, 1/4, 1/8, 1/16 … • A link to 1/2k distance points to a node with a link to 1/2(k+1)distance
Viceroy的拓扑结构 • 结点x的ID∈[0,1),维护一个7项的路由表(即常数度为7): • 前两项是x在环上的前驱和后继 • 结点属于某层:l=x.level是在[1,logN]之间的随机正整数,N为结点总数 • 三、四项记录x到l+1层的两条连接 • 右下边:连接到距离x大约1/2l且最近的l+1层结点(clockwise-closest) • 左下边:连接到离x最近的l+1层结点clockwise-closest) • 第五项是上边:连接到离x最近的l-1层结点 • 后两项是与x同层且离x顺时针、逆时针方向最近的两个结点的连接,称为“同层环边”