精华内容
下载资源
问答
  • 目录 Redis哈希槽 并发量与哈希槽 ...一个 redis 集群包含 16384 个哈希槽(hash slot),数据库中的每个数据都属于这16384个哈希槽中的一个。集群使用公式 CRC16(key) % 16384 来计算键 key 属于...

    目录

    Redis哈希槽

    并发量与哈希槽

    Redis如何通过哈希槽实现数据共享

    热点缓存的问题

    案例背景

    缓存问题分析与解决过程

    预防“缓存被击穿”总结

    更多思考


    Redis哈希槽

    一个 redis 集群包含 16384 个哈希槽(hash slot),数据库中的每个数据都属于这16384个哈希槽中的一个。集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽。集群中的每一个节点负责处理一部分哈希槽。

    slot返回有关哪个集群插槽映射到哪个redis实例的详细信息。该命令适用于redis集群客户端库实现,以便检索(或在收到重定向时更新)将集群散列槽与实际节点网络坐标(由ip地址和tcp端口组成)关联的映射,以便在接收到命令时,可以将其发送到命令中指定的键的正确实例。

     

    并发量与哈希槽

    也就是说哈希槽是用来决定这个key存在哪个节点,通过哈希计算,得到槽值为1,那么这个数据将存到节点1的Redis上,但是对于并发性的问题,大家可能会有一个误解,如同时有大于16384个请求,我们是否等待16383个槽处理完之后再处理16384之后的请求呢?答案是不需要,槽值一旦被计算出来,就只作为一个值来用,这个值决定了访问哪个节点的Redis,而计算这个值的速度,或者并发量(同一时刻允许多少次计算),并不取决与槽有多少,而是取决与这台服务器的计算能力

    如图,该Redis集群拥有三个节点,哈希槽平均分配

     

     

    Redis如何通过哈希槽实现数据共享

    Redis集群没有使用一致的散列,而是一种不同的分片形式,其中每个 key 在概念上都是我们称之为散列槽的部分。

    Redis集群中有16384个散列槽,为了计算给定 key 的散列槽,我们简单地取16384模的CRC16。

    Redis集群中的每个节点负责哈希槽的一个子集,例如,您可能有一个具有3个节点的集群,其中:

    • 1、节点A包含从0到5500的散列槽。
    • 2、节点B包含从5501到11000的散列槽。
    • 3、节点C包含从11001到16383的散列槽。

    这允许轻松地添加和删除集群中的节点。例如,如果我想添加一个新节点D,我需要将节点A,B,C中的一些散列槽移动到D。同样,如果我想从集群中删除节点A,我可以只移动由A使用的散列槽到B和C,当节点A将为空时,我可以将它从群集中彻底删除。

    因为将散列槽从一个节点移动到另一个节点不需要停机操作,添加和移除节点或更改节点占用的散列槽的百分比也不需要任何停机时间。

    只要涉及单个命令执行(或整个事务或Lua脚本执行)的所有 key 都属于同一散列插槽,Redis群集就支持多个 key 操作。用户可以使用称为散列标签的概念强制多个 key 成为同一个散列槽的一部分。

    Hash标记记录在Redis集群规范文档中,但要点是如果在关键字{}括号内有一个子字符串,那么只有该花括号“{}”内部的内容被散列,例如 this{foo}key 和 another{foo}key 保证在同一散列槽中,并且可以在具有多个 key 作为参数的命令中一起使用。

     

    热点缓存的问题

    redis cluster采用数据分片的哈希槽来进行数据存储和数据的读取。redis cluster一共有2^14(16384)个槽,所有的master节点都会有一个槽区比如0~1000,槽数是可以迁移的。master节点的slave节点不分配槽,只拥有读权限。但是注意在代码中redis cluster执行读写操作的都是master节点,并不是你想 的读是从节点,写是主节点。第一次新建redis cluster时,16384个槽是被master节点均匀分布的。

     

     

    和一致性哈希相比

    1. 它并不是闭合的,key的定位规则是根据CRC-16(key)%16384的值来判断属于哪个槽区,从而判断该key属于哪个节点,而一致性哈希是根据hash(key)的值来顺时针找第一个hash(ip)的节点,从而确定key存储在哪个节点。
    2. 一致性哈希是创建虚拟节点来实现节点宕机后的数据转移并保证数据的安全性和集群的可用性的。redis cluster是采用master节点有多个slave节点机制来保证数据的完整性的,master节点写入数据,slave节点同步数据。当master节点挂机后,slave节点会通过选举机制选举出一个节点变成master节点,实现高可用。但是这里有一点需要考虑,如果master节点存在热点缓存,某一个时刻某个key的访问急剧增高,这时该mater节点可能操劳过度而死,随后从节点选举为主节点后,同样宕机,一次类推,造成缓存雪崩,看下面这个案例

     

    案例背景

    电商场景促销活动的会场页由于经常集中在某个时间点进行“秒杀”促销,这些页面的QPS(服务器每秒可以处理的请求量)往往特别高,数据库通常无法直接支撑如此高QPS的请求,常见的解决方案是让大部分相同信息的请求都尽可能地压在缓存(cache)上来缓解数据库(DB)的压力,从而尽可能地去满足高并发访问的诉求(如图2-1所示)。

     

    这里写图片描述

     

     

    在一次业务促销过程中,运营给一大批用户集中推送了一条消息:10点钟准时抢购一批远低于市场价而且数量有限的促销活动商品。由于确实物美价廉,用户收到消息之后10点钟准时进入手机客户端的会场页进行疯抢。几分钟内很多用户进入会场页,最终导致页面异常,服务器疯狂报警。报警信息显示很多关于缓存的异常,由于缓存拿不到数据转而会转向数据库去查询数据,这样数据库更加难以支撑,整个业务集群处于雪崩状态(如图所示)。

     

    这里写图片描述

     

     

    此时缓存到底发生了什么问题?关注哪些方面可以有效地预防缓存被击穿导致雪崩的发生呢?

    缓存问题分析与解决过程

    1. 首先查看缓存详细日志,发现有很多带有“CacheOverflow”字样的日志,初步怀疑是触发了缓存限流。但是计算了缓存的整体能力和当前访问量情况:缓存的机器数×单机能够承受的QPS > 当前用户访问的最大QPS值,此时用户访问QPS并没有超过缓存之前的预算,怎么也会触发限流呢?
    2. 进一步分析日志,发现所有服务器上限流日志中缓存机器IP貌似都是同一台,说明大流量并没有按预想平均分散在不同的缓存机器上。回想前面提到的案例实际现象,发现确实有部分数据用户的访问请求都会触发对缓存中同一个key(热点key)进行访问,用户访问QPS有多大,则这个key的并发数就会有多大,而其他缓存机器完全没有分担任何请求压力。
    3. 然后紧急梳理出存在“热点请求”的key,并快速接入“热点本地缓存”方案,然后迅速在下一场秒杀活动中进一步进行验证,此时发现之前异常大幅度减少。不过还是有少量“CacheOverflow”字样异常日志。热点key的请求都被“本地缓存”拦截掉了,此时发现远程QPS限流异常已经基本没有了,这又是什么原因呢? 

    这里写图片描述

     



    仔细查看缓存单台机器的网络流量监控,发现偶尔有网络流量过大超过单台缓存机器的情况。 

    这里写图片描述

     


    说明缓存中有某些key对应的value数据过大,导致尽管QPS不是很高,但是网络流量(QPS×单个value的大小)还是过大,触发了缓存单台机器的网络流量限流。

    1. 紧急梳理出存在“大value”的key,发现这些“大value”部分是可以精简,部分是可以直接放入内存不用每次都远程获取的,经过一番梳理和优化之后,下次“秒杀”场景终于风平浪静了。至此问题初步得到解决。

    预防“缓存被击穿”总结

    1. 评估缓存是否满足具体业务场景的请求流量,不是简单地对预估访问流量除以单台缓存的最大服务能力
    2. 如果使用的缓存机制是按key的hash值散列到同一台机器,则必须梳理出当前业务场景中被高并发访问的那些key,看看这些key的并发访问量是否会超过单台机器的服务能力,如果超过则必须采取更多措施进行规避。
    3. 除了关注key的并发访问量外,还要关注key对应value的大小,如果key的并发访问量×value大小 > 单台缓存机器的网络流量限制,则也需要采取更多措施进行数据精简。

    更多思考

    1. 单个key的请求量不超过单台缓存机器的服务能力,但是如果多个key正好散列到同一台机器,而且这几个key的流量之和超过单台机器的服务能力,我们该如何处理呢?
    2. 单个key的并发访问量×对应value大小 < 单台缓存机器的网络流量限制,但是如果多个key的并发访问量×各自对应value大小 >单台缓存机器的网络流量限制,又该如何处理呢?

    针对上述两个问题,首先要做的是做好缓存中元素key的访问监控,一旦发现缓存有QPS限流或者网络大小限流时,能够迅速定位哪些key并发访问量过大,或者哪些key返回的value大小较大,再结合缓存的散列算法,通过一定规则动态修改key值来自动将这些可疑的key平均散列到各台缓存机器上去,这样就可以充分地利用所有缓存机器来分摊压力,保证缓存集群的最大可用能力,从而减少缓存被击穿的风险。提示:Redis集群提供了移动哈希槽的命令,我们可以从这一点入手

    展开全文
  • redis哈希槽和一致性哈希实现原理

    千次阅读 2020-10-24 17:41:39
    在 Redis 中为了保证 Redis 的高可用也为 Redis 搭建了集群对数据进行分存放。在 Mysql数据库要存储的量达到一个很高的地步的时候,我们会对数据库进行分库分表操作。OK,到这儿先假设我们不知道什么是集群、什么是...

    1 一致性哈希

    伴随着系统流量的增大,出现了应用集群。在 Redis 中为了保证 Redis 的高可用也为 Redis 搭建了集群对数据进行分槽存放。在 Mysql数据库要存储的量达到一个很高的地步的时候,我们会对数据库进行分库分表操作。
    OK,到这儿先假设我们不知道什么是集群、什么是分库分表,我们先来看一个数据库水平切分演变的例子:

    假设我们的系统中有一张会员表 customer_info,
    我们的系统刚开始无人问津,我们在一个单个的数据库中放这张表,所有的会员记录都插入到这个数据库的这张表中,这没什么问题,是一个很正常且合理的操作。某段时间,我们的系统突然火爆了起来,注册会员激增,达到了千万级别并且还在快速增长,这时候所有的用户请求数据都会请求这张表,毫无疑问数据库的压力很大,于是可能会经常发生宕机事件,给系统造成了很大影响。为了解决这件事情,我们将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据不同。
    这样做能够有效的缓解单机数据库的压力和系统的性能瓶颈。

    看完了这个例子,我们对水平拆分数据库有了一个大致的印象,其实就是把很多的数据按照一定的规则存放在不同的服务器上,然后查找的时候能够根据存放的时候的规则去找到前面存放的数据。那么我们要说的一致性哈希算法,其实就是解决了这里面的 存取规则 的问题,有了这个一致性哈希算法,我们能够准确的知道我们要取的数据落在哪个机器的哪个数据库中。

    1.1 简单哈希

    还是上面水平拆分数据库的例子,假设我们现在不知道什么一致性哈希,什么集群分槽,就让我们自己想的话,我们可以很容器的想到 java 中的 HashMap 的原理,它通过计算了一个 key 的哈希值,然后拿这个哈希值对底层数组取模就得到了一个哈希桶,如果数据存在的话,就一定在这个哈希桶里,否则就不存在。类似的可以想到,假设我们的customer_info我们可以按照用户id去分库分表,假设此时存在水平的三个库表,如下,我们分别称之为 节点D1,节点D2,节点D0

    节点	机器 ip	      数据库	           数据表
    D0		127.0.0.1	customer		customer_info
    D1		127.0.0.2	customer		customer_info
    D2		127.0.0.3	customer		customer_info
    

    分库分表的时候,用户 A 的记录落在了 D1 机器,用户 B 的记录落在了 D2 机器,用户 C 的机器落在了 D0 机器上,用户 A 要存在哪条数据库上的计算过程是用户 A 的会员 id 的哈希值对 3 取模,因为现在只有 3 台机器,伪代码: A_id.hash() % / 3,用户 B 和用户 C 依次类推。如下图所示
    1576749439795.jpg

    这好像很方便的解决了存取规则的问题,我们来分析一波:
    假设我们的系统用户量又激增了,我们就需要再加一些机器,此时我们再计算哈希值的时候,取模不再是对 3 取模了,而是对 4 进行取模了,之前 A_id.hash() % / 3 = 1,而现在 A_id.hash() % / 4 = ? 这个值很大概率不会是 1,所以这就会出现用户明明存在记录但是却查不到的情况,这就问题很大了,如果要解决这个问题只能在机器节点数量变化的时候对数据重新哈希,这代价就有点大了。所以,我们需要想办法让这种情况不发生,这种情况发生的根本是哈希算法本身的特性导致的,直接使用取模的话这是无法避免的,所以就有了一致性哈希。

    1.2 一致性哈希

    上面通过数据库的例子介绍了哈希算法,然后也分析了它的劣势,当机器数量发生变动的时候,几乎所有的数据都会移动(不移动的应该是运气比较好吧,前后取模都是同一个值),这个代价很大。此时的问题从水平如何拆分变成了,当增加或者删除节点时,对于大多数记录,保证原来分配到的某个节点,现在仍然应该分配到那个节点,将数据迁移量的降到最低,这就是一致性哈希要做的事情。在这里我们不指定是数据库还是什么,反正都是分布式存储节点。
    一致性 Hash 算法也是使用取模的思想,只是,刚才描述的取模法是对节点数量进行取模,而一致性Hash算法是对 232 取模,什么意思呢?
    简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为 0~232 -1(即哈希值是一个32位无符号整形),整个哈希环如下,从 0~232 -1代表的分别是一个个的节点,这个环也叫哈希环。 1576749570792.jpg

    然后我们将我们的节点进行一次哈希,按照一定的规则,比如按照 ip 地址的哈希值,让节点落在哈希环上。比如此时我们可能得到了如下图的环: 1576749699149.jpg
    然后就是需要通过数据 key 找到对应的服务器然后存储了,我们约定,通过数据 key 的哈希值落在哈希环上的节点,如果命中了机器节点就落在这个机器上,否则落在顺时针直到碰到第一个机器。如下图所示 : A 的哈希值落在了 D2 节点的前面,往下找落在了 D2 机器上,D的哈希值 在 D1 节点的前面,往下找到了 D1 机器,B的哈希值刚好落在了D1 节点上,依次~~~ 1576749737091.jpg

    1.3 一致性哈希的分析

    一致性哈希主要就是解决当机器减少或增加的时候,大面积的数据重新哈希的问题,主要从下面 2 个方向去考虑的,当节点宕机时,数据记录会被定位到下一个节点上,当新增节点的时候 ,相关区间内的数据记录就需要重新哈希。

    1.4 某节点宕机(缩减节点)

    我们假设上图中的 节点 D2 因为一些原因宕机了,可以看到,只有数据 A 的记录需要重新重新定位存储到节点 D1 上,因为 D1 是 D2 的下一个节点,其它的数据都没有被影响到,此时被影响的仅仅是 图中的 D0-D2 这段区间的记录,也就是之前落在 D2 上的数据现在都要落到 D1 上面了。如下图 1576749947380.jpg

    1.5 新增节点

    我们假设我们需要增加一台机器,也就是增加一个节点D4,如下图所示,这个节点落在 D2-D1 之间,按照上述的哈希环上的哈希值落在节点的规则,那么此时之前落在 D2 到 D4 之间的数据都需要重新定位到新的节点上面了,而其它位置的数据是不需要有改变的。 1576750002698.jpg

    1.6 一致性哈希的数据倾斜问题

    一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题。比如只有 2 台机器,这 2 台机器离的很近,那么顺时针第一个机器节点上将存在大量的数据,第二个机器节点上数据会很少。如下图所示,D0 机器承载了绝大多数的数据 1576750067545.jpg

    1.7 虚拟节点解决数据倾斜问题

    为了避免出现数据倾斜问题,一致性 Hash 算法引入了虚拟节点的机制,也就是每个机器节点会进行多次哈希,最终每个机器节点在哈希环上会有多个虚拟节点存在,使用这种方式来大大削弱甚至避免数据倾斜问题。同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“D1#1”、“D1#2”、“D1#3”三个虚拟节点的数据均定位到 D1 上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。这也是 Dubbo 负载均衡中有一种一致性哈希负载均衡的实现思想1576750113727.jpg

    1.8 一致性哈希的应用案例

    一致性哈希用到的地方很多,特别是中间件里面,比如 Dubbo 的负载均衡也有一种策略是一致性哈希策略,使用的就是虚拟节点实现的。Redis 集群中也用到了相关思想,但是没有直接使用用它,而是根据实际情况改进了一下。而对于存储数据的节点水平切分的时候它的作用就更不可代替了。and so on···

    2 Redis 集群分槽的实现

    Redis 集群并没有直接使用一致性哈希,而是使用了哈希槽 (slot) 的概念,Redis 没有直接使用哈希算法 hash(),而是使用了crc16校验算法。槽位其实就是一个个的空间的单位。
    其实哈希槽的本质和一致性哈希算法非常相似,不同点就是对于哈希空间的定义。一致性哈希的空间是一个圆环,节点分布是基于圆环的,无法很好的控制数据分布,可能会产生数据倾斜问题。而 Redis 的槽位空间是自定义分配的,类似于Windows盘分区的概念。
    这种分区是可以自定义大小,自定义位置的。Redis 集群包含了 16384 (214)个哈希槽,也就是整个哈希函数H的值空间为 0~214 -1(即哈希值是一个14位无符号整形),每个 Key 经过计算后会落在一个具体的槽位上,而槽位具体在哪个机器上是用户自己根据自己机器的情况配置的,机器硬盘小的可以分配少一点槽位,硬盘大的可以分配多一点。如果节点硬盘都差不多则可以平均分配。所以哈希槽这种概念很好地解决了一致性哈希的弊端。
    另外在容错性和扩展性上与一致性哈希一样,都是对受影响的数据进行转移而不影响其它的数据。而哈希槽本质上是对槽位的转移,把故障节点负责的槽位转移到其他正常的节点上。扩展节点也是一样,把其他节点上的槽位转移到新的节点上。

    需要注意的是,对于槽位的转移和分派,Redis集群是不会自动进行的,而是需要人工配置的。所以Redis集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。
    1576750217120.jpg

    转载 :chanclee - redis哈希槽和一致性哈希实现原理

    展开全文
  • 哈希槽是在redis cluster集群方案中采用的,redis cluster集群没有采用一致性哈希方案,而是采用数据分片中的哈希槽来进行数据存储与读取的。 一致性哈希 一致性hash是一个0-2^32的闭合圆,(拥有2^23个桶空间,每...

    背景

    随着memcache和redis的出现,更多人认识到了一致性哈希。

    一致性哈希用于解决分布式缓存系统中数据选择节点存储问题数据选择节点读取问题以及在增删节点后减少数据缓存的消失范畴防止雪崩的发生

    哈希槽是在redis cluster集群方案中采用的,redis cluster集群没有采用一致性哈希方案,而是采用数据分片中的哈希槽来进行数据存储与读取的。

    一致性哈希

    一致性hash是一个0-2^32的闭合圆,(拥有2^23个桶空间,每个桶里面可以存储很多数据,可以理解为s3的存储桶)所有节点存储的数据都是不一样的。计算一致性哈希是采用的是如下步骤:

    1. 对节点进行hash,通常使用其节点的ip或者是具有唯一标示的数据进行hash(ip),将其值分布在这个闭合圆上。
    2. 将存储的key进行hash(key),然后将其值要分布在这个闭合圆上。
    3. 从hash(key)在圆上映射的位置开始顺时针方向找到的一个节点即为存储key的节点。如果到圆上的0处都未找到节点,那么0位置后的顺时针方向的第一个节点就是key的存储节点。

    添加节点带来的影响
    图1为一致性hash的分布情况,箭头指向key的分布情况。

    如果现在node2和node4节点中间增加一个node5节点,那么在node4和node2之间的这些数据要存储的节点就会有所变化。在图中的黄色区域的数据将会从原来的node4节点挪到node5节点。

    删除节点带来的影响
    以图1为基准,删除了node2节点后,原本在node2节点上的数据就会被重新定位node4上。这样就产生一个影响:原来node2的数据转移到node4上,这样node4的内存使用率会骤增,如果node2上存在热点数据,node4会扛不住甚至会可能挂掉,挂掉之后数据又转移给node3,如此循环会造成所有节点崩溃,也就是前面所说的雪崩的情况。

    节点太少造成的影响
    节点太少的话可能造成数据倾斜的情况,如图中中只有俩节点,可能会造成大量数据存放在node A节点上,而node B节点存储很少的数据。

    虚拟节点
    为了解决雪崩现象和数据倾斜现象,提出了虚拟节点这个概念。就是将真实节点计算多个哈希形成多个虚拟节点并放置到哈希环上,定位算法不变,只是多了一步虚拟节点到真实节点映射的过程

    以雪崩现象来说明:如下图节点real1节点又俩个虚拟节点v100和v101,real2有俩个虚拟节点v200和v201,real3节点有v300和v301俩个虚拟节点。

    当real1节点挂掉后,v100和v101节点也会随即消失,这时k1数据就会被分配到v301上,k4就会被分配到了v200上,这就解决了雪崩的问题,当某个节点宕机后,其数据并没有全部分配给某一个节点,而是被分到了多个节点。

    正因为加入了虚拟节点机制,数据倾斜的问题也随之解决

    注意:真实节点不放置到哈希环上,只有虚拟节点才会放上去。

    为什么要使用闭合的哈希环
    举个例子,如果在2^23-3处有一个key,而2^23-3~2^23处并没有节点,那么这个key该存在哪里节点呢?说到这里你应该明白来吧

     

    哈希槽

    redis cluster采用数据分片的哈希槽来进行数据存储和数据的读取。redis cluster一共有2^14(16384)个槽,所有的master节点都会有一个槽区比如0~1000,槽数是可以迁移的。master节点的slave节点不分配槽,只拥有读权限。但是注意在代码中redis cluster执行读写操作的都是master节点,并不是你想 的读是从节点,写是主节点。第一次新建redis cluster时,16384个槽是被master节点均匀分布的。

    和一致性哈希相比

    1. 它并不是闭合的,key的定位规则是根据CRC-16(key)%16384的值来判断属于哪个槽区,从而判断该key属于哪个节点,而一致性哈希是根据hash(key)的值来顺时针找第一个hash(ip)的节点,从而确定key存储在哪个节点。
    2. 一致性哈希是创建虚拟节点来实现节点宕机后的数据转移并保证数据的安全性和集群的可用性的。redis cluster是采用master节点有多个slave节点机制来保证数据的完整性的,master节点写入数据,slave节点同步数据。当master节点挂机后,slave节点会通过选举机制选举出一个节点变成master节点,实现高可用。但是这里有一点需要考虑,如果master节点存在热点缓存,某一个时刻某个key的访问急剧增高,这时该mater节点可能操劳过度而死,随后从节点选举为主节点后,同样宕机,依次类推,造成缓存雪崩。解决这个问题请看我的另一篇文章如何应对热点缓存问题

    新建master节点
    使用redis-trib.rb工具来创建master节点

     

    ./redis-trib.rb add-node 172.60.0.7:6379 172.60.0.5:6379
    

    注释:

     

    192.168.10.219:6378是新增的节点
    
    192.168.10.219:6379集群任一个旧节点
    

    注意:新建的master节点是没有槽区的,需要给master节点分配槽,不然缓存无法命中。分配槽的方法自行百度。
    删除master节点
    1.如果主节点有从节点,需要将从节点转移到别的主节点上。
    2.转移后 如果主节点有哈希槽,去调哈希槽,然后在删除master节点
    注意:redis cluster的动态扩容和缩容并不会影响集群的使用。

    展开全文
  • 哈希槽其实就是一个数组,数组[0, 1, 2, ..., 2^14-1]形成hash slot空间 3-2、把哈希槽均匀分段,分配给redis节点 redis节点1,负责存储5461个哈希槽的数据,编号0号至5460号哈希槽 redis节点2,负责存储5462个哈希...

    面试题:在高并发的互联网公司中,有1亿条数据需要缓存,请问如何设计存储这批数据?
    答:单台服务器肯定存储不了这么大的数据,一般是分布式存储,就像数据库的分库分表一样存储,那针对缓存redis如何分布式存储这么大的数据?

    业界的做法一般有3种:
    1、方法一:哈希取余分区
    针对redis来说1亿条数据,一般是对应1亿个key value,我们把他分别存储在N个节点,如上图N=3,然后用户每次读写操作,根据节点N使用公式hash(key)%N计算出哈希值,用来决定数据映射到哪一个节点上
    用来决定数据映射到哪一个节点上
    这种方案的优缺点:
    优点:简单粗暴,只要提前预估好数据量,然后规划好节点,例如:3台、30台、300台节点,就能保证未来一段时间内的数据支撑
    缺点:节点扩容或收缩节点的时候就麻烦了,因为每次节点有变动数据节点映射关系需要重新计算,会导致数据的重新迁移
    例如原先是3台,后面要新增到8台,要把所有的历史数据按hash(key)%8,重新洗一遍,非常麻烦


    2、方法二:一致性哈希分区
    在1997年,麻省理工学院的Karger等人提出了一致性哈希算法,为的就是解决分布式缓存的问题
    一致性哈希算法基本原理大概需要3个步骤来解释:构造一致性哈希环、节点映射、路由规则
    步骤1:构造一致性哈希环
    一致性哈希算法中首先有一个哈希函数,哈希函数产生hash值,所有可能的哈希值构成一个哈希空间,哈希空间为[0, 2^32-1],这本来是一个“线性”的空间,但是在算法中通过恰当逻辑控制,使其首尾相衔接,也即是0=2^32-1,这样就构造一个逻辑上的环形空间

    步骤2:节点映射
    将集群中的各IP节点映射到环上的某一个位置
    假设有四个节点Node A、B、C、D,经过ip地址的哈希函数计算(例如:hash(192.168.1.13)),它们的位置如下:

    步骤3:路由规则
    路由规则包括存储(setX)和取值(getX)规则
    当需要存储一个<key-value>对时,首先计算键key的hash值:hash(key),这个hash值必然对应于一致性hash环上的某个位置,然后沿着这个值按顺时针找到第一个节点,并将该键值对存储在该节点上
    例如有4个存储对象Object A、B、C、D,经过对key的哈希计算后,它们的位置如图
    对于各个Object,它所真正的存储位置是按顺时针找到的第一个存储节点
    例如Object A顺时针找到的第一个节点是Node A,所以Node A负责存储Object A,Object B存储在Node B

    一致性哈希如何实现容错性和扩展性?
    容错性
    假设Node C节点挂掉了,Object C的存储丢失,如果要重新把数据补回来时,Object C就会顺时针找到的最新节点是Node D
    也就是说Node C挂掉了,受影响仅仅包括Node B到Node C区间的数据,并且这些数据会转移到Node D进行存储
    扩展性
    假设现在数据量大了,需要增加一台节点 Node X,Node X位置在Node A到Node B之间,那么受到影响的仅仅是Node A到Node X间的数据,重新把A到X之间的数据洗到Node X上即可

    优缺点
    优点:与哈希取余分区相比,容错性和扩展性更灵活,例如Node C瘫痪,只影响Node B到Node C区间的数据,影响面小;
    再例如增加一台节点Node X,只影响到Node A到Node B之间的数据,不会导致哈希取余全部数据重洗
    缺点:数据倾斜不一致性
    如果在分片的集群中,节点太少,并且分布不均,一致性哈希算法就会出现部分节点数据太多,部分节点数据太少。也就是说无法控制节点存储数据的分配。如图,大部分数据都在A上了,B的数据比较少

     

    3、方法三:哈希槽分区
    由于一致性哈希分区存在数据倾斜不一致性的问题,故引入了槽的概念
    3-1、什么是哈希槽呢?
    哈希槽其实就是一个数组,数组[0, 1, 2, ..., 2^14-1]形成hash slot空间

    3-2、把哈希槽均匀分段,分配给redis节点
    redis节点1,负责存储5461个哈希槽的数据,编号0号至5460号哈希槽
    redis节点2,负责存储5462个哈希槽的数据,编号5461号至10922号哈希槽
    redis节点3,负责存储5461个哈希槽的数据,编号10923号至16383号哈希槽

    3-3、计算每条数据的slot空间位置
    将数据key进行哈希取值,映射已经固定大小的hash slot空间上
    例如:可以采用spring redis的API
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    例如:我们往redis设置3条数据:
    redisTemplate.opsForValue.set("A", "agan1");
    redisTemplate.opsForValue.set("B", "agan2");
    redisTemplate.opsForValue.set("C", "agan3");
    然后计算key,A、B、C的slot槽位置
    io.lettuce.core.cluster.SlotHash.getSlot("A")=6373
    io.lettuce.core.cluster.SlotHash.getSlot("B")=10374
    io.lettuce.core.cluster.SlotHash.getSlot("C")=14503
    故,
    key A、B落在slot空间的5461至10922区间上,并最终存储在Node 2上
    key C落在slot空间的10923至16383区间上,并最终存储在Node 3上

    3-4、redis哈希槽分区的特点
    1)解耦数据和节点之间的关系,例如:数据的读写只要计算出槽号就可以,节点的扩容和收缩只要重新均衡分配槽区间即可;故简化了节点扩容和收缩难度
    2)节点自身维护槽的映射关系,不需要客户端(spring)或者代理服务维护槽分区和数据
    3)支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景

    数据和槽号是绑在一起的,spring通过槽号找到节点

    ========================================

    一、spring与redis通信
    1、建立TCP管道长连接
    2、发送
    3、结果返回

    二、redis哈希槽分区
    1、分析:哈希取余分区
    2、分析:一致性哈希分区原理
    3、分析:哈希槽分区原理
    4、redis集群哈希槽部署
    5、查看redis哈希槽的数据分布
    6、redis集群哈希槽扩容
    7、redis集群哈希槽收缩
    8、spring集成redis集群哈希槽

    三、建立TCP长连接,需要解决以下5个问题(常见的面试题):
    1、redis集群3主3从,spring配置文件该配几个ip?配1个还是6个?
    2、spring如何知道redis每个节点有多少个槽?
    3、spring如何实现redis槽和节点的映射关系?
    4、spring如何计算redis哈希槽?
    5、有了哈希号,spring如何算出redis集群节点IP?

    四、spring采用了netty与redis建立tcp连接后,就是如何进行数据网络通信?
    spring与redis在通信方面,技术点采用了netty、lettuce、CompletionStage、commons-pool2技术来实现网络通信
    最核心的技术是由于netty是异步通信,发出去和回来的是2条异步线程,为了解决这个难题,lettuce大量采用了CompletionStage把2条异步线程从异步改成同步

    五、通信异常处理
    1、spring与redis的TCP连接异常断开后,如何重连?
    2、发送者Endpoint和CommandHandler的设计原理
    3、redis断开重连,新channel如何加入发送者Endpoint?
    4、redis的tcp异常断开后,未发送的数据如何存储?
    5、如何把tcp异常断开的数据,再次发送出去?
    6、什么是redis集群MOVED异常?
    7、什么是redis集群ASK异常?
    8、当redis集群主从切换、哈希槽迁移,spring如何知道?
     

    展开全文
  • Redis 哈希槽概念

    2020-04-04 10:51:00
    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希...
  • 一致性哈希和哈希槽使用场景对比

    千次阅读 2019-08-24 20:32:26
    一致性哈希和哈希槽是分布式缓存集群系统常用的两种算法,本文不会再介绍这两种算法,感兴趣的可以阅读参考博文。本文想在此基础上分析下两种算法使用场景的差异。 在参考博文4中给了一个示例: 上图为一致性...
  • 1、集群分片模式 如果 redis 只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的...下面详细了解下 redis 的位分片原理,在此之前,先了解
  • 槽位越小,节点少的情况下,压缩率高 Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),...
  • 但此时master7007上是没有哈希槽的,所以需要给7007分配哈希槽 迁移哈希槽 redis-cli --cluster reshard --cluster-from all --cluster-to d725f58bb3c41a92405fa4d3119bddbf91f06a73 --cluster-slots 300 --...
  • Redis 集群没有使用一致性 hash 算法,而是引入了哈希槽的概念。 Redis 集群有 16384个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
  • 说说Redis哈希槽的概念? Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。 ...
  • 哈希槽

    2019-05-14 22:57:00
    https://blog.csdn.net/z15732621582/article/details/79121213 转载于:https://www.cnblogs.com/zousong/p/10865199.html
  • 一致性哈希 先看一致性hash,常见的一个环形图如下: 在1997年,麻省理工学院的 Karger 等人提出了一致性哈希算法,为的就是解决分布式缓存的问题。 在一致性哈希算法中,整个哈希空间是一个虚拟圆环。 对于各个 ...
  • redis 集群哈希槽的概念

    千次阅读 2018-12-11 16:08:37
    redis中默认有多少个哈希槽? Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会...
  • Redis的哈希槽介绍
  • 先说普通哈希算法:让数据id的哈希值和redis集群的个数取模,得到的是几这个数据就存放在哪个redis服务器上 普通哈希算法存在数据迁移的问题,即当集群数量增加或减少,原来数据的key与Redis序号对应的集群关系会...
  • 哈希槽 redis集群用的是哈希槽,而不是简单哈希和一致性哈希。 槽位的转移,即为槽位ID不变,而是槽位地址变了。集群只需要记住槽位ID和槽位地址映射就可以了。crc计算一个key的结果是一个恒定的槽位ID,即使是槽...
  • Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通 过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。 ...
  • Redis - Redis 哈希槽的概念

    万次阅读 多人点赞 2018-03-18 13:42:00
    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希...
  • 例如当前集群有3个节点,那么: 节点 A 包含 0 到 5500号哈希槽 节点 B 包含5501 到 11000 号哈希槽 节点 C 包含11001 到16384号哈希槽 3 Cluster 模式至少需要三个主节点 因为 Cluster 模式是基于Gossip 协议来同步...
  • 5、哈希槽 Redis集群(Cluster)并没有选用一致性哈希,而是采用了哈希槽(SLOT)的这种概念。主要的原因就是一致性哈希算法对于数据分布、节点位置的控制并不是很友好(整个哈希空间是一个虚拟圆环,数据顺时针...
  • redis集群之哈希槽

    2019-09-01 19:35:49
    redis 集群通过分片的方式保存数据库中的键值对:集群的整个数据库被分为16384个(slot),数据库中每个键都属于这16384个的其中一个,集群中的每个节点负责0个或者最多16384个。 怎么计算键key属于哪个? ...
  • 一致性哈希和哈希槽

    2021-08-16 17:59:26
    1、集群分片模式 如果 redis 只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的数据。...下面详细了解下 redis 的位分片原理,在此之
  • Redis哈希槽

    2020-07-28 16:53:42
    Redis 集群没有使用一致性 hash,是引入了哈希槽的概念。 其结构特点: 1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。 2、节点的fail是通过集群中超过半数的节点检测...
  • 1、集群分片模式 如果 redis 只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的...下面详细了解下 redis 的位分片原理,在此之前,先了解
  • Redis Cluster 的虚拟哈希槽策略

    千次阅读 2019-07-04 11:28:07
    Redis Cluster 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内计算公式:slot = CRC16(key) & 16383,每一个节点负责维护一部分槽以及槽所映射的键值数据。Redis 虚拟槽分区的特点:解耦...
  • 一致性Hash Vs 哈希槽

    千次阅读 2019-06-20 01:52:05
    但是,生产与实践中,redis最新版本已经放弃对一致性哈希的应用,提出了哈希槽(Hashslot)的概念,以下将通过两者的分析与对比,领略一下哈希槽的魅力。(最新信息请关注微信公众号: 白白家族) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,332
精华内容 8,932
关键字:

哈希槽