redis 数据分区--一致性hash&&虚拟槽分区
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis 数据分区--一致性hash&&虚拟槽分区相关的知识,希望对你有一定的参考价值。
参考技术A 1.节点区域分区:使用特定的数据,如redis的键或用户ID,再根据节点数量N使用公式:hash(key)%N计算出hash值,用来决定数据映射到哪一个节点上.
这种方案的问题是:
当节点数量变化时,需要重新计算hash,会导致数据的重新迁移.
2.一致性hash算法
一致性hash算法实现思路是为系统中每一个节点分配一个token,范围在0~2^32,这些token构成一个hash环.数据的读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该hash的token节点.
好处:
这种方式最大的好处就是,在加入或删除节点时,只影响hash环中相邻的两个节点,对其他节点无影响.
问题:
3.虚拟槽算法
使用分散度较好的hash函数,将所有的数据映射到 比如0~16383(2^14)范围的槽中(slot).这个槽的数量一般远远大于实例的数量.
槽是集群数据管理和迁移的基本单位.采用大范围槽的主要目的是为了方便数据拆分和集群扩展.
每一个实例会映射一部分范围的槽.
特点:
1.解耦数据和节点之间的关系,简化扩容和锁容的难度
2.节点自身维护槽的映射关系,不需要客户端或代理服务维护槽分区的元数据.
3.支持节点,槽,键之间的映射查询,用于数据路由,在线伸缩灯场景.
HashTags(面试)
Mset k1 v1 k2 v2 k3 v3
通过分片手段,可以将数据合理的划分到不同的节点上,这本来是一件好事。但是有的时候,我们希望对相关联的业务以原子性方式进行操作。举个简单的例子
我们在单节点上执行MSET (m表示多个,一次向redis设置多个key和值), 它是一个原子性的操作,我们要求所有给定的key要在同一时间内被设置,不能出现某些指定的key被更新另一些指定的key没有被更新的情况。但是在集群环境下,我们仍然可以执行MSET命令,但它的操作不在是原子操作,会存在某些指定的key被更新,而另外一些指定的key没有改变,原因是多个key可能会被分配到不同的机器上。
所以,这里就会存在一个矛盾点,及要求key尽可能的分散在不同机器,又要求某些相关联的key分配到相同机器。
这个也是在面试的时候会容易被问到的内容。怎么解决呢?
从前面的分析中我们了解到,分片其实就是一个hash的过程,对key做hash取模然后划分到不同的机器上。所以为了解决这个问题,我们需要考虑如何让相关联的key得到的hash值都相同呢?如果key全部相同是不现实的,所以怎么解决呢?在redis中引入了HashTag的概念,可以使得数据分布算法可以根据key的某一个部分进行计算,然后让相关的key落到同一个数据分片;
举个简单的例子,假如对于用户的信息进行存储,
redis:store:1001、redis:store:1002
那么通过hashtag的方式,
redis:store:1001、redis:store:1002; 表示
当一个key包含 的时候,就不对整个key做hash,而仅对 包括的字符串做hash。
以上是关于redis 数据分区--一致性hash&&虚拟槽分区的主要内容,如果未能解决你的问题,请参考以下文章
Redis - Redis分布式算法原理——Hash一致性理解 & Hash倾斜性解决方案