复制粘贴自: https://www.e-learn.cn/content/redis/2344485, 点击链接访问原文

仅供个人学习参考之用, 如有侵权, 请联系删除!

高级开发不得不懂的Redis Cluster数据分片机制

Redis 集群简介

Redis Cluster 是 Redis 的分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 分布式方面的需求。

Redis Cluster 一般由多个节点组成,节点数量至少为 6 个才能保证组成完整高可用的集群,其中三个为主节点,三个为从节点。三个主节点会分配槽,处理客户端的命令请求,而从节点可用在主节点故障后,顶替主节点。

如上图所示,该集群中包含 6 个 Redis 节点,3主3从,分别为M1,M2,M3,S1,S2,S3。除了主从 Redis 节点之间进行数据复制外,所有 Redis 节点之间采用 Gossip 协议进行通信,交换维护节点元数据信息。

一般来说,主 Redis 节点会处理 Clients 的读写操作,而从节点只处理读操作。

数据分片策略

分布式数据存储方案中最为重要的一点就是数据分片,也就是所谓的 Sharding。

为了使得集群能够水平扩展,首要解决的问题就是如何将整个数据集按照一定的规则分配到多个节点上,常用的数据分片的方法有:范围分片,哈希分片,一致性哈希算法和虚拟哈希槽等。

范围分片假设数据集是有序,将顺序相临近的数据放在一起,可以很好的支持遍历操作。范围分片的缺点是面对顺序写时,会存在热点。比如日志类型的写入,一般日志的顺序都是和时间相关的,时间是单调递增的,因此写入的热点永远在最后一个分片。

对于关系型的数据库,因为经常性的需要表扫描或者索引扫描,基本上都会使用范围的分片策略。

Redis Cluster 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内,计算公式:slot = CRC16(key) & 16383。每一个节点负责维护一部分槽以及槽所映射的键值数据。

Redis 虚拟槽分区的特点:

  • 解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
  • 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据
  • 支持节点、槽和键之间的映射查询,用于数据路由,在线集群伸缩等场景。

Redis 集群提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以下线部分节点进行缩容。可以说,槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动。

下面我们就先来看一下 Redis 集群伸缩的原理。然后再了解当 Redis 节点数据迁移过程中或者故障恢复时如何保证集群可用。

扩容集群

为了让读者更好的理解上线节点时的扩容操作,我们通过 Redis Cluster 的命令来模拟整个过程。

当一个 Redis 新节点运行并加入现有集群后,我们需要为其迁移槽和数据。首先要为新节点指定槽的迁移计划,确保迁移后每个节点负责相似数量的槽,从而保证这些节点的数据均匀。

1) 首先启动一个 Redis 节点,记为 M4。 
2) 使用 cluster meet 命令,让新 Redis 节点加入到集群中。新节点刚开始都是主节点状态,由于没有负责的>槽,所以不能接受任何读写操作,后续我们就给他迁移槽和填充数据。
3) 对 M4 节点发送 cluster setslot { slot } importing { sourceNodeId } 命令,让目标节点准备导入槽的数据。 >4) 对源节点,也就是 M1,M2,M3 节点发送 cluster setslot { slot } migrating { targetNodeId } 命令,让源节>点准备迁出槽的数据。 
5) 源节点执行 cluster getkeysinslot { slot } { count } 命令,获取 count 个属于槽 { slot } 的键,然后执行步骤>六的操作进行迁移键值数据。
6) 在源节点上执行 migrate { targetNodeIp} " " 0 { timeout } keys { key... } 命令,把获取的键通过 pipeline 机制>批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
7) 重复执行步骤 5 和步骤 6 直到槽下所有的键值数据迁移到目标节点。 
8) 向集群内所有主节点发送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配给目标节点。为了>保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽执行新节点。

收缩集群

收缩节点就是将 Redis 节点下线,整个流程需要如下操作流程。

1) 首先需要确认下线节点是否有负责的槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性。 
2) 当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记改节点后可以正常关闭。

下线节点需要将节点自己负责的槽迁移到其他节点,原理与之前节点扩容的迁移槽过程一致。

迁移完槽后,还需要通知集群内所有节点忘记下线的节点,也就是说让其他节点不再与要下线的节点进行 Gossip 消息交换。

