Chord算法

转自:http://blog.csdn.net/wangxiaoqin00007/article/details/7374833

虽然网上搜索CHord,一搜一大堆,但大多讲得不太清楚明白。今天发现一篇blog,图文并茂,逻辑清楚且易懂,特意转载收藏。

 

P2P的一个常见问题是如何高效的定位节点,也就是说,一个节点怎样高效的知道在网络中的哪个节点包含它所寻找的数据,如下图:

clip_image002

对此,有三种比较典型的来解决这个问题。

Napster:使用一个中心服务器接收所有的查询,服务器告知去哪下载其所需要的数据。存在的问题是中心服务器单点失效导致整个网络瘫痪。

clip_image004

Gnutella:使用消息洪泛(message flooding)来定位数据。一个消息被发到系统内每一个节点,直到找到其需要的数据为止。当然,使用生存时间(TTL)来限制网络内转发消息的数量。存在的问题是消息数与节点数成线性关系,导致网络负载较重。

clip_image006

SN型:现在大多数采用所谓超级节点(Super Node),SN保存网络中节点的索引信息,这一点和中心服务器类型一样,但是网内有多个SN,其索引信息会在这些SN中进行传播,所以整个系统的崩溃几率就会小很多。尽管如此,网络还是有崩溃的可能。

现在的研究结果中,Chord、Pastry、CAN和Tapestry等常用于构建结构化P2P的分布式哈希表系统(Distributed Hash Table,DHT)。

DHT的主要思想是:首先,每条文件索引被表示成一个(K, V)对,K称为关键字,可以是文件名(或文件的其他描述信息)的哈希值,V是实际存储文件的节点的IP地址(或节点的其他描述信息)。所有的文件索引条目(即所有的(K, V)对)组成一张大的文件索引哈希表,只要输入目标文件的K值,就可以从这张表中查出所有存储该文件的节点地址。然后,再将上面的大文件哈希表分割成很多局部小块,按照特定的规则把这些小块的局部哈希表分布到系统中的所有参与节点上,使得每个节点负责维护其中的一块。这样,节点查询文件时,只要把查询报文路由到相应的节点即可(该节点维护的哈希表分块中含有要查找的(K,V)对)。

这里介绍的Chord算法就是解决网络内节点定位问题的一种P2P协议。它通过多个节点跳转找到我们所查找的资源:

clip_image008

我们先看看它是如何进行的,随后再总结其特点和操作特征,以及一些实现。

1.Chord里面的基本要素

节点ID:NID(node identifier),表示一个物理机器,m位的一个数字(m要足够大以保证不同节点的NID相同的几率小的可以忽略不计),由节点机器的IP地址通过哈希操作得到。

资源ID;KID(key identifiers),原为键ID,其实际表示一个资源(因为Key与一个资源value哈希绑定),故在本文中统称资源ID(这样比较直观),m位的一个数字(m要足够大以保证不同资源的KID相同的几率小的可以忽略不计),由Key通过哈希操作得到。

常哈希函数:较之一般哈希函数,节点的加入和离开对整个系统影响最小,另外还有一些优势在此不赘述。在Chord中使用SHA-1来进行常哈希计算。

Chord环:Chord Ring,NID和KID被分配到一个大小为2^m的环上,用于资源分配(给某一个节点)和节点分布,以及资源定位(注:在这个环上的ID为0--2^m-1)。首先我们说资源分配,资源被分配到NID>=KID的节点上,这个节点成为k的后继节点,是环上从k起顺时针方向的第一个节点,记为successor(k)。而节点分布则顺时针将节点N由大到小放在这个环上。例如下边这幅图:

clip_image010

这是一个m=6的环,其中有10个节点,5个资源,K10的后继节点为N14,也就是说K10被分配给了N14。

2.Chord资源定位(Key Location)

资源定位是Chord协议的核心功能,为了便于理解,我们先介绍一个简单的资源定位方法,然后再介绍这个可伸缩的资源定位方法。

简单方法:

