一致 Hash 算法分析
2018-01-08 02:38
211 查看
当我们在做数据库分库分表或者是分布式缓存时,不可避免的都会遇到一个问题:
如何将数据均匀的分散到各个节点中,并且尽量的在加减节点时能使受影响的数据最少。
Hash 取模
随机放置就不说了,会带来很多问题。通常最容易想到的方案就是hash 取模了。
可以将传入的 Key 按照
index = hash(key) % N这样来计算出需要存放的节点。其中 hash 函数是一个将字符串转换为正整数的哈希映射方法,N 就是节点的数量。
这样可以满足数据的均匀分配,但是这个算法的容错性和扩展性都较差。
比如增加或删除了一个节点时,所有的 Key 都需要重新计算,显然这样成本较高,为此需要一个算法满足分布均匀同时也要有良好的容错性和拓展性。
一致 Hash 算法
一致 Hash 算法是将所有的哈希值构成了一个环,其范围在0 ~ 2^32-1。如下图:
之后将各个节点散列到这个环上,可以用节点的 IP、hostname 这样的唯一性字段作为 Key 进行
hash(key),散列之后如下:
之后需要将数据定位到对应的节点上,使用同样的
hash 函数将 Key 也映射到这个环上。
这样按照顺时针方向就可以把 k1 定位到
N1节点,k2 定位到
N3节点,k3 定位到
N2节点。
容错性
这时假设 N1 宕机了:依然根据顺时针方向,k2 和 k3 保持不变,只有 k1 被重新映射到了 N3。这样就很好的保证了容错性,当一个节点宕机时只会影响到少少部分的数据。
拓展性
当新增一个节点时:在 N2 和 N3 之间新增了一个节点 N4 ,这时会发现受印象的数据只有 k3,其余数据也是保持不变,所以这样也很好的保证了拓展性。
虚拟节点
到目前为止该算法依然也有点问题:当节点较少时会出现数据分布不均匀的情况:
这样会导致大部分数据都在 N1 节点,只有少量的数据在 N2 节点。
为了解决这个问题,一致哈希算法引入了虚拟节点。将每一个节点都进行多次 hash,生成多个节点放置在环上称为虚拟节点:
计算时可以在 IP 后加上编号来生成哈希值。
这样只需要在原有的基础上多一步由虚拟节点映射到实际节点的步骤即可让少量节点也能满足均匀性。
号外
最近在总结一些 Java 相关的知识点,感兴趣的朋友可以一起维护。地址: https://github.com/crossoverJie/Java-Interview
相关文章推荐
- 一致 Hash 算法分析
- HASH 一致算法
- 常用 Hash 算法冲突解决方法分析
- 常用 Hash 算法冲突解决方法分析
- 数值分析多种算法C语言代码-推荐
- 线性判别分析(Linear Discriminant Analysis, LDA)算法分析
- Linux路由表的结构与算法分析
- 矩形和圆的相交检测 算法分析与实现
- 算法分析与复杂性理论 第三题 Til the Cows Come Home
- 研究生课程 算法分析-分治法
- 算法题——Longest Substring Without Repeating Characters(C++)hash思想
- 图像分析------连通组件标记算法
- nginx 基本hash的初始化 源码分析
- Hash 算法
- 【数据结构与算法学习笔记】PART1:算法分析(计算,计算模型,大O记号,算法分析,迭代与递归,动态控制)
- 三种强大的物体识别算法——SIFT/SURF、haar特征、广义hough变换的特性对比分析
- 三个博弈论算法分析
- 南邮算法分析与设计实验3 回溯法
- 《算法学习与数据结构》part2 算法分析与数据结构之串
- OpenCV学习笔记(28)KAZE 算法原理与源码分析(二)非线性尺度空间构建