最容易理解的Consistent Hashing讲解(一致性哈希算法使用场景及原理)
2018-02-16 17:17
330 查看
一、使用场景
考虑一个场景,有一个redis集群,那么我们如何分配不同的要缓存的数据,使之能够尽可能均匀的存储到各个redis服务器上呢?肯定有人会想到使用传统的hash + 取模 算法。服务器ID = hash(object) % N (N为服务器个数)
举个例子,如果我们有4个redis服务器,编号分别为0,1,2和3,产生的十个数据的hash值分别为1~10。列出具体的数据分布情况。
0号服务器:4、8
1号服务器:1、5、9
2号服务器:2、6、10
3号服务器:3、7、11
首先我们不管分布的是否均匀,我假设一种情况,如果多加一个节点,即4号服务器,那么这些数据是要重新分布的,重新分布的结果我们来看一下。
0号服务器:5、10
1号服务器:1、6
2号服务器:2、7
3号服务器:3、8
4号服务器:4、9
可以看到,除了1、2、3这三个数据,其他数据的缓存位置都发生了变化,这样会导致很严重的性能问题。
这时候我们的一致性哈希算法就出场了。该算法的目的是在移除/新增一个节点时,尽可能减少“缓存数据key”到服务器映射的改变。
(1)首先要构造一个环形hash值区域,一般值区域为0~2^32-1。
(2)对key的值求hash值,h1 = hash(key),将该值放入环形hash区域的某个桶中。
(3)对每个redis服务器的编号值(可以是IP,也可以是其他某个标识符)求hash值,h2 = hash(node),将该值放入环形hash区域的某个桶中。
(4)每个缓存数据都缓存在它前方(hash环顺时针方向的前方)的redis服务器中。
(图片来自网络)
这样就完美解决了之前因为新增/移除节点而导致的数据缓存位置大幅度移动的情况,因为每个节点所在的hash桶的位置都是固定不变的,而且每个数据所在的hash桶位置也是不变的。因此如果在两个节点如图中的A1和C2之间再插入一个节点X,则若是X插入的位置在key2的位置的前面(A1与key2)之间,则整个图只需要移动key2的缓存位置,让object2缓存到X就行,如果X节点的插入位置在key2 和C2之间,则不需要移动任何缓存数据。
但是这样还是有缺陷的,可能会存在hash分布不均匀的情况,那就需要虚拟节点,因为在hash环上,节点越多,分布的会更均匀。
(图片来自网络)
在图中有v1~v6若干个节点,缓存数据都会分布在这几个节点上,但这都是虚拟的,缓存数据实际存储的位置时n1~n3,这样会使得缓存分布更加均匀。
相关文章推荐
- Java 23种设计模式使用场景(含Demo讲解分析,便于理解)
- 【转载】理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- KVC,KVO的一些原理理解与使用介绍
- KVC,KVO的一些原理理解与使用介绍[续]
- 深入理解Oracle索引(6):在实践中初步认识3大索引的使用场景
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- ORM,ASP.NET中ORM学习,ASP.NET中ORM学习心得,WEB2.0中ORM实现原理,Asp.net简单ORM示例源码详细讲解,Asp.net2.0:如何使用ObjectDataSource(配合ORM )(二)
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- JS 对于回调函数的理解,和常见的使用场景应用,使用注意点
- 对Socket CAN的理解(2)——【Socket的原理及使用】
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 《Oracle物化视图实战手册》-原理讲解-应用场景-实战
- 从运行原理及使用场景看Apache和Nginx
- 你如何理解 HTML5 的 section?会在什么场景使用?为什么这些场景使用 section 而不是 div?
- IE兼容问题解决根源:深刻理解hasLayout属性,原理与使用方法
- TryParse使用 理解out参数原理
- Jetty Continuation实现原理和使用场景分析
- 理解可变参数va_list、va_start、va_arg、va_end原理及使用方法
- 关于Java的数据结构HashMap,ArrayList的使用总结及使用场景和原理分析
- 理解va_list、va_start、va_arg、va_end原理既使用方法