最近在整理redis分布式集群,首先就整理一下分布式算法原理。常见的分区规则有哈希分区和顺序分区两种,Redis采用的是哈希分区规则。
- 节点取余分区
使用特定的数据,如Redis的键或用户ID为key,节点数量为N,则:hash(key)%N,计算出哈希值,然后决定映射到哪个节点上,如节点数为4时,哈希值的结果可能为0、1、2,3. 现假设有4个redis节点,HashCode值为1~20的20个数据,那么
redis节点
HashCode
HashCode
HashCode
HashCode
HashCode
redis0
4
8
12
16
20
redis1
1
5
9
13
17
redis2
2
6
10
14
18
redis3
3
7
11
15
19
当增加一个redis节点时,如下图只有1,2,3,20这4个命中了,即4/20=20%
redis节点
HashCode
HashCode
HashCode
HashCode
redis0
5
10
15
20
redis1
1
6
11
16
redis2
2
7
12
17
redis3
3
8
13
18
redis4
4
9
14
19
优点:简单 缺点:当节点数量变化时,如扩容或收缩节点,数据节点映射关系需要重新计算,会导致数据的重新迁移。
- Consistent hashing一致性算法原理 一致性算法也叫环形hash算法。 基本思想:将对象和cache都映射到同一个hash数值空间中,并且使用相同的hash算法。
算法过程:构造长度为的2³²的整数环,根据节点名称的Hash值,将缓存服务器节点放置在这个Hash环上,然后根据需要缓存的数据的key值计算得到Hash值,然后在Hash环上顺时针查找这个key的Hash最近的服务器节点,完成key到服务器的映射查找。 keyA、keyB、keyC为三个节点,对象为key1,key2,key3,key4:
可以分析一下,当移除一个节点时,影响的是该节点到逆时针到达下一个节点的这部分,如移除keyB,keyB到KeyA的值会重新指向keyC;添加节点时,影响的是添加的节点逆时针到达下一个节点的一部分,不会对其它节点造成影响。_一致性算法,明显的抑制对象的键的重新分布。_ 理想状态下,3个节点是均匀分布在环上的,可是实际一般不会均匀分布,会出现hash倾斜,如下图,A B C三个节点挨的比较紧密:
缺点: 加减节点会造成哈希环中部分数据无法命中,需要手动处理或者忽略这部分数据,因此一致性哈希常用于缓存场景中。 节点比较少时,节点变化将大范围影响哈希环中数据映射,因此不适合少量节点的分布式场景。 普通的一致性哈希分区在增减节点时,需要增加一倍或减去一般节点才能保证数据和负载的均衡。
虚拟槽分区 如下图,每个节点增加一个虚拟节点,这样对象1、3指向节点A,4、5指向节点B,2、6指向节点C,明显抑制了hash一致性分布不均匀的现象。
使用分散度良好的哈希函数把所有数据映射到一个固定范围的整数集合中,整数定义为槽。这个范围一般远大于节点数,槽是集群内数据管理和迁移的基本单位。采用大范围槽的主要目的是为了方便数据拆分和集群扩展。 命中率计算公式: (1-n/(n+m))*100% n是服务器台数 m是新增服务器台数,新增服务器台数越多命中率越大,所有增加虚拟节点命中率也会增加。
增加虚拟节点,每个实际节点设置100~500虚拟节点,可以抑制hash一致性分布不均匀的现象。