考虑如下场景:节点n寻找KID为id的资源,此时节点n首先问询是否在下一个节点上(find_successor),这要看资源k的KID是否在该节点NID和下一个节点的NID之间,若在则说明资源k被分配给了下一个节点,若不在则在下一个节点上发起同样的查询,问询下下一个点是否有该资源。如此迭代下去,用伪代码定义这个操作:

n.find_successor(id) 
   if (id є (n; successor]) 
       return successor; 
   else 
       // 将查询沿着环进行下去 
     return successor.find_successor(id);

例如下图:

clip_image012

节点N8寻找K54这个资源,N8.find_successor(K54)发现下一个节点N14不合符54є (8; 14],于是N14发起同样的搜索,然后一跳一跳后直到节点N56满足54є (51; 56],于是得知资源K54在N56这个节点上。

在一个有N个节点的环上,这样的查找方法显然在最坏的时候要查找N次才能得到所需资源的位置,查找次数与节点个数成线性关系。显然,这样的效率不给力,所以Chord使用了可伸缩资源定位的方式来提高效率。

可伸缩方法:

在每个节点N上都维护了最多有m项(m为ID的位数)的路由表(称为finger table),用来定位资源。这个表的第i项是该节点的后继节位置,至少包含到2^(i-1)后的位置。还是延续上边的例子:

clip_image014

节点N8的路由表中,左边那一栏包含了N8+1到N8+32(2^5-1)的位置,右边那一栏每个位置对应的实际存在的节点。比如N8+1-N14,表示在N8后的第一个位置上的资源由N14来负责。这样记录有以下优势:

每个节点只包含全网中一小部分节点的信息。

每个节点对于临近节点负责的位置知道的更多,比如N8节点对于N14负责的位置知道3处,而对N21负责的位置只知道1处。

路由表通常不包含直接找到后继节点的信息,往往需要询问其他节点来完成。

当在某个节点上查找资源时,首先判断其后继节点是不是就持有该资源,若没有则直接从该节点的路由表从最远处开始查找,看哪一项离持有资源的节点最近(发现后跳转),若没有则说明本节点自身就有要寻找的资源。如此迭代下去。

例如:节点N8寻找K54这个资源

clip_image016

首先,在N8上查找后继节点为N14,发现K54并不符合54є (8; 14]的要求,那么直接在N8的路由表上查找符合这个要求的表项(由远及近查找),此时N8的路由表为:

clip_image018

我们发现路由表中最远的一项N8+32--N42满足42є (8; 54],则说明N42这个点离持有K54这个资源的节点最近(因为N42在该路由表中离N8这个节点最远),那么此时跳到N42这个节点上继续查找。N42的后继节点为N48,不符合54є (42; 48]的要求,说明N48不持有资源54,此时,开始在N42的路由表上查找:

N42节点的路由表为:

clip_image020

我们由远及近开始查找,发现N42+8--N51满足51є (42; 54],则说明N51这个点离持有K54这个资源的节点最近,那么此时跳到N51这个节点上继续查找。N51节点的后继节点为N56,符合54є (51; 56],此时定位完成,N56持有资源节点K54。

用伪代码表示:

// 查询节点n后继节点。 
n.find_successor(id) 
if (id є (n; successor]) 
return successor; 
else n0 = closest_preceding_node(id); 
return n0.find successor(id); 
// search the local table for the highest 
// predecessor of id 
n.closest_preceding_node(id)  
for i = m downto 1 
if (finger[i] є (n; id)) 
return finger[i]; 
return n;

经证明,最多经过O(log N)次查找就能找到一个资源。

3.Chord的节点加入

Chord通过在每个节点的后台周期性的进行stabilization询问后继节点的前序节点是不是自己来更新后继节点以及路由表中的项。

有三个操作: 
join(n0) :n加入一个Chord环,已知其中有一个节点n0.

Stabilize(): n查询其后继节点的前序节点P来决定P是否应该是n的后续节点,也就是说当p不是n本身时,说明p是新加入的,此时将n的后继节点设置为p。

