61
22
6
6
70
4
5
1
2
3
Successor(6)=0Successor(1)=1
Successor(2)=3
图1Chord环结构
1引言
在规模庞大的对等网络结构中,如何快速准确地到目标
资源是目前对等网络研究中的热点问题。目前在这个方面的研究中,基于DHT的分布式查算法具有扩展性好、效率高和自适应强等特点,其中有代表性的算法有:Chord [1,12]
,Pastry[2]
,CAN[3]
,
Tapestry[4],Symphony[15],Kelips[16],Skipnet[17],Structuredsuperpeers[18]
等。Chord作为典型的DHT查算法具有结构简单、查速度机器码注册码
快和负载平衡等特点。在Chord的基础之上,MIT相继进行了
One-Hop
[5,6]
,Koorde[7]
和EpiChord
[8,9]
外置电源等跟进式的研究,这些算法
在速度和稳定性上有了更大的提高。本文在介绍Chord结构的基础之上,对最新的One-Hop和EpiChord进行介绍,分析算法的性能。
2Chord
2.1Chord的构造
Chord是基于相容散列(ConsistentHashing)[10]的一种资源
定位及查算法。与传统的散列相比,相容散列具有更好的稳定性和负载平衡。相容散列使用Hash函数,如SHA-1[11],作用于网络中每个节点的IP,从而得到每个节点的标识;同样,使用SHA-1作用于网络资源的“关键字”,从而得到每个网络资源的标识id。 相容散列按如下规则将资源指定给节点:网络节点标识以
2m为模构成环(m为资源和节点标识的位数,即满足2m-1≤节
点数量≤2m)。资源k被指定到环中等于k的节点或者紧跟着
k的节点,这个节点被称为k的Successor节点,可以表示为
Successor(k)。如果节点被表示为一个从0到2m-1的环,那么Successor(k)就是在环上从k出发顺时针方向第一个遇到的节点。如图1,节点0、1、3;关键字1、2、6在节点环上的存储情况。
相容散列使节点加入和离开只会引起网络一小部分的变化。当一个节点n加入时,一些先前指定到n的Successor上的资源,现在要指定到n;当n节点离开环,那么原来存储在n中的资源将自动转存于n的Successor节点上。
2.2Chord查算法
2.2.1
简单查
Chord中的每个节点仅存储其Successor节点的地址,查
过程沿着Successor进行。算法如下:
n.find_successor(id)if(id∈(n,successor))
returnsuccessor;else
对等网中Chord资源查算法研究
张
震
王晓明
(暨南大学计算机科学系,广州510632)
E-mail:zhang2003174@yahoo.com.cn
摘
要
在大规模的对等网络结构中,如何快速准确地确定资源的位置是一个比较突出的问题,基于DHT(Distributed
HashTable)资源定位及查算法是目前比较流行的算法之一,文章介绍了其中具有代表性的Chord算法以及基于Chord
的两种改进算法,对其进行了分析比较。关键词
对等网查算法
ChordOne-HopEpiChord
文章编号1002-8331-(2006)11-0147-06
文献标识码A
中图分类号TP309
ResearchonChordLookupAlgorithmforPeer-to-PeerNetwork
ZhangZhenWangXiaoming
(DepartmentofComputerScience,JinanUniversity,Guangzhou510632)
Abstract:AnimportantproblemthatconfrontsPeer-to-PeerNetworkistheefficientlocationofthenodethatstoresadesireddataitem.TheresearchfocusesontheDHT(DistributedHashTable),becauseDHTlookupalgorithmsofferascalableandefficientroutingandobjectlocationplatformforPeer-to-Peernetworks.WeintroduceChord,themostrepresenta
tiveDHTlookupalgorithm.ThenweintroducetwoupdatealgorithmsofChord.Keywords:Peer-to-PeerLookupalgorithm,Chord,One-Hop,EpiChord
基金项目:暨南大学自然科学基金资助项目
作者简介:张震(1975-),男,助教,主要研究方向:网络体系结构,路由算法,网络安全。王晓明(1960-),女,博士,教授,主要研究方向:网络体系结
5456
5148
42
38
32
21
14
1
8
查54
图2简单查过程
FingerTableFinger[0]14Finger[1]14
Finger[2]14Finger[3]21Finger[4]32Finger[5]42FingerTableFinger[0]48Finger[1]48Finger[2]48Finger[3]51Finger[4]
1
Finger[5]14
54
56
5148
42
38
32
21
14
1
8
图4升级查过程
returnsuccessor.find_successor(id);其查复杂度为O(n)。
图2中描述了节点8查id54的过程:
2.2.2升级查
每个节点n要维护一个包含m个表项的finger表,m为资
源和节点标识的位数,第i个表项包含的是在节点环中存放(n+2i-1)mod2m的点s,即s=Successor((n+2i-1)mod2m),1≤i≤
m。称s是n的第i个finger,表示为n.finger[i]。
定义1
finger[i]:环中存储(n+2i-1)mod2m的点。
Successor:节点在环上的下一个节点,即n.finger[1]。Predecessor:节点在环上的前一个节点。
图1中节点0,1,3的FingerTable,如图3所示。
特征
(1)每个节点保存部分其他点的信息,并且保存在环路上临近节点的信息量比远端节点的信息量大。
(2)每个节点只包含O(logN)个表项,造成一个节点通常没有足够的信息来直接到任何一个关键字。
算法如下:
n.find_successor(id)if(id∈(n,successor])returnsuccessor;else
n′=closest.preceding_node(id);returnn′.find_successor(id);n.closest_preceding_node(id)
fori=mdownto1if(finger[i]∈(n,id])returnfinger[I];returnn;
如果id在节点n与其Successor之间,则id一定存储在n的Successor中;否则执行n.closest_preceding_node过程查finger表,到与id最近的节点n′
;n′再次调用find_successor。这是因为越接近id就会了解到更多的关于id的信息,可以尽快地定位id。图4显示对于图2中的查任务使用升级查算法以后的查过程。
节点8在其finger表中到最接近54的节点42,将请求发送给节点42,同样42在其finger表中到节点51,节点42将请求发送给51,节点51发现目标54位于它与其Successor(即56)之间,查成功,发送请求给节点56,节点56响应请求。查是一个递归的过程。
定理在n个节点的网络中,升级算法的查复杂度为
O(logn)。
证明:假设节点n要查存储资源k的节点,假定p是所求节点紧前面的一个节点,如果n≠p,则调用closest_
preceding_node(k)在n的finger中到最接近k的节点。设p
点在由i确定的区域[n+2i-1,n+2i],由于这个区域非空(包含p),
节点n会联系它的第i个fingerf,n与f的距离至少是2i-1;f和
p也在这个区域内,也就是说他们的距离至少是2i-1,由于f与p
都在[n+2i-1,n+2i]区域内,它们的距离至多为2i-1,这说明每一次节点的查过程都使得到的节点与目标节点的距离至少缩短一半。由于节点和id的分布随机,那么查节点的数量就会为O(logn)。
2.3稳定性问题
Chord节点的频繁加入、失效或离开可能造成路由错误。
如果节点n的加入是单一的,n可以通过已知点n′
进行m+1次find_successor查过程到n的Successor、Predecessor,并构
成其fingertable。由于n的加入一定会影响到某些节点的
finger,所以,随后要更新其他节点的fingertable。这个过程是
完备的,但是,在网络环境中,节点的加入是随机的,如果每有一个节点加入就要进行一次全面的更新,系统消耗大,影响查速度。为此,Chord采用定期更新的方法。
Stabilization过程:
FingerTableFinger[0]1Finger[1]3Finger[2]
0
Finger[0]3Finger[1]3Finger[2]
0
FingerTable
Finger[0]
0Finger[1]0Finger[2]
0FingerTable0
1
2
3
4
5
6
7
图3FingerTable
2
2
2
3
3
3
45
1
4
4
SliceLeaderUnitLeader
OrdinaryNode
图5One-Hop的信息流程
n.create()predecessor=nil;successor=n;n.join(n′
)predecessor=nil;
successor=n′_find_successor(n)n.stabilize()
x=successor.predecessor.if(x∈(n,successor])successor=x;successor.notify(n);
n.notify(n′
)if(predecessorisnilorn′∈(predecessor,n))
predecessor=n′n.fix_fingers()next=next+1;if(next>m)next=1;
finger[next]=find_successor(n+2next-1);n.check_predecessror()if(predecessorhasfailed)predecessor=nil;
n.create():建立一个节点。
n.join():通过已知节点n′
将n加入到环中,n只是考虑Successor的正确性,Predecessor初始为nil。
n.stabilize():节点定期执行,确认每个节点的Successor是
否正确。令x=Predecessor(Successor(n)),如果x∈(n,n.suc-
cessor),说明x是新近加入到n后面的节点,调整n的Succes-sor为x,随后通过notify()过程指定x节点的Predecessor。
fix_fingers():使每个节点的fingertable保持更新。check_predecessor():每个节点定期执行确定节点的Pre-decessor是否有效,如果失效,就置为nil,在后面的stabilize()
中,通过notify()加以更新。
Chord中,起码要保持节点Successor的正确性。这样查
至少是按着Successor逐步进行的,保证最终会到目标点。对于所有节点的fingertable尽量保持更新,提高查效率(达到
O(logn))。
3One-Hop
对Gnutella网络
[13]
的研究
[14]
表明:规模为100000个节点
的系统,平均每秒钟发生19次成员变化事件,节点变化并不是非常频繁。可见Chord的稳定过程并没有占据过多的带宽,反而是递归查过程占用大量的带宽。基于上述分析开发了
One-Hop算法,尝试扩大节点路由信息,加快查速度。
3.1One-Hop
One-Hop将Chord环分割成k个Slice(分片),每个Slice
都有一个SliceLeader。Slice再次被分为u个同样大小的分片,称为Unit,每个Unit选取Unit中间的节点作为UnitLeader。
One-Hop的信息流程如图5。
(1)节点定时发送keep-alive信息检查其Predecessor和
Successor的状况,如发现变化,将这个变化信息发送给它的SliceLeader。
(2)SliceLeader将成员节点的变化信息收集在一起,等待
tbig时间,将这些信息发送给其他的SliceLeader。SliceLeader
之间的信息交换是异步的,这样可以节约带宽。
(3)SliceLeader将成员节点的变化信息收集在一起,等待一小段时间twait,将这个信息发送给这个Slice中的所有Unit
Leader成员。
(4)每个UnitLeader将SliceLeader发送来的信息综合,加入到keep-
alive信息中,发送给其Successor和Predecessor
节点。
(5)普通节点将接收到的keep-alive信息沿着一个方向进行传播:如果从Predecessor接收到信息,那么就将信息传送给它的Successor;如果是从Successor接收到的信息,那么将信息传送给它的Predecessor。当信息传送到Unit的边界时,信息消亡。
3.2One-Hop算法分析
3.2.1
One-Hop中的时间设定
One-Hop的基本构想就是在节点中存储全部节点的路由
信息,算法效率和节点中存储信息的实时性关系密切。规定:当一个节点发现其Successor或者Predecessor发生变化后,在ttot时间后,系统中所有节点都要知道这个变化。
定义2
twait:SliceLeader把信息传送给成员UnitLeader的时间间隔;
tsmall:UnitLeader把信息传送给成员节点的时间间隔;
tbig:SliceLeader把信息传送给其他的SliceLeader的时间
间隔;
tdetect:从发生变化到SliceLeader发现变化的时间间隔。
当SliceLeader收集完成员节点的变化信息后,在twait+tsmall
后,Slice的所有成员节点会知道发生在本Slice中的所有变化。再经过tbig,SliceLeader将变化信息发送给其他k-1个
SliceLeader。再经过twait+tsmall,系统所有的节点将了解发生的所有变化。那么ttot=tdetect+twait+tsmall+tbig。
定义3
f:可接受的首次查失败比例;n:系统中节点的数量;
r:系统中成员节点变化比率。
假设节点均匀分布在环上,则失败请求比例应小于或者等于节点变化率,即:
r≤f×nttot
,可以得到:ttot≤
f×n
r3.2.2
k和u的确定
筛底使用m个字节来描述一个变化事件,v个字节是构造数据
表1节点带宽表
SliceLeader
UnitLeaderOthernodes
上游带宽
rm(u+2)+
2vk
t
big
2×r×m+3v
r×m+2v
下游带宽
rm+
2vk
t
big
路网r×m+2v
r×m+2v
id2
62
57
51
49
47
40
35
30
20
25
17
15
10
6
0
Lookup2
图6EpiChord查示例
节点
30
51
62
10
0
节点路由信息
…,62,51,10,20,…
…,57,62,0,10,…
…,57,0,6,10,…
…,62,0,6,15,…
…,57,62,6,17,…
表2节点路由表
t
0
1
2
3
4
5
6
7
操作
向10,51,62发送请求
51回复(57,62,0,10)
向0发送请求
62回复(0,6)
向6发送请求
10回复(62,0,6)
0回复(6)
6回复
等待回复
的请求
10,51,62
10,62
0,10,62
0,10
0,6,10
0,6
6
最好的
Predecessor
62
0
0
0
0
0
0
最好的
Successor
10
10
10
6
6
6
6
查成功
表3EpiChord搜索过程
包的额外消耗。考察下面四种通信:
(1)keep-alive信息:keep-alive信息构成了系统底层通信。假定keep-alive信息是每秒钟发送的,每个信息中包含r个事件信息,则keep-alive信息的大小为r×m+v;每个节点接收到这个信息以后要发送确认信息,大小为v。因此,上、下游带宽均为:r×m+2v。
(2)普通节点通知SliceLeader的信息:每个Slice中每秒
发生r
k
个变化,因此SliceLeader的下游带宽为
r×(m+v)
k
;每
个信息都要做回复,即上游带宽为r×v
k
。
(3)SliceLeader之间的交换信息:每个SliceLeader收集tbig时间内成员的变化信息,信息的大小为r
k
×tbig×m+v,SliceLeader将这个信息发送给其他k-1个SliceLeader,随后收到他们的回复信息,显然,所有的SliceLeader的上游和下游带
宽是对称的:(r×m
k
+2v
tbig
)(k-1)。
(4)SliceLeader与UnitLeader之间的信息:SliceLeader将过去twait=1s中收集到的信息构成一个批次发送,这个批次中包含r个变化信息,信息的大小为(r×m+v)×u。去除可忽略的信息,系统中每个节点的带宽使用情况见表1。
可以看出,SliceLeader上游带宽使用量很大,系统需要通过调整k、u减少这个带宽。k和u决定了每个unit的大小,由于UnitLeader在unit的中间并且keep-alive信息是每秒钟发
送的,那么tsmall的大小就是unit大小的一半,即:tsmall=
n
2ku
。给
定了twait和tdetect以后,通过tsmall和ttot能够确定tbig的大小。为了分析简单,假定tdetect=3s,twait=1s;给定n,r和f值以后,分析k和u。将上面的假定带入到SliceLeader的上游带宽公式中,经过证明我们得到如下结论:当
k=r×m×n
4v
!
u=4vn
r×m×(ttot-twait-tdetect)2
!
翻罐笼时,SliceLeader的上游带宽最小。
由n=2ku×tsmall,得到tsmall=tbig。
4EpiChord
大多数的DHTs查算法是通过节点主动发送探测信息来不断更新保存在本地的路由信息;EpiChord引入了反应式路由维护策略:节点在查询的时候,通过其他节点的回复信息更新本地的路由信息。这种反应式策略不能保持路由的及时更新,为此,在EpiChord中采用并行查,通过加快查速度缓解这个问题。
4.1并行查算法
节点根据本地路由信息产生p个并行查询:其中1个发给和目标值最接近的后继节点,其余的发给和目标值最近的p-1个前驱节点。请求发送是异步的,目的是节约带宽。系统采用两种方法来发现新的路由信息:
(1)当一个节点第一次加入网络,它从临近的节点(Suc-cessor、Predecessor)中获得完整的路由信息的拷贝。
(2)节点通过查询的回复信息更新本地路由。
当节点n收到查询后做出如下三种回复:
①n包含目标,则返回目标,查成功;
②如果n是目标的前驱节点,n会从本地路由信息中提供其Successor信息以及通往目标的l个最好的下一跳节点信息;
③如果n是目标的后继节点,n会从本地路由信息中提供其Predecessor信息以及通往目标的l个最好的下一跳节点信息。
l个最好的下一跳:根据本地路由信息到紧跟在目标后面的一个节点以及l-1个目标最近的前驱节点。
可以得出这样的结论,当p增大时,系统性能提高,查速度更快、延时更小。实验也验证了这一点[8],但当p≥3时,随着p增大,系统性能提高就不是很明显了,为了节约节点资源,设定p=3。
图6中点30寻id2,表2为每个节点已有的路由信息,表3为EpiChord查过程,其中p=3,l=3。控制器设计
EpiChord采用反复式查方式而不是递归式的,即:节点并行发送p个请求,等待请求回复信息;这个查询将更加接近目标。EpiChord的反复式查询方式避免了发送多余的信息:如
nq-1
nq-2
nq
nx
n1
n2
21
q
q-1
q-2
3图9EpiChord强稳定算法
n
图7EpiChord节点路由信息分片
n
m
图8
全局错误示意图
果使用p个并行的递归查,当一个查线程到目标时,其他递归查线程还会继续下去,浪费很大的带宽。
4.2反应式路由维护
反应式路由维护主要内容有三个方面:
(1)EpiChord系统中,每条路由信息都有固定的生存时间。
当节点接收到信息(无论是请求还是回复)时,如果节点的路由中没有发送点的信息,则添加发送点的路由信息,并将加入时间设定为本地时间;如果已含有发送点的信息,那么重新设置加入时间为本地时间。请求响应中的每条路由信息包含生存时间(发送点发送信息时的时间减去路由信息的加入时间),生存时间信息用于设置或者重新设置接受节点各路由信息的生存时间。路由信息在以下两种情况下被清除:它映射的节点不响应请求达到一定的数量;或者生存时间超过了指定门限t。
(2)为了保证EpiChord至少也具有Chord的效率O(logn),对EpiChord节点中的路由信息分片。每个节点路由表分割为两个对称的指数级(如2)大小的分片Slice,如图7。随着查逐渐接近目标,每个Slice中的路由信息成指数增长,这样的分片机制提供了查路径O(logn)的保证。
(3)为了保证系统效率,EpiChord规定每个Slice中必须包含一定数量的有效路由信息。如果某个分片中没有足够多的有效路由信息,那么节点将向这个分片中的中间节点发送查询信息,通过查询获取补充路由信息。
4.3稳定性算法
当有大量节点同时加入到环上同一位置时,会引起地址错误;另外,当节点未作宣布就离开会造成出现孤儿节点,即环路上的节点不知道这些节点的存在。EpiChord采用两种稳定算法:弱稳定
算法和强稳定算法。
4.3.1弱稳定算法
弱稳定算法为保持局部节点稳定的算法。节点定期检查它的Successor和Predecessor是否有效,如果发现了新的
Successor和Predecessor就作路由更新,也就是说节点只维护局
部信息的正确。
弱稳定算法无法修复全局错误,如图8所示,对于这样的错误只能通过强稳定算法修复。
4.3.2强稳定算法
强稳定算法为保持全局节点稳定的算法。强稳定算法的设计是基于一个简单的思想:回路。图8中,n节点发送一个包含本身标识的探测包,探测包沿着Successor发送,当探测包到达节点m,m通过其Successor以及探测包中n的标识发现路由错误;在m节点执行弱稳定算法修正这个错误。探测包经历整个
环路,效率低;有效的方法是将环路分段,向各段并行发送探测包,探测包沿着Successor指针传送,通过传送路径发现错误。
算法如下:
(1)节点x根据其路由信息在环路上选取q个均匀分布的节点:n1,n2,n3,…,nq,满足nx<n1<n2<n3<…<nq;
(2)x发送一个以x为目标的探测包给nq;
(3)x继续发送给ni一个以ni+1为目标的探测包,其中i=q-
1,…,1,如果nj失效了,那么就用它的Successor代替;
(4)x生成一个以n1为目标的探测包,发送给x的Successor节点。算法如图9所示。
当探测包到达标识大于或者等于目标的节点时,探测包消亡。探测包消亡时有如下两种情况出现:
(1)探测包经过的网络段不存在错误:如果探测包在它的目标节点消亡,或者在目标节点的Successor节点消亡。
(2)探测包经过的网络段存在错误:如果探测包没有在(1)中指定的节点消亡,即探测包节点越过了目标到达了另外的一个段中的节点,但这个点却不是目标节点的Successor,这说明出现全局错误,EpiChord利用这两个段交接部分的节点信息纠正错误。
如果系统的规模庞大,即n/q也比较大,这样每一段中的探测包传递非常耗时。对于这种情况,系统通过对分段进行再分段来解决,如节点y接收到探测包其目标地址为nz,那么在ny和nz节点之间再次选取q个节点,ny<n1<n2<…<nq<nz,重复上面描述的算法。可见,强稳定算法的算法复杂性为O(n2)。
5总结
Chord算法是结构简单,容易实现的一种DHT算法。节点中保存O(logn)个局部路由信息,使用递归搜索算法把这些分散的路由信息结合成一个整体,充分体现了对等网络分布式的特