[ Redis ] 从一致性哈希算法说起,到 RedisCluster 集群的介绍

2023-12-20 14:32

本文主要是介绍[ Redis ] 从一致性哈希算法说起,到 RedisCluster 集群的介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言: 哨兵管理下的主从复制只做到了对一台Redis的高可用,本质上只存有一台机的数据容量。 —— 那么如果海量数据量超过了这台机器的容量呢? 你也许想到了,再对哨兵管理下的读写分离做集群。但是这个集群该怎么做呢?  

在这里插入图片描述
 
最简单的做法,就是哈希分片(你可以类比HashMap) —— 原本所有数据是存在一个小规模读写分离集群上的。当数据超过这个小规模集群的时候。我们就应该做大规模集群了。这时候我们把这个小规模集群看成一个分片。配置多个这样的分片,然后通过哈希算法+对分片个数取模(类似HashMap存储数据时计算下标的方式)把所有数据均匀分布在这些分片上。
 
—— 但是这样的集群存在一个问题,你要对集群的机器再做扩容或者缩容怎么办?哈希分片的位置是依靠分片个数来计算的,现在你分片个数变了。那必然导致要查询的数据映射不到原本应有的机器上,造成缓存雪崩效应…
 

这个时候的分片我们就可以用哈希算法的进化版 —— 一致性哈希是算法,这个算法的特点就是扩容/缩容只会导致极少量的缓存失效,这里我只做大致的讲解,对于这个算法的细节,本人强烈推荐这位大佬的博文:白话解析:一致性哈希算法 consistent hashing
 

  1. 一致性哈希算法本质上也是要求模,我们可以想象一个原上有2^32个点,假设我们对三台机的IP做哈希后取模(hash(服务器IP地址) % 2^32),得出的结果映射在这个圆环上,就是这三台机器应有的位置。

在这里插入图片描述
 
 
 
 
2. 假设这时候来了一个缓存数据的请求操作经过(hash(缓存数据) % 2^32)后,映射在途中橙点位置,那么这个点没有缓存机器怎么办? 这时就会按照顺时针找到的第一个节点作为缓存请求对象,如此以往。

在这里插入图片描述
 
 
 
 
3. 那么就很容易看出来,由于这个顺时针寻址的操作 —— 当要扩容或者缩容/宕机时,就只有一台机的缓存数据会受影响(如下图,如果把B去掉,那么3的缓存请求就会打到C上,这时候C再去数据库同步一次数据就行了,扩容同理)。

在这里插入图片描述
 
 
 
 
4. 但是理想是丰满的,现实确是骨感的,如果哈希算法后三台机器分布的节点不均匀怎么办? 如下图,3、4、6、2、1的缓存请求全部打在机器A上。

在这里插入图片描述
 
 
 
 
5. 那这个时候就要引入虚拟节点的概念了 —— 这个可以对原有哈希是算法进行加工(如某些算法依赖哈希种子,就可以改变这个种子),然后做多次哈希计算(有点布隆过滤器下标的味道了…),将原本的一个节点,虚拟出多个节点,分布在不同位置,进一步扩大节点的均匀分布程度,结果就如下所示,这时候就解决各机器可能分布不均的问题了。

在这里插入图片描述
 
 
 
 

上面大概解释了一致性哈希算法做大规模数据集群的概念,但Redis做大规模集群用的最多的还是官方推出的RedisCluster —— 首先这是一个去中心化的集群思想(原本的哨兵是不是类似一个中心?来管理主从复制的小规模集群)。这新方案相当于让每个主节点不但具备和从节点完成读写分离的能力,同时自身还具备了哨兵的选举能力(主节点之间会相互监督),和动态扩/缩容(和哈希一致性算法有类似之处)的能力,当然对Redis的集群方案有很多,下面简单罗列一下,仅供知识拓展,因为现在主流、好用的大规模集群还是RedisCluster。

 
 
Redis集群还可以通过

  • 哈希一致性算法对每台机进行分片(上文已描述),从而达到集群效果,缺点是开发人员维护成本相对较高
  • 使用Twemproxy —— 推特最开始出的集群方案之一,但是缺点是无法在线扩容、缩容
  • Codis集群 —— 很优秀的一个集群方案,前豌豆荚大神开发,但要想使用Codis,必须使用它内置的Redis,所以它内部的版本号就很重要了,可惜的是这个项目再Redis3.2.8后就没维护了
  • 官方推出的RedisCluster去中心化大规模集群方案 ( 如下文描述 )

 
 

