`
IXHONG
  • 浏览: 450199 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Redis Cluster 原理

阅读更多

 一、CLUSTER MEET 命令的实现

    通过向节点 A 发送 CLUSTER MEET 命令,客户端可以让接收命令的节点 A 将另一个节点 B 添加到节点 A 当前所在的集群里面:

    CLUSTER MEET <ip> <port>

    收到命令的节点 A 将与节点 B 进行握手(handshake),以此来确认彼此的存在,并为将来的进一步通信打好基础:

    1)节点 A 会为节点 B 创建一个 clusterNode 结构,并将该结构添加到自己的 clusterState.nodes 字典里面。

    2)之后,节点 A 将根据 CLUSTER MEET 命令给定的 IP 地址和端口号,向节点 B 发送一条 MEET 消息。

    3)如果一切顺利,节点 B 将接收到节点 A 发送的 MEET 消息,节点 B 会为节点 A 创建一个 clusterNode 结构,并将该结构添加到自己的 clusterState.nodes 字典里面。

    4)之后,节点 B 将向节点 A 返回一条 PONG 消息。

    5)如果一切顺利,节点 A 将收到节点 B 返回的 PONG 消息,通过这条 PONG 消息节点 A 可以知道节点 B 已经成功地接收到了自己发送的 MEET 消息。

    6)之后,节点 A 将向节点 B 返回一条 PING 消息。

    7)如果一切顺利,节点 B 将接收到节点 A 返回的 PING 消息,通过这条 PING 消息节点 B 可以知道节点 A 已经成功地接收到了自己返回的 PONG 消息,握手完成。

    之后,节点 A 会将节点 B 的信息通过 Gossip 协议传播给集群中的其他节点,让其他节点也与节点 B 进行握手,最终,经过一段时间后,节点 B 会被集群中的所有节点认识。

 

二、槽指派

    Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽(slot),数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。

    当数据库中的16384个槽都有节点在处理时,集群处于上线状态(ok);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。

    通过向节点发送CLUSTER ADDSLOTS命令,可以将一个或多个槽指派(assign)给节点负责:

    CLUSTER ADDSLOTS <slot> [slot . . .]

    127.0.0.1:7000> CLUSTER ADDSLOTS 0 1 2 3 4 . . . 5000

    OK

 

    127.0.0.1:7000> CLUSTER INFO

    cluster_state:ok

 

    clusterNode的slots属性和numslot属性记录了节点负责处理哪些槽:

    struct clusterNode {

        // ...

        unsigned char slots[16384/8];

        int numslots;

        // ...

    };

    slots属性是一个二进制位数组(bit array),这个数组的长度为2048个字节,共包含16384个二进制位。如果slots数组在索引i上的二进制位的值为1,那么表示节点负责处理槽i,为0表示不负责。

 

    一个节点除了会将自己负责处理的槽记录在clusterNode结构的slots属性和numslots属性之外,它还会将自己的slots数组通过消息发送给集群中的其他节点,以此来告诉其他节点自己目前负责处理哪些槽。

 

    clusterState结构中的slots数组记录了集群中所有16384个槽的指派信息:

    typedef struct clusterState {

        // ...

        clusterNode *slots[16384]; // 每个数组项指向一个clusterNode

        // ...

    } clusterState;  

    

三、在集群中执行命令

    在对数据库中的16384个槽都进行了指派之后,集群就会进入上线状态,这时客户端就可以向集群中的节点发送数据命令了。

    当客户端向节点发送与数据库键有关的命令时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己:

    如果指派给了当前节点,节点直接执行这个命令。否则,节点会向客户端返回一个MOVED错误,指引客户端转向(redirect)至正确的节点,并再次发送之前想要执行的命令。

    计算键属于那个槽:

    def slot_number(key):

        return CRC16(key) & 16383

    // CRC-16校验和

    判断槽i是否由当前节点负责处理:

    clusterState.slots[i] == clusterState.myself

 

    一个集群客户端通常会与集群中的多个节点创建套接字连接,而所谓的节点转向实际上就是换一个套接字来发送命令。

    节点和单机服务器在数据库方面的一个区别是,节点只能使用0号数据库。

 

四、重新分片

    Redis集群的重新分片操作可以将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所属的键值对也会从源节点移动到目标节点。(这里的重新分片不是rehash,请注意与客户端一致性hash分片区分开来)

    重新分片操作可以在线进行,在重新分片过程中,集群不需要下线,并且源节点和目标节点都可以继续处理命令请求。

    重新分片操作由Redis的集群管理软件redis-trib负责执行,redis提供了进行重新分片所需的所有命令,而redis-trib则通过想源节点和目标节点发送命令来进行重新分片操作。

    redis-trib对集群的单个槽slot进行重新分片的步骤如下:

    1)redis-trib对目标节点发送CLUSTER SETSLOT <slot> IMPORTING <source_id>命令,让目标节点准备好从源节点导入(import)属于槽slot的键值对。

    2)redis-trib对源节点发送CLUSTER SETSLOT <slot> MIGRATING <target_id>命令,让源节点准备好将属于槽slot的键值对迁移(migrate)至目标节点。

    3)redis-trib向源节点发送CLUSTER GETKEYSINSLOT <slot> <count>命令,获得最多count个属于槽slot的键值对的键名。

    4)对于步骤3获得的每个键名,redis-trib都向源节点发送一个MIGRATE <target_ip> <target_port> <key_name> 0 <timeout>命令,将被选中的键原子地从源节点迁移至目标节点。

    5)重复执行步骤3和步骤4,直到源节点保存的所有属于槽slot的键值对都被迁移至目标节点为止。

    6)redis-trib向集群中的任意一个节点发送CLUSTER SETSLOT <slot> NODE <target_id>命令,将槽slot指派给目标节点,这一指派信息会通过消息发送至整个集群,最终集群中的所有节点都会知道槽slot已经被指派给了目标节点。

    ASK错误:

    在进行重新分片期间,源节点向目标节点迁移一个槽的过程中,可能会出现这样一种情况:属于被迁移槽的一部分键值对保存在源节点里面,而另一部分键值对则保存在目标节点里面。

    当客户端向源节点发送一个与数据库键有关的命令,并且命令要处理的数据库键恰好就属于正在被迁移的槽时:

    源节点会先在自己的数据库里面查找指定的键,如果找到的话,就直接执行客户端发送的命令。没找到的话,那么这个键有可能已经被迁移到了目标节点,源节点将向客户端返回一个ASK错误,指引客户端转向正在导入槽的目标节点,并再次发送之前想要执行的命令。

 

五、复制与故障转移

    Redis集群中的节点分为主节点(master)和从节点(slave),其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制的主节点下线时,代替下线主节点继续处理命令请求。

    设置从节点 CLUSTER REPLICATE <node_id>

    故障检测:

    集群中的每个节点都会定期地向集群中的其他节点发送PING消息,以此来检测对方是否在线,如果接收PING消息的节点没有在规定的时间内返回PONG消息,那么发送PING消息的节点就会将接收PING消息的节点标记为疑似下线(probable fail, PFAIL)。

    如果在一个集群里面,半数以上负责处理槽的节点都将某个主节点x报告为疑似下线,那么这个主节点x将被标记为已下线(FAIL),将x标记为FAIL的节点会向集群广播一条关于x的FAIL消息,所有收到这条FAIL消息的节点都会立即将x标记为FAIL。

    故障转移:

    当一个从节点发现自己正在复制的主节点进入FAIL状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:

    1)复制下线主节点的所有从节点里面,会有一个从节点被选中。

    2)被选中的从节点会执行SLAVEOF no one命令,称为新的主节点。

    3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。

    4)新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。

    5)新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。

    选举新的主节点:

    1)集群的配置纪元是一个自增计数器,它的初始值为0.

    2)当集群里的某个节点开始一次故障转移操作时,集群配置纪元的值会被增一。

    3)对于每个配置纪元,集群里每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的从节点将获得主节点的投票。

    4)档从节点发现自己正在复制的主节点进入已下线状态时,从节点会想集群广播一条CLUSTER_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有接收到这条消息、并且具有投票权的主节点向这个从节点投票。

    5)如果一个主节点具有投票权(它正在负责处理槽),并且这个主节点尚未投票给其他从节点,那么主节点将向要求投票的从节点返回一条CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示这个主节点支持从节点成为新的主节点。

    6)每个参与选举的从节点都会接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,并根据自己收到了多少条这种消息来同济自己获得了多少主节点的支持。

    7)如果集群里有N个具有投票权的主节点,那么当一个从节点收集到大于等于N/2+1张支持票时,这个从节点就会当选为新的主节点。

    8)因为在每一个配置纪元里面,每个具有投票权的主节点只能投一次票,所以如果有N个主节点进行投票,那么具有大于等于N/2+1张支持票的从节点只会有一个,这确保了新的主节点只会有一个。

    9)如果在一个配置纪元里面没有从节点能收集到足够多的支持票,那么集群进入一个新的配置纪元,并再次进行选举,知道选出新的主节点为止。

    这个选举新主节点的方法和选举领头Sentinel的方法非常相似,因为两者都是基于Raft算法的领头选举方法来实现的。

1
0
分享到:
评论

相关推荐

    Redis Cluster的实现机制和原理

    ### Redis Cluster 的实现机制与原理 #### 集群的核心目标与特性 Redis Cluster 是 Redis 数据库的一个分布式版本,旨在解决单个 Redis 实例在处理大量数据和高并发请求时的局限性。其核心目标包括: 1. **高性能...

    rediscluster.rar

    本文将详细介绍Redis Cluster的工作原理、配置、使用以及与MySQL数据库的配合。 **一、Redis Cluster概述** Redis Cluster是一个无中心架构的分布式系统,每个节点都是平等的,它们共同维护整个数据集。通过数据分...

    RedisCluster集群(Spring访问Redis)

    本文将详细介绍RedisCluster集群的架构及原理,并探讨如何通过Spring Data Redis模块实现对Redis Cluster的访问。 ### 1. RedisCluster集群概述 Redis Cluster是Redis官方提供的分布式解决方案,它将数据分片到多...

    25_你能聊聊redis cluster集群模式的原理吗?.zip

    在Java开发中,了解和掌握Redis Cluster的原理和使用方法对于构建高效、稳定的分布式系统至关重要。 一、Redis Cluster的节点通信机制 Redis Cluster中的每个节点都维护着全量的节点信息,包括其他节点的IP地址、...

    redis_cluster实战栗子.rar

    Redis Cluster是Redis官方提供的分布式解决方案,它通过将数据分片(sharding)到多个节点来...通过本实战栗子的学习,你不仅可以了解其工作原理,还能掌握实际操作技巧,从而在实际工作中有效地应用Redis Cluster。

    Redis-Cluster20161110

    【Redis-Cluster20161110】是一个关于Redis集群的资料包,发布于2016年11月10日。这个压缩包包含了一些用于启动和管理Redis集群的工具,以及Redis服务器的安装文件。让我们深入探讨Redis Cluster及其相关知识点。 *...

    03-Redis Cluster集群运维与核心原理剖析.zip

    本资料包包含了对Redis Cluster的运维实践和核心原理的深入剖析,旨在帮助读者理解并掌握如何有效地部署、管理和优化Redis Cluster。 1. **Redis Cluster的分片机制** Redis Cluster采用一致性哈希(Consistent ...

    Windows环境Redis-Cluster配置

    在Windows环境中配置Redis-Cluster,首先需要理解其基本概念和工作原理,然后按照步骤进行安装和配置。 一、Redis-Cluster基础知识 1. 分片(Sharding):Redis-Cluster通过将数据分割成多个片段(slots),并将...

    redis sentinel与redis cluster 集群配置

    Redis Sentinel和Redis Cluster是两种常见的Redis集群解决方案,用于提高Redis数据库的可用性和可扩展性。在本篇文章中,我们将深入探讨这两个系统的工作原理、配置步骤以及它们各自的特点。 首先,让我们了解一下...

    RedisCluster集群搭建代码及相应软件

    总结,本压缩包提供的资源使你能够在本地快速搭建一个简单的RedisCluster测试环境,了解其工作原理和操作方式。在实际生产环境中,你需要考虑网络配置、持久化策略、故障转移机制等更复杂的因素。

    【Redis】Redis Cluster-集群故障转移.doc

    下面将详细介绍 Redis Cluster 集群故障转移机制的工作原理。 集群故障转移机制 Redis Cluster 集群故障转移机制主要通过集群定时任务 clusterCron 来实现。clusterCron 会遍历集群中的节点,对每个节点进行检查,...

    redis-cluster.tar.gz

    Redis 是一个高性能的键值数据库,常用于数据缓存、消息队列以及数据库等功能。...通过深入理解 Redis Cluster 的工作原理和使用方法,你可以更好地优化和利用 Redis 在大数据量场景下的性能优势。

    Redis核心原理与应用实践.docx

    2. Redis Cluster:Redis Cluster 是 Redis 官方提供的集群解决方案,能够提供高可用性和高性能的服务。 Redis 源码分析 Redis 的源码分析是指对 Redis 的源代码进行深入的分析和研究,了解 Redis 的内部实现机制...

    redis-cluster开箱即用作者已经实验

    Redis Cluster是Redis官方提供的分布式解决方案,它通过分片(sharding)技术将数据分散存储在多个节点上,实现了数据的高可用性和...在使用过程中,确保熟悉Redis Cluster的工作原理和限制,以便更好地优化你的应用。

    redis-cluster-5.0.7.tar.gz

    理解Redis Cluster的工作原理和配置细节对于成功部署和管理高可用的Redis服务至关重要。通过深入学习和实践,你将能够充分利用Redis Cluster的强大功能,为你的应用提供高效、可靠的内存数据存储。

    redis cluster集群

    Redis Cluster是Redis官方提供的分布式解决方案,它通过分片(Sharding)...理解其工作原理和部署细节,是充分发挥Redis Cluster优势的关键。在实际应用中,还需要考虑监控、备份、安全等方面,以确保系统的稳定运行。

    Redis Cluster的图文讲解

    【Redis Cluster简介】 Redis Cluster是Redis官方提供的分布式集群解决方案,自Redis 3.0版本开始引入。它旨在解决单个Redis...了解和掌握Redis Cluster的原理和操作,对于构建可扩展、高可用的Redis应用至关重要。

    Redis Cluster集群数据分片机制原理

    Redis Cluster 是 Redis 为应对大规模数据存储需求而推出的分布式解决方案,自 3.0 版本开始引入。Redis Cluster 集群通过数据分片(Sharding)技术实现了数据的分布式存储,允许用户水平扩展存储能力,同时保持高...

Global site tag (gtag.js) - Google Analytics