一、数据分布概述
简单的来讲就是在分布式系统中数据该怎么分布,比如:存储数据的系统有3个节点,需要存储数字1~100,哪些数字存在节点1上,哪些数字存在节点2上,哪些数字存在节点3上?
1.数据分布算法的基本目标:
1.均匀性(Uniformity):不同存储节点的 负载 应该 均衡。接着上面的例子,比如:节点1放了数字1~98,节点2放了数字99~100,节点3什么都没方,这就叫不均衡。
2.稳定性(Consistency):每次一个
key
通过 数据分布算法 得到的 分布结果 应该保持 基本稳定,即使在有存储节点发生变化的情况下。
二、顺序分布
接着上面的例子,顺序分布假设每个节点最多存33个数字,那么此时需要4个节点,节点1存数字1~33,节点2存数字34~66,节点3存数字67~99,节点4存数字100.
优点:可支持顺序访问,所有的Hash分布算法都不支持顺序访问。
缺点:均匀性不够,数据分散度不够。
对比顺序分布与hash分布
分布方式 | 特点 | 典型产品 |
哈希分布 | 数据分散度高 键值分布业务无关 无法顺序访问 支持批量操作 | 一致性哈希Memcache Redis Cluster 其他缓存 |
顺序分布 | 数据分散度易倾斜 键值业务相关 可顺序访问 不支持批量操作 | BigTable HBase |
三、哈希分布
1.普通hash分布
将key做哈希后对节点数取余,一般是在客户端分片。
优点:简单、能保证稳定性、数据够分散。
缺点:稳定性太差、扩容影响太大!添加节点的时候整个数据会做很多偏移。
缺点举例,比如:3个节点扩容添加1个节点,会发生80%的数据迁移。
如果用这个中方式做数据分布,扩容的时候建议使用多倍扩容。比如3个节点,扩容的时候,再添加3个节点,这样只会发生50%的数据迁移。
不建议使用这种古老的数据分布方式。
2.一致性hash
一般在客户端分片。节点比较多的时候建议使用这种方式。
节点伸缩的时候只影响临近的节点,还是要使用多倍扩容,不然会数据倾斜。
原理:
1.将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希空间环就是下图中的黑色圆环
2.对每个服务器的唯一识别标志(IP或者主机名)求hash值,将得到的值放入第一步的圆环中对应的位置。如下图的node1 node2 node3 node4
3.对要保存的数据的key求hash值,将得到的值落入圆环中,就是下图的黄色圆圈,然后在圆环中顺时针找到最近的node(服务器的唯一识别标志(IP或者主机名)求hash值落在圆环中所在的点),该数据就存储在该node中
伸缩影响:
1.挂了一台服务器:比如上图中,node2挂了,只会影响node4节点(Node2顺时针往下走第一个节点),node2的数据会全部迁移到node4节点上。其余节点上的数据不用迁移。
2.如果多加一台服务器: 比如上图中,在node4和node3之间加入node5,node3(node5顺时针往下走第一个节点)中的数据会有一部分符合要求的被迁移到Node5上。
优点:
稳定性较好,对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
缺点:
服务节点太少时,均匀性不够,容易因为节点分部不均匀而造成数据倾斜问题。
缺点举例:比如只有2个节点,可能所有的数据就存在了一个节点上,另外一个节点是空的。
3.虚拟槽分区hash slot
这就是redis cluster(3.0中有了)使用的数据分布方式。
预设虚拟槽:每个槽映射一个数据子集,一般比节点数大。
由服务端管理节点、槽、数据的关系。
原理:
1.redis cluster共有16384(0~16383)个hash槽,分在集群不同的节点上。比如下图中,0~3276范围的槽在node1上,3277~6553范围的槽在node2上,以此类推。
2.对key做crc16(key)算出的值再对16383取余,最终得到的结果就是该key在哪个槽上。
3.集群维护了槽和节点的对应关系,通过第二步得到Key在哪个槽上就能知道key在哪个集器上