Cassandra的一致性哈希(Consistent Hashing)和虚拟节点(Virtual Nodes)的关系

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bluishglc/article/details/52847591

本文原文出处: http://blog.csdn.net/bluishglc/article/details/52847591 严禁任何形式的转载,否则将委托CSDN官方维护权益!

一致性哈希所要解决的问题

一般的哈希算法存在的问题是:当“模”发生变化时,所有的值都需要重新哈希,而一致性哈希算法的特别之处就是它能把这种变化带来的影响降低到最小。关于这一点不再赘述,可以参考http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html,讲的非常明白。简单地说,就是在添加和删除节点的时候,只有失效节点上的数据会受影响,需要重新哈希,所有其他的节点的数据的都不受影响。

一致性哈希和虚拟节点的关系

为了理清现两者之间的关系,让我们先分开考虑。下图是Cassandra官方文档中提供的一致性哈希和虚拟节点的对比图,上半部分是单纯使用一致性哈希的情形,下图是一致性哈希+虚拟节点的情形。

关于上半部分,首先每个节点只对应一个分区,1->A,2->B,…,然后,你可以看到,数据的副本都是连续存储的,就是说A的三份副本一定是放在结点1,2,3上,B的三份副本一定是放在结点2,3,4上,依次类推, 这样做的目的也是适应一致性哈希算法的需要,因为当某一节点失效时,比如Node 1, A区间会并入B区间,算法会引导客户去紧邻的下一个节点也就是Node 2上去读写数据,所以在一开始,我们就让Node 2来冗余Node 1的数据,就是为这个场景做准备。

再来看下半部分,让我们先忽略虚拟节点的存在,假定整个区间就被切分成了16个区间,对应16个物理节点,需要强调的是这时的区间(虚拟节点)依然是连续排列的),一致性哈希算法依然工作如初。现在,假定我们用6台高性能的物理机替换现有的16台物理机,原有的16个分区(也包括它们的副本)将分配或者映射到这6台机器上。需要特别注明的是,根据官方文档的表述,这种分配或者映射的过程是随机的,且不像单纯使用一致性哈希时那样是把副本分配到本连续的节点上的(randomly selected and non-contiguous),基于这种新情形,让我们重新分析一下数据的读写过程:如果一条数据属于虚拟节点A,则写入时会同步写入虚拟节点B和虚拟节点C(这里我们假定replia的数量是3),当虚拟节点A失效(其实是虚拟节点A对应的物理节点失效)时,系统会去下一个临近节点B去读写冗余数据,应该说到目前为止,都来还是按照一致性哈希的逻辑在进行,与未引入虚拟node之前没有任何差异,接下来不同的就是:B只是一个虚拟节点,系统需要从虚拟节点<->物理节点的映射关系中找到B对应的物理节点之后,再进行读写,这是引入虚拟节点之后的不同之处,也就是多了一步二次映射的计算过程。

那么引入虚拟节点之后到底带来了什么收益呢?总的来说,引入VNode的主要收益是在系统的拓扑结构发生变化和重建节点时可以保证整个系统的高可用性。关于一点,《Cassandra 3.x High Availability, 2nd Edition》一书有一幅插图形象地说明了问题。

下图是重建Node 2节点的示意图,Node 2存储的3份数据副本F,B,A分别从Node 1,4,3上获取,也就是说只有1,4,3节点参与了Node 2的重建,整体上看这带给1,4,3节点比较大的负载,如果5,6两个节点可以参与的话无疑会分摊一些压力。同样地,我们也可以用这个图来考虑一下Node 2失效时的情形,那就所以对B的请求会转嫁到Node 3上,这会使Node 3的负载增加一倍。

我们再来对比地看一下采用虚拟节点之后的情形:同样考虑Node 2重建的过程,它上面的8个数据分区将来自全部已存在的节点,也就是说所有节点都参与了Node 2的重建,最而最大限度地分摊了系统负载。一样的,当Node 2失效时,存放在上面的两个(或三个)分区会由另外的两个(或三个)节点接管,这和前面由单一节点接管相比也分摊了系统的负载。

小结

无论是否引入虚拟节点,一致性哈希一直工作于Canssandra上,它解决的主要问题是避免节点(模)失效时导致所有已存在的hash映射关系失效。

虚拟节点的作用在于:让物理节点host更多个分区(即多个虚拟节点),由于每一个分区都有另外多份副本放在另外多个物理节点上,这带来的实际效果是密切了各个物理节点之间的关联性,从互为主被的角度来看,就如同将每一个节点和所有其他节点连上线,形成了N*N的关联关系,每一个物理节点都可能包含所有其他节点的某一小部分数据副本,所以每个节点都有可能参与到任意节点的重建工作中去,而当某一节点失效,所有其他节点都有可能来分摊失效节点的负载。总结起来,引入虚拟节点的收益是:

  • 无需为每个节点计算、分配token
  • 添加移除节点后无需重新平衡集群负载
  • 重建死掉的节点更快
  • 允许在同一集群使用不同性能的机器

没有更多推荐了,返回首页