一致性hash主要用于分布式系统中,用于解决数据选择节点存储、选择节点访问、增删节点后数据的迁移和重分布问题。redis集群并没有使用一致性hash,而是使用了hash槽来解决数据分配的问题。
一致性hash:
它是一个0-2^32次方的圆,主要操作步骤:将每一个节点进行hash(如ip),让其落在这个闭合的圆环上;当我们进行数据存储或访问时,计算key的hash值,让其也落在这个闭合圆环之中;那么它顺时针找到的第一各服务节点就是存储key的节点
当添加节点时,例如再节点2和4之间添加了一个节点5,那么就有可能伴随数据的重分配,图中黄色区域的数据被分配到了节点5之上
当删除节点时,那么它的数据就会被分配到它顺时针寻找到的下一个节点之上。以下图为例节点2被删除,2的数据被分配到了4,那么就有可能出现一个问题,4的内存使用率就是瞬间增高,如果2之上有热点数据,就有可能将4直接打挂,这样就会顺延再将数据转移到3,从而导致所有节点循环崩溃。
同时当,集群中节点过少时还有可能出现数据倾斜,大量的数据都被分配到了同一个节点上,导致单一节点内存使用率和qps都很高,分布式服务的负载不平衡。如下图所示,从A顺时针到B明显比,B顺时针到A所占的区域小,那么数据被分配到A的概率就会比B大。
为了解决雪崩现象和数据倾斜现象,提出了虚拟节点的概念。就是将真实节点计算多个哈希形成多个虚拟节点并放置到哈希环上,定位算法不变,只是多了一步虚拟节点到真实节点映射的过程。如下图所示每个节点都映射出了两个虚拟节点,当节点1挂掉以后,它的数据并没有全部转移到同一个节点,而是被分配到了v301和v200,即节点2和3之上;此外由于加入了虚拟节点数据倾斜的问题也得到了解决。
redis 使用数据分片的hash槽来应对数据存储和读取。redis集群共有2^14次方16384个hash槽,当操作数据时,使用CRC16算法计算key的hash值,然后与16384取模从而确定该数据是属于哪一个slot槽的。redis集群中,每个服务节点都被分配一段hash槽,只要确定了数据属于哪一个槽,就可以确定该数据是在哪一个节点之上。槽是可以迁移的,master节点的slave节点不分配槽,只拥有读权限。但是注意在代码中redis cluster执行读写操作的都是master节点,并不是你想 的读是从节点,写是主节点。第一次新建redis cluster时,16384个槽是被master节点均匀分布的。当新增或删除master节点时,需要对槽进行重分配,而不是直接对数据进行分配。对于hash槽的转移和分配,redis不会自动进行,需要人工辅助。
一致性hash和redis hash槽的区别
1. redis hash槽并不是闭合的,它一共有16384个槽,使用CRC16算法计算key的hash值,与16384取模,确定数据在哪个槽中,从而找到所属的redis服务器;一致性hash表示一个0到2^32的圆环,对数据计算hash后落到该圆环中,顺时针第一个节点为其所属服务。
2.一致性hash是通过虚拟节点去避免服务节点宕机后数据转移造成的服务内存占用率过高,保证数据完整性和集群可用性的;而hash集群是使用主从节点的形式,主节点提供读写服务,从节点进行数据同步备份,当主节点出现故障后,从节点继续提供服务。