Redis 集群使用 cluster forget { downNodeId } 命令来讲指定的节点加入到禁用列表中,在禁用列表内的节点不再发送 Gossip 消息。

客户端路由

在集群模式下,Redis 节点接收任何键相关命令时首先计算键对应的槽,在根据槽找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点。这个过程称为 MOVED 重定向。

需要注意的是 Redis 计算槽时并非只简单的计算键值内容,当键值内容包括大括号时,则只计算括号内的内容。比如说,key 为 user:{10000}:books时,计算哈希值只计算10000。

MOVED 错误示例显示的信息如下,键 x 所属的哈希槽 3999 ,以及负责处理这个槽的节点的 IP 和端口号 127.0.0.1:6381 。 客户端需要根据这个 IP 和端口号, 向所属的节点重新发送一次 GET 命令请求。

由于请求重定向会增加 IO 开销,这不是 Redis 集群高效的使用方式,而是要使用 Smart 集群客户端。Smart 客户端通过在内部维护 slot 到 Redis 节点的映射关系,本地就可以实现键到节点的查找,从而保证 IO 效率的最大化,而 MOVED 重定向负责协助客户端更新映射关系。

Redis 集群支持在线迁移槽( slot ) 和数据来完成水平伸缩,当 slot 对应的数据从源节点到目标节点迁移过程中,客户端需要做到智能迁移,保证键命令可正常执行。例如当 slot 数据从源节点迁移到目标节点时,期间可能出现一部分数据在源节点,而另一部分在目标节点。

所以,综合上述情况,客户端命令执行流程如下所示:

  • 客户端根据本地 slot 缓存发送命令到源节点,如果存在键对应则直接执行并返回结果给客户端。
  • 如果节点返回 MOVED 错误,更新本地的 slot 到 Redis 节点的映射关系,然后重新发起请求。
  • 如果数据正在迁移中,节点会回复 ASK 重定向异常。格式如下: ( error ) ASK { slot } { targetIP } : { targetPort }

客户端从 ASK 重定向异常提取出目标节点信息,发送 asking 命令到目标节点打开客户端连接标识,再执行键命令。

ASK 和 MOVED 虽然都是对客户端的重定向控制,但是有着本质区别。ASK 重定向说明集群正在进行 slot 数据迁移,客户端无法知道什么时候迁移完成,因此只能是临时性的重定向,客户端不会更新 slot 到 Redis 节点的映射缓存。但是 MOVED 重定向说明键对应的槽已经明确指定到新的节点,因此需要更新 slot 到 Redis 节点的映射缓存。

故障转移

当 Redis 集群内少量节点出现故障时通过自动故障转移保证集群可以正常对外提供服务。

当某一个 Redis 节点客观下线时,Redis 集群会从其从节点中通过选主选出一个替代它,从而保证集群的高可用性。这块内容并不是本文的核心内容,感兴趣的同学可以自己学习。

但是,有一点要注意。默认情况下,当集群 16384 个槽任何一个没有指派到节点时整个集群不可用。执行任何键命令返回 CLUSTERDOWN Hash slot not served 命令。当持有槽的主节点下线时,从故障发现到自动完成转移期间整个集群是不可用状态,对于大多数业务无法忍受这情况,因此建议将参数 cluster-require-full-coverage 配置为 no ,当主节点故障时只影响它负责槽的相关命令执行,不会影响其他主节点的可用性。

