Chord算法实现详细

背景

Chord算法DHT(Distributed Hash Table)的一种经典实现,以下从网上无节操盗了一段介绍性文字

Chord是最简单,最精确的环形P2P模型。“Chord”这个单词在英文中是指“弦”,在分布式系统中指“带弦环”,在P2P领域则指基于带弦环拓扑结构的分布式散列表(DHT)或者构建与其上的P2P网络。虽然MIT和UC Berkeley的研究早在2001年之前就开发了Chord及其应用系统,但有关Chord的正式论文[Stoica et al., 2001]发表在计算机通信领域著名会议ACM SIGCOMM’01 上,其他刊物和会议后来也有刊登Chord的论文的,如[Stoica
et al., 2003]。Chord是结构化的P2P领域最著名的理论模型,到2006年已经被引用超过3000次,可以说,凡是研究过P2P的人,没有不知道Chord的。

如果仅仅将Chord看成一个分布式散列表,那么它只支持结构化P2P最简单的功能:将节点和数据对象映射到覆盖网中。Chord基于安全的一致性散列函数来分配节点ID和对象ID。在一个有N个节点的网路中,每个Chord节点保存O(logN)个其他节点的信息,查询数据对象需要的覆盖网络的路由跳数也是O(logN),当节点离开或者加入网络时,为了维持网络结构,保持自适应性所需要的的消息数在O(log2N)。作为分布式的散列表,Chord具有几乎最优的路由效率,确定性的对象查询,负载均衡,高可扩展性以及良好的容错性与自适应性;但最重要的一点是:Chord简单,优美,这是它最为经典的直接原因。

Chord算法原理介绍可以先了解下,本文侧重Chord的实现,具体是构造Chord环的实现,即如何初始化和新增节点。其他对环的操作都可以类比,而且实现会更简单。

Chord的开源实现主要有两个,一个是单机版的jchord,另一个是集群形式的open chord项目。以下描述都是参考开源项目代码展开的。

单线程版

在单个线程里,Chord环类似是一个内存数据结构。Chord环的节点上可以存储数据,也可以起服务,这取决于你利用Chord来做什么。以下的实现主要侧重于新建Chord环,并可以增加节点,在增加节点的过程中,按照Chord的算法描述,怎么样影响相关节点,怎么维护Finger表内容。

首先,Chord类维护ChordNode的一个List,createNode方法根据nodeId创建一个新的ChordNode,为其生成好NodeKey,为所有的ChordNode排好序(TreeMap)。

ChordNode表示环上的节点,包含这些元素:

nodeId, ChordKey,successor, predecessor和 FingerTable。

根据nodeId在生成ChordKey,即环上的位置,然后赋予后继和前继(顺时针方向为向后)。

FingerTable维护的是m个<index, ChordNode>,m为所选hash函数的hash值位数(比如选择SHA1,m等于hash位数160,即hash环最大值为2160-1),index为key+2i,i取0, 1, … ,m-1。对于小型p2p网络来说,m的取值还是比较大的,导致节点的finger表冗余度可能会有90%以上(可能前50个值都指向N1,后100个都指向N2,最后的10个指向N5),不过这部分冗余倒不会对查找/路由性能带来什么明显影响。

FingerTable可以形象理解为,以本节点出发,将整个环切为m份,切的方式是按2的等比增长切,即1,2,4,8,…,2159,每个index值为finger表里的一条记录的key,选择该index值为起点顺时针最近的后继节点作为该finger项的value。如此的话,每个环上的节点都维护了一张全局的二分节点路由表。

然后,在建立新的Chord哈希环的时候,

1. 生成Chord,并创建若干个节点。每个节点在创建的时候,都相当于以自身为第一个节点创建了环。

2. 把创建好的节点逐个加入到某个节点的环上,加入过程只会影响某几个节点

2.1 在指定的节点N0上join新节点Nk。join过程是借助已有节点N0的finger表为新的节点Nk找到后继Nsuc =N0.findSuccessor(Nk.key),此时Nk的前继为null

2.2  确认新节点Nk与后继节点Nsuc的相互关系。需要注意的是,这个确认过程指的是待确认节点的后继是不是现在的后继,以及,后继节点的前继

会不会因待确认节点的加入而更新。

因为可能后继节点Nsuc和新节点Nk之间还有节点Nbet,则需要更新Nk的后继节点为Nbet,且后继节点Nsuc和原前继之间加入了Nk之后,

原前继的后继要改变。

2.3  确认刚刚的后继节点Nsuc的原前继节点Npre =Nsuc.getPre()的后继节点。因后继节点Nsuc的原前继节点Npre可能会因为新节点Nk的加入