RedisCluster大规模集群


 
RedisCluster集群和哈希一致性算法有点类似,但是它不是一台机器映射一个节点的方式。而是一台机器管理多少个节点(这里我们把节点称为槽)的方式来做集群,具体如下:
 

  1. 所有的redis节点彼此互联(通过PING-PONG机制来确认彼此是否健康),内部使用二进制协议优化传输速度和带宽。
     

  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效 —— 以上两点和哨兵是一样的思想,假设对一台机器发送Ping超过多久没返回,就会主观认为这台机器挂了,然后其他机器也会对这台机器发Ping信号,如果一半以上认为挂了就客观上认为真的挂了,此时会做新主节点选举的事情。(不管是RedisCluster还是哨兵的故障转移,他们底层使用的都是Raft算法)
     

  3. Redis把[0-16383]个槽均匀分布给每一台机器管理,比如A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:

    • 节点A覆盖0-5460;

    • 节点B覆盖5461-10922;

    • 节点C覆盖10923-16383.

      在这里插入图片描述

      [ RedisCluster集群图示 ]

       

  4. 当有数据来时会对这个数据做哈希+取模计算出数据的归属槽位(如:CRC16(缓存数据) & 16384-1),请求任一机器,这时机器内就会计算,如果是当前管理的槽位,就会去找数据返回。反之会把管理当前槽位的机器信息通过叫做Move的命令发给客户端重定向到对应的机器上来获取结果。
     

  5. 如果这时候做动态扩容,那么就会把每个节点管理的槽位分一部分到新的节点上,比如:

    • 节点A覆盖1365-5460
    • 节点B覆盖6827-10922
    • 节点C覆盖12288-16383
    • 节点D覆盖0-1364,5461-6826,10923-12287

    同样删除一个节点也是类似,移动完成后就可以删除这个节点了。
     

  6. 动态扩容时如果来了缓存请求,机器发现槽点由正在扩容的机器上管理,就会把新机器的信息通过一个叫ask的命令发送给客户端去寻找对应数据。
     

总结:

  • 一致性哈希算法集群: 由2^32 个节点组成的环,机器的IP地址做哈希运算然后对2^32取模后的节点映射在环上。缓存请求通过同样的算法+顺时针寻址找到对应的机器 —— 这样的好处是动态扩/缩容只会影响极小部分数据。而为了分布更加均匀,采用对机器做多次哈希,虚拟出不同节点来优化。
  • RedisCluster集群: 将16384个槽位均匀分给每台机管理,缓存请求机器时,会用哈希算法+取模得出对应的槽位。机器内部会做运算,检测当前槽位是否属于自身,是则返回数据,否则重定向到对应的机器返回数据 —— 动态扩/缩容时会对16384个槽位做二次分配。当有请求过来是,也是通过机器内部分析找出管理槽位的机器节点并返回相应数据。(需要注意的是:采用去中心化概念,主节点之间相互监督,完成故障转移。 故障转移的选举方式和哨兵一样,都是采用Raft算法)
     
     
     
     

本文参考:

Redis-Cluster集群

高可用Redis(十二):Redis Cluster

白话解析:一致性哈希算法 consistent hashing

Redis集群化方案对比:Codis、Twemproxy、Redis Cluster

另外推荐一位非常棒博主,他对Redis的理解更加透彻 —— http://kaito-kidd.com/

这篇关于[ Redis ] 从一致性哈希算法说起,到 RedisCluster 集群的介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/516388

相关文章

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Java中 instanceof 的用法详细介绍

《Java中instanceof的用法详细介绍》在Java中,instanceof是一个二元运算符(类型比较操作符),用于检查一个对象是否是某个特定类、接口的实例,或者是否是其子类的实例,这篇文章... 目录引言基本语法基本作用1. 检查对象是否是指定类的实例2. 检查对象是否是子类的实例3. 检查对象是否

Redis持久化机制之RDB与AOF的使用

《Redis持久化机制之RDB与AOF的使用》:本文主要介绍Redis持久化机制之RDB与AOF的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis持久化机制-RDB与AOF一、RDB持久化机制1、RDB简介2、RDB的工作原理3、RDB的优缺点4

基于Redis实现附近商铺查询功能

《基于Redis实现附近商铺查询功能》:本文主要介绍基于Redis实现-附近商铺查询功能,这个功能将使用到Redis中的GEO这种数据结构来实现,需要的朋友可以参考下... 目录基于Redis实现-附近查询1.GEO相关命令2.使用GEO来实现以下功能3.使用Java实现简China编程单的附近商铺查询4.Red

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli

Redis中RedisSearch使用及应用场景

《Redis中RedisSearch使用及应用场景》RedisSearch是一个强大的全文搜索和索引模块,可以为Redis添加高效的搜索功能,下面就来介绍一下RedisSearch使用及应用场景,感兴... 目录1. RedisSearch的基本概念2. RedisSearch的核心功能(1) 创建索引(2

Redis中HyperLogLog的使用小结

《Redis中HyperLogLog的使用小结》Redis的HyperLogLog是一种概率性数据结构,用于统计唯一元素的数量(基数),本文主要介绍了Redis中HyperLogLog的使用小结,感兴... 目录 一、HyperlogLog 是什么?️ 二、使用方法1. 添加数据2. 查询基数China编程3.

Redis中的数据一致性问题以及解决方案

《Redis中的数据一致性问题以及解决方案》:本文主要介绍Redis中的数据一致性问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Redis 数据一致性问题的产生1. 单节点环境的一致性问题2. 网络分区和宕机3. 并发写入导致的脏数据4. 持

浅谈Redis Key 命名规范文档

《浅谈RedisKey命名规范文档》本文介绍了Redis键名命名规范,包括命名格式、具体规范、数据类型扩展命名、时间敏感型键名、规范总结以及实际应用示例,感兴趣的可以了解一下... 目录1. 命名格式格式模板:示例:2. 具体规范2.1 小写命名2.2 使用冒号分隔层级2.3 标识符命名3. 数据类型扩展命

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