Notify(n0): n0通知n它的存在,若此时n没有前序节点或,n0比n现有的前序节点更加靠近n,则n将其设置为前序节点。

Fix_fingers(): 修改路由表。

具体的,例如:

这是原先的结构:

clip_image022

现在N26节点要加入系统,首先它指向其后继N32,然后通知N32,N32接到通知后将N26标记为它的前序节点(predecessor)。如下图:

clip_image024

然后N26修改路由表,如下图:

clip_image026

下一次N21运行stabilize()询问其后继节点N32的前序节点是不是还是自己,此时发现N32的前序节点已经是N26:

clip_image028

于是N21就将后继节点修改为N26,并通知N26自己已经将其设置为后继节点,N26接到通知后将N21设置为自己的前序节点。

这个加入操作会带来两方面的影响:

1)正确性方面:当一个节点加入系统,而一个查找发生在stabilization结束前,那么此时系统会有三个状态:

A.所有后继指针和路由表项都正确时:对正确性没有影响。

B.后继指针正确但表项不正确:查找结果正确,但速度稍慢(在目标节点和目标节点的后继处加入非常多个节点时)。如下图:

clip_image030clip_image031

C.后继指针和路由表项都不正确:此时查找失败,Chord上层的软件会发现数据查找失败,在一段时间后会进行重试。

总结一下:节点加入对数据查找没有影响。

2)效率方面:当stabilization完成时,对查找效率的影响不会超过O(log N) 的时间。当stabilization未完成时,在目标节点和目标节点的后继处加入非常多个节点时才会有性能影响。可以证明,只要路由表调整速度快于网络节点数量加倍的速度,性能就不受影响。

4.Chord节点失败的处理

我们可以看出,Chord依赖后继指针的正确性以保证整个网络的正确性。但如图,若N14, N21, N32同时失效,那么N8是不会知道N38是它新的后继节点。为了防止这样的情况,每个节点都包含一个大小为r的后继节点列表,一个后续节点失效了就依次尝试列表中的其他后继节点。可以证明,在失效几率为1/2的网络中,寻找后继的时间为O(log N) 。

5.Chord的特征和应用

特征:去中心化,高可用度,高伸缩性,负载平衡,命名灵活。

应用:全球文件系统、命名服务、数据库请求处理、互联网级别的数据结构、通信服务、事件通知、文件共享。

参考文献:

Chord项目网址:http://pdos.csail.mit.edu/chord/

http://net.chinaunix.net/8/2008/07/28/1231438.shtml

转载于:https://www.cnblogs.com/z-sm/p/5058176.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARP、Tracert、Route 与 NBTStat命令详解

ARP   ARP是一个重要的TCP/IP协议,并且用于确定对应IP地址的网卡物理地址。实用arp命令,我们能够查看本地计算机或另一台计算机的ARP高速缓存中的当前内容。此外,使用arp命令,也可以用人工方式输入静态的网卡物理/IP地址对&…

地籍宗地出图(一)

在ArcGIS中,我们经常需要标注;在地籍处理中,需要承包地出图。具体的出没有可参考的标准。通常软件中的做法有: 第一种,以村组为背景,将某户的承包地选择出来,并标黑。这样的结果,领导…

USACO 3.3.2 Shopping Offers解题报告

写在前面:因为之前没写的C的USACO Training的解题报告太多……所以就不写了,要是想要代码可以联系我:xiedong_1993foxmail.com 这题就是传说中的五维背包,其实写起来难度不大。但是我写的时候可以说是遇到了重重困难。因为我对C的…

LeetCode—238. 除自身以外数组的乘积

238. 除自身以外数组的乘积 题目描述: 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。…

黑马程序员_java基础笔记(15)...银行业务调度系统_编码思路及代码

—————————— ASP.NetAndroidIOS开发、.Net培训、期待与您交流!—————————— 1,面试题目:银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6个业务窗口,1 — 4号窗口…

一次非常有意思的sql优化经历