而改变其后继节点。

2.2和2.3都是确认过程,只是基于的点不一样,可以体会一下,思路是一样的。

3. 刷新每个节点的finger表。该过程可以理解为,在各个节点都更新了各自的前继和后继节点之后,每个节点再把自己的finger表过一遍,更新某些后继节点。

总结来说,如上图,Nk的加入只会影响其后继节点Nx的前继节点选择,及Nx的前继节点Ny的后继节点选择,即这三个节点之间的互相指认可能会变化。

但前提是Nx和Ny必须是最接近Nk的直接前继和直接后继。如右侧图中在Ny前面,会不会有Nz更接近Nk,而应该是Nk的后继呢?答案是否定的。从原理角度看,Chord算法保证了这件事(Finger表和直接前/后继的定义有一定的特殊性)。另一方面,其实上面的图中的N0节点可能并不是处在那个位置。为了帮助理解,下面详细说明当N0在join这步为Nk第一次找后继的过程。

在第一次选择Nx的时候,是通过N0的findSuccessor(key)找的(即2.1步骤做的事)。

给定一个key位置,查找successor:

1.    判断key位置是否在本节点和本节点后继节点之间,如果是,那么就把本节点的后继节点返回。否则进入2。

2.    为该key找本节点最近的前继节点(不一定是本节点的直接后继节点),利用本节点前继节点的findSuccessor方法来找该key的后继节点,即进入递归,回到1。

要注意的是找最近的前继节点这一步,依赖的是本节点的finger表,按finger表倒序找,找到那个节点满足finger节点在目标key位置和本节点之间,就ok。

从直观上理解,finger表里的倒序第一个点距离本节点的距离最多是半个环,即2m-1,倒序第二个的距离是2m-1+2m-2。也就是说,这种倒序找是很大范围的找,以这种方式找到节点再调用findSuccessor方法找key的后继,可以脑补一下这种扫环的方式。(为帮助理解,画了一个饼)

所以N0第一次帮Nk找的后继Nx,以及Nx本身的前驱Ny,它们这四个点之间的位置关系,其实出现情况很复杂,不一定像我上面画的那样分布,我画的图甚至可能是错的,比例也完全不是那样的。如何证明Nz的不存在性,相信在了解Chord数学原理后应该可以比较好地理解。

上述描述了Chord环的生成过程和新增节点详细实现。

集群版

集群版指节点之间可能是存在于local的一个JVM内的Chord网络,也可以是存在于多个JVM之间的remote的Chord网络。

如果是Remote情况下的话,对比上述实现,节点的join步骤会增加节点之间通信环节,整体实现思路是一致的,只是集群形式要处理的内容会更丰富些。

针对通信这点,Open chord提供chord node之间的几种通信协议:Local的话是在单个JVM内;Remote的话包括rmi和socket。

Open chord还提供了在每个节点上允许存储序列化后的java对象,实际上是在Chord算法基础上对节点的一种利用,在此不展开。

把Chord放到集群环境里之后,除了对节点进行join来加入已有网络外,许多其他操作都会涉及类似的若干次通信,包括移除节点,展示节点Finger表等操作。

这些操作的实现,通过上述描述的新增节点,实现上应该很好理解。下面列举了open chord的命令行提供的对local或remote chord网络进行的操作列表:

  • CreateNode,创建多个节点
  • Insert,插入数据到local网络里
  • InsertNetwork,插入数据到remote网络里
  • CrashNodes,消灭local网络里的若干个节点
  • JoinNetwork,加入节点到remote网络里
  • LeaveNetwork,离开remote网络
  • Remove,从local网络里删除数据
  • RemoveNetwork,从remote网络里删除数据
  • Retrieve,从local网络里获取数据
  • RetrieveNetwork,从remote网络里获取数据
  • ShowEntries,展示local网络里每个node的entry
  • ShowEntriesNetwork,展示remote网络里每个node的entry
  • ShowFingerTable,展示local网络里指定node的finger table
  • ShowFingerTableNetwork,展示remote网络里指定node的finger table
  • ShowNodes,展示local网络里所有nodes
  • ShowSuccessorList,展示local网络里指定node的后继列表
  • ShutdownNodes,关闭一系列nodes
  • Wait,阻塞console一段时间

也就是说,集群环境下,对Chord的操作会以命令行的方式,操作节点、获取节点信息,从实现原理上,类似上述那样的实现步骤。

总结

下面简单总结我对Chord的理解。Chord这种DHT的实现,本质上是在一致性哈希的基础上,增加了Finger表这种快速路由信息,通过在节点上保存整个网络的部分信息,让节点的查找/路由以O(logN)的代价实现,适合大型p2p网络。所以,我理解的Chord基本就等于一致性哈希+Finger表。

