当前位置: 首页 > 后端技术 > Java

RedisCluster引起的几种算法的思考

时间:2023-04-01 16:39:02 Java

比较几种相似的算法,了解RedisCluster使用的算法的原因。首先介绍一下单调性:单调性是指如果某些内容已经通过哈希分配给了相应的缓冲区,则系统会添加一个新的缓冲区。散列的结果应该能够保证原来分配的内容能够映射到新的buffer,而不会映射到旧的bufferset中的其他buffer。1、HASH取余算法的简单公式:hash(object)%N应用场景:比如你有N个缓存服务器(以下简称缓存),如何将一个object对象映射到N个缓存中,你大概会用到类似的到下面的通用方法计算对象的哈希值,然后均匀映射到N个缓存;一切运行正常,再考虑以下两种情况;1某缓存服务器m宕机(在实际应用中必须考虑这种情况),所有映射到缓存m的对象都将失效。怎么办,缓存m需要从缓存中移除。此时有N-1个缓存,映射公式变为hash(object)%(N-1);2由于访问量增加,需要增加缓存。此时有N+1个缓存,映射公式变为hash(object)%(N+1);1和2是什么意思?这意味着突然几乎所有的缓存都失效了。对于服务器来说,这是一场灾难,洪水般的访问会直接涌向后台服务器;那么再考虑第三个问题,因为硬件能力越来越强,后面添加的节点可能要多做一些工作,显然上面的hash算法也做不到。hash的余数不满足单调性原则。有什么办法可以改变这种情况,这是一致性哈希。2.一致性哈希算法一致性哈希是一种哈希算法。简单的说,就是在移除/添加缓存时,尽可能少的改变已有的键映射关系,尽可能的满足单调性的要求。在一致性哈希算法中,0到2^32-1区间的数字顺时针组成一个环,如下图(图不全,请自行脑补):在rediscluster,集群服务器对ip或服务器名进行hash函数,然后对2^32取模,得到的数位于上面的环中,得到服务器在环中的位置。当key存入redis集群时,会对key进行hash函数,然后进行2^32取模,得到的值就是key在hashring上的位置。然后从这个位置开始,沿着圆圈顺时针走,直到到达第一个服务器位置,也就是存放密钥的地方。如下图:ObjectA通过hash()函数计算后,取模2^32,得到在hash环上的位置,然后顺时针找到第一个服务器位置,也就是ObjectA存放的位置。ObjectB也是如此。这样的设计有什么好处?我们看下图:上图中,假设C服务器宕机了,那么此时C服务器中存储的key会被传送到D服务器上。同时,顺时针搜索服务器在计算出新增数据在哈希环上的位置后,会直接跳过C,存储到D中。这样,服务器宕机不会影响所有服务器中的数据存储。而是只影响数据在D服务器中的存储内容。这样就避免了哈希检索时如果一台服务器宕机,分母会发生变化,所有服务器中的数据都会发生变化的情况。同样,在添加服务器时,也是在哈希环中寻找加入位置。新数据顺时针找到新添加的服务器后,会存储到新添加的服务器中,不会影响其他服务器的数据。可见哈希共识算法满足单调性原则。那么哈希共识算法有哪些缺点呢?如果有A、B、C三台服务器,通过计算,A和B在哈希环上比较近,B和C,C和A比较远。那么这个时候,数据顺时针落在服务器C和服务器A上的概率就会增加。掉到B服务器的概率很小。这就产生了数据倾斜的问题。数据不能均匀分布。下图也是数据倾斜问题的体现:3.哈希槽算法针对一致性哈希算法中数据倾斜的问题,ReidsCluster进行了优化,推导出了哈希槽算法。这是如何做的。在redis集群中,有一个固定数量的slots:16384,redis会根据clustermaster的数量,平均分配一定数量的slots给每个master节点。Redis会根据key进行hash计算,对16384取模,结果就是slot的个数。哪个服务器分配给这个slot,那么这段数据就会存储在那个服务器上。当redis集群扩容时,集群加入新节点后,需要执行reshard命令重新分配hash。此时,redis将允许用户输入分配的新节点数。一般为16384个槽/主节点个数得到的值,平分数据。选择平分后,上一个节点的每个节点都会被分成一些key,给新的节点,来补足新节点的个数。因为redis的slots总数固定为16384,添加一个新的节点,rehash一次,slots与节点数的对应关系肯定会发生变化。即原节点取出一部分时隙分配给新加入的节点。因为新加入的节点的slot是由其他节点分配的,所以slot的数量不是连续的,而是一段一段的。为什么其他节点均匀过来而不是重新分配所有slot,因为之前的节点已经存储了数据,如果全部重新分配,那么存储的key需要重新排列,所以优先分配不存储keyValue的slot到新节点。Redis集群缩容是将删除的槽平均分配给其他主节点接收数据。在rediscluster集群中,相当于节点上有槽,槽中有数据。通过在节点上均匀分配槽来避免一致性哈希中的数据倾斜问题