参考原文:http://en.wikipedia.org/wiki/Kademlia
参考资料:http://blog.csdn.net/tsingmei/archive/2008/09/13/2924368.aspx
Kademlia
Kademlia是一种通过分布式哈希表实现的协议算法,他是由Petar和David为非集中式P2P计算机网络而设计的。Kademlia规定了网络的结构,也规定了通过节点查询进行信息交换的方式。Kademlia网络节点之间使用UDP进行通讯。参与通讯的所有节点形成一张虚拟网(或者叫做覆盖网)。这些节点通过一组数字(或称为节点ID)来进行身份标识。节点ID不仅可以用来做身份标识,还可以用来进行值定位(值通常是文件的散列或者关键词)。其实,节点ID与文件散列直接对应,它所表示的那个节点存储着哪儿能够获取文件和资源的相关信息。
当我们在网络中搜索某些值(即通常搜索存储文件散列或关键词的节点)的时候,Kademlia算法需要知道与这些值相关的键,然后分步在网络中开始搜索。每一步都会找到一些节点,这些节点的ID与键更为接近,如果有节点直接返回搜索的值或者再也无法找到与键更为接近的节点ID的时候搜素便会停止。这种搜索值的方法是非常高效的:与其他的分布式哈希表的实现类似,在一个包含n个节点的系统的值的搜索中,Kademlia仅访问O(log(n))个节点。
非集中式网络结构还有更大的优势,那就是它能够显著增强抵御拒绝服务攻击的能力。即使网络中的一整批节点遭受泛洪攻击,也不会对网络的可用性造成很大的影响,通过绕过这些漏洞(被攻击的节点)来重新编织一张网络,网络的可用性就可以得到恢复。
内容
1 系统细节
1.1 路由表
1.2 系统细节
1.3 定位节点
1.4 定位资源
1.5 加入Kademlia网络
1.6 查询加速
2 学术意义
3 在文件分享网络中的应用
1 系统细节
第一代P2P文件分享网络,像Napster,依赖于中央数据库来协调网络中的查询,第二代P2P网络,像Gnutella,使用泛洪来查询文件,它会搜索网络中的所有节点,第三代p2p网络使用分布式哈希表来查询网络中的文件,分布式哈希表在整个网络中储存资源的位置,这些协议追求的主要目标就是快速定位期望的节点。
Kademlia基于两个节点之间的距离计算,该距离是两个网络节点ID号的异或,计算的结果最终作为整形数值返回。关键字和节点ID有同样的格式和长度,因此,可以使用同样的方法计算关键字和节点ID之间的距离。节点ID一般是一个大的随机数,选择该数的时候所追求的一个目标就是它的唯一性(希望在整个网络中该节点ID是唯一的)。异或距离跟实际上的地理位置没有任何关系,只与ID相关。因此很可能来自德国和澳大利亚的节点由于选择了相似的随机ID而成为邻居。
选择异或是因为通过它计算的距离享有几何距离公式的一些特征,尤其体现在以下几点:
节点和它本身之间的异或距离是0
异或距离是对称的:即从A到B的异或距离与从B到A的异或距离是等同的
异或距离符合三角形不等式:给定三个顶点A B C,假如AC之间的异或距离最大,那么AC之间的异或距离必小于或等于AB异或距离和BC异或距离之和.
由于以上的这些属性,在实际的节点距离的度量过程中计算量将大大降低。Kademlia搜索的每一次迭代将距目标至少更近1 bit。一个基本的具有2的n次方个节点的Kademlia网络在最坏的情况下只需花n步就可找到被搜索的节点或值。
1.1 路由表
为了说明简单,本部分基于单个bit构建路由表,如需关于实际路由表的更多信息,请看“查询加速”部分。
Kademlia路由表由多个列表组成,每个列表对应节点ID的一位(例如:假如节点ID共有128位,则节点的路由表将包含128个列表),包含多个条目,条目中包含定位其他节点所必要的一些数据。列表条目中的这些数据通常是由其他节点的IP地址,端口和节点ID组成。每个列表对应于与节点相距特定范围距离的一些节点,节点的第n个列表中所找到的节点的第n位与该节点的第n位肯定不同,而前n-1位相同,这就意味着很容易使用网络中远离该节点的一半节点来填充第一个列表(第一位不同的节点最多有一半),而用网络中四分之一的节点来填充第二个列表(比第一个列表中的那些节点离该节点更近一位),依次类推。
如果ID有128个二进制位,则网络中的每个节点按照不同的异或距离把其他所有的节点分成了128类,ID的每一位对应于其中的一类。
随着网络中的节点被某节点发现,它们被逐步加入到该节点的相应的列表中,这个过程中包括向节点列表中存信息和从节点列表中取信息的操作,甚至还包括当时协助其他节点寻找相应键对应值的操作。这个过程中发现的所有节点都将被加入到节点的列表之中,因此节点对整个网络的感知是动态的,这使得网络一直保持着频繁地更新,增强了抵御错误和攻击的能力。
在Kademlia相关的文字作品中,列表也称为K桶,其中K是一个系统变量,如20,每一个K桶是一个最多包含K个条目的列表,也就是说,网络中所有节点的一个列表(对应于某一位,与该节点相距一个特定的距离)最多包含20个节点。
随着对应的bit位变低(即对应的异或距离越来越短),K桶包含的可能节点数迅速下降(这是由于K桶对应的异或距离越近,节点数越少),因此,对应于更低bit位的K桶显然包含网络中所有相关部分的节点。由于网络中节点的实际数量远远小于可能ID号的数量,所以对应那些短距离的某些K桶可能一直是空的(如果异或距离只有1,可能的数量就最大只能为1,这个异或距离为1的节点如果没有发现,则对应于异或距离为1的K桶则是空的)。
让我们看上边的那个简单网络,该网络最大可有2^3,即8个关键字和节点,目前共有7个节点加入,每个节点用一个小圈表示(在树的底部)。我们考虑那个用黑圈标注的节点6,它共有3个K桶,节点0,1和2(二进制表示为000,001和010)是第一个K桶的候选节点,节点3目前(二进制表示为011)还没有加入网络,节点4和节点5(二进制表示分别为100和101)是第二个K桶的候选节点,只有节点7(二进制表示为111)是第3个K桶的候选节点。图中,3个K桶都用灰色圈表示,假如K桶的大小(即K值)是2,那么第一个K桶只能包含3个节点中的2个。
众所周知,那些长时间在线连接的节点未来长时间在线的可能性更大,基于这种静态统计分布的规律,Kademlia选择把那些长时间在线的节点存入K桶,这一方法增长了未来某一时刻有效节点的数量,同时也提供了更为稳定的网络。
当某个K桶已满,而又发现了相应于该桶的新节点的时候,那么,就首先检查K桶中最早访问的节点,假如该节点仍然存活,那么新节点就被安排到一个附属列表中(作为一个替代缓存).只有当K桶中的某个节点停止响应的时候,替代cache才被使用。换句话说,新发现的节点只有在老的节点消失后才被使用。
1.2 协议消息
Kademlia协议共有四种消息。
PING消息—用来测试节点是否仍然在线。
STORE消息—在某个节点中存储一个键值对。
FIND_NODE消息—消息请求的接收者将返回自己桶中离请求键值最近的K个节点。
FIND_VALUE消息,与FIND_NODE一样,不过当请求的接收者存有请求者所请求的键的时候,它将返回相应键的值。
每一个RPC消息中都包含一个发起者加入的随机值,这一点确保响应消息在收到的时候能够与前面发送的请求消息匹配。