Chord算法实现详细

时间: 2025-01-04 22:14:42

Chord算法实现详细的相关文章

Chord算法(原理)

Chrod算法是P2P中的四大算法之一,是有MIT(麻省理工学院)于2001年提出,其他三大算法分别是: CAN Pastry Tapestry Chord的目的是提供一种能在P2P网络快速定位资源的的算法,Cord并不关心资源是如何存储的,只是从算法层面研究资源的取得,因此Chord的API就简单到只有一个set.get. 1.Chord是什么? Chord是一个算法,也是一个协议.作为一个算法,Chord可以从数学的角度严格证明其正确性和收敛性:作为一个协议,Chord详细定义了每个环节的消

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

Chord算法

转自:http://blog.csdn.net/wangxiaoqin00007/article/details/7374833 虽然网上搜索CHord,一搜一大堆,但大多讲得不太清楚明白.今天发现一篇blog,图文并茂,逻辑清楚且易懂,特意转载收藏. P2P的一个常见问题是如何高效的定位节点,也就是说,一个节点怎样高效的知道在网络中的哪个节点包含它所寻找的数据,如下图: 对此,有三种比较典型的来解决这个问题. Napster:使用一个中心服务器接收所有的查询,服务器告知去哪下载其所需要的数据.

OpenStack_Swift源码分析——Ring的rebalance算法源代码详细分析

今天有同学去百度,带回一道面试题,和大家分享一下: 打印: n=1 1 n=2 3 3 2 4 1 1 4 5 5 n=3 7 7 7 7 6 8 3 3 2 6 8 4 1 1 6 8 4 5 5 5 8 9 9 9 9 提供一段参考程序: <pre name="code" class="cpp">// ConsoleApplication1.cpp: 主项目文件. #include "stdafx.h" #include &quo

【机器学习】算法原理详细推导与实现(五):支持向量机(下)

[机器学习]算法原理详细推导与实现(五):支持向量机(下) 上一章节介绍了支持向量机的生成和求解方式,能够根据训练集依次得出\(\omega\).\(b\)的计算方式,但是如何求解需要用到核函数,将在这一章详细推导实现. 核函数 在讲核函数之前,要对上一章节得到的结果列举出来.之前需要优化的凸函数为: \[ min_{\gamma,\omega,b}->\frac{1}{2}||\omega||^2 \] \[ y^{(i)}(\omega^Tx^{(i)}+b) \geq 1 ,i=1,2,.

【机器学习】算法原理详细推导与实现(六):k-means算法

[机器学习]算法原理详细推导与实现(六):k-means算法 之前几个章节都是介绍有监督学习,这个章节介绍无监督学习,这是一个被称为k-means的聚类算法,也叫做k均值聚类算法. 聚类算法 在讲监督学习的时候,通常会画这样一张图: 这时候需要用logistic回归或者SVM将这些数据分成正负两类,这个过程称之为监督学习,是因为对于每一个训练样本都给出了正确的类标签. 在无监督学习中,经常会研究一些不同的问题.假如给定若干个点组成的数据集合: 所有的点都没有像监督学习那样给出类标签和所谓的学习样

红黑树(一)之原理和算法的详细分析【转】

本文转载自:http://www.cnblogs.com/skywang12345/p/3245399.html R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个节点或者是黑色,或者是红色.(2)根节点是黑色.(3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果

【优化算法】Greedy Randomized Adaptive Search算法 超详细解析,附代码实现TSP问题求解

01 概述 Greedy Randomized Adaptive Search,贪婪随机自适应搜索(GRAS),是组合优化问题中的多起点元启发式算法,在算法的每次迭代中,主要由两个阶段组成:构造(construction)和局部搜索( local search). 构造(construction)阶段主要用于生成一个可行解,而后该初始可行解会被放进局部搜索进行邻域搜索,直到找到一个局部最优解为止. 02 整体框架 如上面所说,其实整一个算法的框架相对于其他算法来说还算比较简单明了,大家可以先看以

63天算法训练详细说明

目的 熟悉新近学习的编程语言各种语法糖,最大化的精简代码. 复习基本数据结构和基本算法,提高代码效率. 训练持久力. 说明 所有的算法题目来源于LeetCode,版权归官方所有. 知乎:大家是如何刷LeetCode的? Github:详尽的LeetCode题解 Github:动画演示LeetCode题目 常用数据结构和算法的动态可视化 个人训练 截至2020年2月26日时,基础题目共有1257道,按一个随笔3道题目为例,预计花费时间1257/3=419天,大概是1年3个月,当然某些时候状态好或者