Kademlia协议

Kademlia是一种分布式哈希表(DHT),是第三代对等网络的节点动态管理和路由协议。


构建网络拓扑

Kad网络中的每个节点都会被分配唯一的节点ID,一般是160bit的二进制数。节点之间可以计算距离,节点距离以节点ID的XOR值度量:
在这里插入图片描述
因此,节点之间的距离越近,意味着节点ID的公共前缀越长。节点之间的距离以节点的最长公共前缀(cpl)为度量,cpl越大,表示两个节点越接近,例如节点
在这里插入图片描述
基于此,一个完整的网络空间可以被表示成为一颗如下图所示的二叉树,树的叶子节点代表网络节点,下图演示了使用3bit作为节点ID位数的节点树结构。
在这里插入图片描述
下图展示了从节点 [公式] ​视角来分割上面的网络树的结果:
在这里插入图片描述

  • 节点<A, B, C, D>与M的公共前缀长度为0,将其归为一个单元
  • 节点<F, G>与M的公共前缀长度为1,将其归为单元2
  • 节点与M的公共前缀长度为2,将其归为单元3

需要说明的是:距离越长,代表节点之间越接近,千万不要弄反了。而且可以总结发现,从任一节点来看,与其距离为0的节点占据网络节点总数的1/2,距离为1的节点占据网络节点总数的1/4,


构建路由表

假如当前节点ID为​ M ,X ​距离​ M上维护的节点Y的距离为:
在这里插入图片描述
其中:
在这里插入图片描述
这个证明也很简单:
在这里插入图片描述
在这里插入图片描述
于是:上面的问题就转化为:
当 M ​收到询问距离​ X 更近的节点请求时,​ M 首先计算自身距离目标节点的距离​
在这里插入图片描述
然后再从自己维护的节点列表中选择出距离​M为的d1​的所有节点(翻译一下:即从M的路由表中找到与​有最长公共前缀的所有节点)。

Kademlia协议中,每个节点按照与自己的距离来切割节点网络树:被切割的子树称之为 Bucket。整个路由表本质上便是一个Bucket数组,Kademlia协议以​聚类网络节点:每个Bucket ​中的节点必然与本节点具有相同的最长公共前缀。

由于节点只有160bit,最长公共前缀长度最大只有160,因此,路由表中的Bucket 数量最多也就160。但是每个​ Bucket 内节点数量可能会非常多,根据之前的计算,与节点最长公共前缀长度为0的​内节点数占据网络总节点数量的1/2,​内节点数占网络总节点数的1/4…

Kademlia协议对每个Bucket 内维护的节点数设置了一个上限,称之为​K值,在一般的实现中 ​。一旦​ Bucket 内节点数超过​,便根据一定的淘汰算法进行更新。

根据该基本原理,节点构建的路由表如下图所示:
在这里插入图片描述


​分裂

在一些实现Kademlia协议实现中,每个节点初始时只有一个Bucket ​,感知到网络上有节点时,直接将远程节点信息添加至该​,直到该​内节点数量超过​,此时开始分裂 Bucket 。

所谓分裂是指创建一个新的 Bucket ​ ​,然后将原来​ Bucket ​ 内的部分节点迁移至新 Bucket ​ ​。因为原 Bucket ​ ​内的节点与本节点的距离不尽相同,所以,迁移的原则是:将与本地节点更近(即​更大)节点迁移至新建 Bucket ​ ​,迁移完成后再判断新建 Bucket ​ ​内节点数是否超过​限制,如果是,继续对该新建 Bucket ​ ​进行分裂。

上面提到迁移的过程中会将部分节点迁移至新 Bucket ​ ​,那么如何选择这些需要被迁移的节点呢?答案是根据​内节点与本节点之间的cpl决定:

初始状态时,本地只有1个​,此时分裂的目标是:

newBucket := bucket.Split(len(rt.Buckets)-1, rt.local)

在原​ Bucket ​ 中保留与本节点​为0(无任何公共前缀的节点),将其他节点迁移至新 Bucket ​ ​中。

一次分裂后,第一个 Bucket ​ ​中保留的全部是与当前节点无任何公共前缀的节点,第二个 Bucket ​ ​中保留的全部是与当前节点公共前缀大于等于1的节点。

接下来判断第二个​ Bucket ​ 是否需要再次分裂,如果分裂,再次创建新 Bucket ​ ​,然后将第二个​ Bucket ​ 中与本地节点公共前缀超过1的节点迁移至新 Bucket ​ ,与本地节点公共前缀长度为1的节点依然保留在第二个​ Bucket ​ 中。


路由算法

路由算法要解决的是如何根据目标ID找到地址或者找到与该ID最节点的目标节点地址。

在一个对等网络中,某个节点要查询其他节点的信息时,它可依赖的信息只有两个:

  • 目标节点ID;
  • 当前节点维护的路由表;

其查询的核心思想是:逐步迭代,递近查找。其基本过程如下:

在这里插入图片描述
在这里插入图片描述在这里插入图片描述


路由表更新

Kademlia网络中节点是动态变化的,节点可新接入网络,也可从网络离线。这也意味着每个节点的路由表也是一直变化着的。

新节点上线

在这里插入图片描述
流程:
在这里插入图片描述


节点离线

节点离线在Kademlia协议中无需做特殊处理,如果某个节点离线,那么其离线事件最终会反馈到网络节点的路由表中,将其从路由表中剔除即可,相比于Chord协议有了极大的简化。


用Kademlia网络存储对象

使用Kademlia网络构建大规模分布式存储系统,需要解决以下两个核心问题:

  • 建立对象与网络节点之间的映射

  • 节点动态变化时保证对象的可访问

对象与节点映射

建立对象与节点的映射,一般有两种方法:

  • 查表:维护全局<对象,节点>映射表

  • 计算:直接根据对象特征,通过数学运算得到目标节点

方法1需要维护庞大的全局映射表,且其很明显会成为系统瓶颈,且违背了对等网络的原则。

方法2必须将对象映射至节点空间,即将对象根据其唯一特征计算160bit的指纹,根据该指纹找到网络中与其指纹最接近的​个节点,这些节点将成为对象的最终存储目的地。一般这个指纹会选取对象内容的hash,便于对象去重和对象的唯一性保证。而之所以选择​个节点存储对象是为了提高对象数据的可靠性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值