原文:一次非常有意思的sql优化经历场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course(c_id int PRIMARY KEY,name varchar(10))数据100条 学生表: create table Student(id int PRIMARY KEY,name varchar(10))数据70000条 学生成绩表SC…

Go Out Otherwise Shut Up

Shut Up For Ever! Work ,Work, Right Now! 下面盗用一下PLMM的格言给自己Add Oil。 a za a za fighting! Forge Ahead,Never Retreat! 这两句还是蛮有气势的,哈哈。 转载于:https://www.cnblogs.com/Farseer1215/archive/2005/05/07/150413.html

setCharacterEncoding和setContentType

request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值 response.setContentType("text/html;charsetgb2312")是设置页面中为中文编码 前者是设置动态文字(参数,数据库)&#xff0c…

LeetCode—239. 滑动窗口最大值(困难)

239. 滑动窗口最大值(困难) 题目描述: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值 。 …

intellij idea搭建springboot

intellij idea2018.3创建springboot项目1.new > spring initilizer > web > spring web initializer运行项目方法一:导航板上的命令台图标,输入命令:mvn springboot:run,即可看到running,浏览器测试控制器方法,这种方法暂…

logstash

http://www.cnblogs.com/fangjian0423/p/logstash-elasticsearch-build.html http://chenlinux.com/2013/07/11/howto-filter-count-in-logstash/

连连看路径求解的算法

这是路径求解的算法做一个简单的介绍,适合入门者;首先是 x to x ,这个是横向比较直连然后是 y to y ,这个是竖向比较直连然后是 1个折点算法很简单;比如7x3的000100000000000000001p1 是 3,0p2 是 6,2那么折点是000100x0000000000x001折点1是 6,0 ,折点2是 3,2注意这个值和p1,p…

LeetCode—240. 搜索二维矩阵 II

240. 搜索二维矩阵 II 题目描述: 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 考察重点:简单的二维矩阵搜索 func SearchMatr…

Android开发:什么是IBinder

上回书简单描述了进程间传递类对象的原理,这回在讲Parcel之前,先要讲一个东西:IBinder。IBinder是什么呢?首先要明白,Android的远程调用(就是跨进程调用)就是通过IBinder实现的,下面…

Debug调试

先设置断点,然后Debug调试 step into:进入子函数step over:越过子函数,但子函数会执行step return:跳出子函数转载于:https://www.cnblogs.com/android-for-dh/p/4482519.html

python matplotlib绘图大全(散点图、柱状图、饼图、极坐标图、热量图、三维图以及热图)...

//2019.7.14晚matplotlib七种常见图像输出编程大全 七种图形汇总输出如下: import numpy as np #导入数据结构nmupy模块import matplotlib.pyplot as plt #导入matplotlib图像输出模块plt.rcParams["font.sans-serif"]["SimHei"] #输出图像的标…

Java入门需掌握的30个基本概念[转]

Java的白皮书为我们提出了Java语言的11个关键特性(1)Easy:Java的语法比C的相对简单,另一个方面就是Java能使软件在很小的机器上运行,基础解释其和类库的支持的大小约为40kb,增加基本的标准库和线程支持的内存需要增加125kb。(2)分布式:Java带…

LeetCode—241. 为运算表达式设计优先级

241. 为运算表达式设计优先级 题目描述: 给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以按任意顺序 返回答案。 考察重点:(递归分治) 以符号位分割为左右…

报错:不是可以识别的内置函数名称

!!创建函数的时候不需要加dbo.,但在访问的时候,标量函数要加.dbo的 自己写完的函数,调用后报错提示:不是可以识别的内置函数名称 例:SELECT JS_ID A.ID, JSHM A.JSHM, JS_MC A.JS_MC, XY_DM …

C++右值引用与转移语义

std::forwad? C11 中定义的 T&& 的推导规则为: 右值实参为右值引用,左值实参仍然为左值引用。 参考: 右值引用与转移语义转载于:https://www.cnblogs.com/glensblog/p/11098359.html