一致性哈希的核心是增量迁移。普通取模,节点数一变,所有 数据都要重新分布。一致性哈希用哈希环,节点变化只影响格 邻区间,数据迁移量可控。举个例子,原来3个节点,现在加 到4个节点,只有1/3的数据需要迁移。
那一致性哈希环怎么构建?节点怎么分布?
哈希环本质是把节点和Key都映射到一个环形空间。节点! 的哈希值是100,节点B是300,节点C是600,环从0到 99。那哈希值150的Key,会落在A和B之间,由A负责。 具体实现上,有两种方式
第一种是排序后二分查找,把所有节点哈希值排序,查找 第一个大千等于Key哈希值的节点。 第二种是TreMapceilingkey,0(logN)时间复朵度。 我之前用TreeMap实现过,代码很简单。
虚拟节点是解决什么问题的?
解决数据倾斜。如果3个节点的哈希值分别是100、400、800,环上100到400的区间有300个位置,400 到800只有400个,800到100要跨环有300个--数 据分布不均匀。
虚拟节点的解法是:每个物理节点映射100个虚拟节点 ,比如节点A有A-1、A-2到A-100,都在环上均匀分布。这样实际数据会均匀散列到虚拟节点上,再映射回物 理节点。
总结:一致性哈希的本质:节点和数据映射到环形空间,数据找最近节点。
核心:节点变化只影响相邻区间数据,其他数据完全不受影响。
哈希环的java实现
用TreeMap一行代码搞定--把每一个节点的哈希值作为Key存进TreeMap,查询时,用ceilingEntry方法找大于等于Key哈希值的最小节点,如果找不到就返回环起点(firstEntry),这就是顺时针找最近节点的逻辑。
换句话说,哈希环的核心就是“找一个就近的节点”,treeMap帮你干了这事。
虚拟节点解决数据倾斜
物理节点只有3个,哈希值分布在环上可能很近,导致数据分布不均匀。
虚拟节点的解法:每个物理节点生成100个虚拟节点(比如“nodeA-v0”到“nodeA-v99”),哈希值分布在环上。查询时从TreeMap找到虚拟节点,再映射回物理节点。100个虚拟节点能让数据分布的方差缩小到原来的1/100.
三个常见的应用场景:
场景一:Redis集群分片。Redis Cluster用的是槽(16384个),本质上是一致性哈希的离散分布版本。
场景二:Kafka分区分配。新消费者加入消费者组时,用一致性哈希分配分区,最小数据迁移。
场景三:CDN就近访问。用户请求映射到最近的CDN节点,减少延迟。
最后总结:一致性哈希不是什么高深理论,就是一个“环”加一个“找最近的节点”。