Redis Cluster数据分片机制的更多相关文章

  1. 高级开发不得不懂的Redis Cluster数据分片机制

    Redis 集群简介 Redis Cluster 是 Redis 的分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 分布式方面的需求. Redis Cluster 一般由多个节点组 ...

  2. Redis Cluster 数据分片

    介绍 Redis Cluster Redis 集群是 Redis 提供的分布式数据库方案, 集群通过分片(sharding) 来进行数据共享, 并提供复制和故障转移功能. 节点 一个 Redis 集群 ...

  3. Redis Cluster 的数据分片机制

    上一篇<分布式数据缓存中的一致性哈希算法> 文章中讲述了一致性哈希算法的基本原理和实现,今天就以 Redis Cluster 为例,详细讲解一下分布式数据缓存中的数据分片,上线下线时数据迁 ...

  4. redis持久化数据的机制——转发

    转载:https://www.cnblogs.com/xingzc/p/5988080.html Redis提供的持久化机制(RDB和AOF)   Redis提供的持久化机制 Redis是一种面向“k ...

  5. 在 Istio 中实现 Redis 集群的数据分片、读写分离和流量镜像

    Redis 是一个高性能的 key-value 存储系统,被广泛用于微服务架构中.如果我们想要使用 Redis 集群模式提供的高级特性,则需要对客户端代码进行改动,这带来了应用升级和维护的一些困难.利 ...

  6. JuiceFS v1.0 beta3 发布,支持 etcd、Amazon MemoryDB、Redis Cluster

    JuiceFS v1.0 beta3 在元数据引擎方面继续增强,新增 etcd 支持小于 200 万文件的使用场景,相比 Redis 可以提供更好的可用性和安全性.同时支持了 Amazon Memor ...

  7. redis cluster集群部署

    上一篇http://www.cnblogs.com/qinyujie/p/9029153.html,主要讲解了 redis cluster 集群架构 的优势.redis cluster 和 redis ...

  8. redis cluster 集群畅谈(一)

    redis单机在大数据量情况的会出现瓶颈问题,通过redis 主从架构和 哨兵集群结合可以实现99.99% 高可用 .水平扩容支持更高QPS的解决方案. 在大数据量面前,主从架构结合哨兵集群的解决方案 ...

  9. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

随机推荐

  1. git clean解决 GIT error: The following untracked working tree files would be overwritten

    git clean用法:https://www.cnblogs.com/lsgxeva/p/8540476.html :

  2. 使用另一个版本的glibc

    glibc是Linux系统的核心库,稍有不慎就会导致系统崩溃.如果在程序中必须使用另一版本的glibc,则需要小心从事.具体来言,是在编译时指定--rpath和--dynamic-linker,而在运 ...

  3. Go语言系列教程(十二)之函数完结篇

    Hello,各位小伙伴大家好,我是小栈君.上一期我们讲到了关于函数的有参.无参.匿名函数,本期我们分享一下关于go语言函数类型.匿名函数和闭包的概念和实战.闲话不多说,立马开始分享. 在Go语言中,函 ...

  4. 定时删除10天前的Es索引

    说明 主要用在索引名为 xxxx-yyyy.MM.dd 这种,可以自定义修改下边的脚本 删除索引shell 创建 delete_es_indices_over_10_day.sh #!/bin/bas ...

  5. FusionInsight大数据开发---Flume应用开发

    Flume应用开发 要求: 了解Flume应用开发适用场景 掌握Flume应用开发 Flume应用场景Flume的核心是把数据从数据源收集过来,在送到目的地.为了保证输送一定成功,发送到目的地之前,会 ...

  6. SQL系列(二)—— 查询(select)

    在开始之前先了解下SQL中的操作分类.根据与数据库不同操作的交互,对数据不同的处理类型,可以将SQL分为四种:插入.删除.修改.查询.本篇文章中主要介绍查询操作.其实查询操作也是日常应用使用最为频繁且 ...

  7. [更新] Jetbrains IntelliJ IDEA 2019 的许可证密钥

    亲测有效.转载目的:提供一种方法,当然可以看一下原网站的更新及其他方法.转载:[更新] Jetbrains IntelliJ IDEA 2019 的许可证密钥(100%工作),By Gideon    ...

  8. spring boot EnableAutoConfiguration exclude 无效

    本文链接:https://blog.csdn.net/ID19870510/article/details/79373386 首先讲一下SpringBootApplication注解源码定义为 @Ta ...

  9. c#按指定长度分解数组

    在操作数据库时,我们需要注意一点,就是in查询的参数不能超过1000个,否则会报错,所以我们在进行in查询的时候需要对参数数量进行控制: 用于分解数组的扩展方法: /// <summary> ...

  10. Java IO---缓冲流和转换流

    一. 缓冲流 ​ 缓冲流是处理流的一种,也叫高效流,是对4个基本输入输出流的增强,它让输入输出流具有1个缓冲区,能显著减小与外部的IO次数,从而提高读写的效率,并且提供了一些额外的读写方法. ​ 因为 ...