一.BiTtorrent的DHT实现 — Kademlia 协议
在kad网络中的,每个节点都有自己的 id 值(从160bit空间中随机选取)。并规定节点间的距离是节点id值的异货值。
每个节点都有一个路由表。这个路由变实际上是个二叉树,二叉树中的叶子节点存放的是具有相同最大前缀的节点 id。
每个叶子节点我们叫做 k桶,这个 k桶里有 k个其他节点的信息(IP address,UDP port,Node ID)。
在BitTorrent的实现中,取值为k=8。当y节点收到一个 RPC消息时,用发送者的 ip来更新我们的 K 桶。
具体步骤如下:
1.在我们的路由表中找到具有最大前缀的 k 桶。
2.如果y已经在k桶中,我们需要把它移到尾部。
3.如果y不在k桶中,且k同没有满,直接将y放在k桶尾部。
4.如果 k桶满了,则取首部的记录项z,发送 ping请求,如果没有回应,则删除 z,并把 y放在尾部,
如果有回应则把 y删除。
当K 桶满的时候我们可以进行分桶,把以前的 k桶中的信息分给子 k桶。当我们要查询距离某个id最近的id时,
我们最多执行[logN](二叉树的深度减去1),[]为向下取证,N 为节点数量。
通过这种方式,能够大大提高查找速度。假如节点 x 要找节点 id为 t的节点,kad 按照如下步骤进行路由查找:
1.在路由表中找到和 t最大前缀匹配的桶,并对桶中的节点发送 find_node 操作。
2.从x的第[㏒d]个K桶中取出α个节点的信息(“[”“]”是取整符号),同时进行FIND_NODE操作。
如果这个K桶中的信息少于α个,则从附近多个桶中选择距离最接近d的总共α个节点。
3.对接受到查询操作的每个节点,如果发现自己就是t,则回答自己是最接近t的;
否则测量自己和t的距离,并从自己对应的K桶中选择α个节点的信息给x。
4.X对新接受到的每个节点都再次执行FIND_NODE操作,此过程不断重复执行,
直到每一个分支都有节点响应自己是最接近t的。
5.通过上述查找操作,x得到了k个最接近t的节点信息。
注意:这里用“最接近”这个说法,是因为ID值为t的节点不一定存在网络中,也就是说t没有分配给任何一台电脑。
这里α也是为系统优化而设立的一个参数,就像K一样。在BitTorrent实现中,取值为α=3。
当节点x要查询<key,value>对时,和查找节点的操作类似,x选择k个ID值
最接近key值的节点,执行get_peers(FIND_VALUE)操作,并对每一个返回的
新节点重复执行FIND_VALUE操作,直到某个节点返回value值。
一 旦get_peers(FIND_VALUE)操作成功执行,
则<key,value>对数据会缓存在没有返回value值的最接近的节点上。
这样下一次查询相同的 key时就会更加快速的得到结果。通过这样的方式,
热门<key,value>对数据的缓存范围就逐步扩大,使系统具有极佳的响应速度。
存放<key,value>对数据的过程为: