当前位置: 首页 > news >正文

Redis集群模式之Redis Cluster(1)

        在前面的文章中我们介绍了什么是主从复制模式和哨兵模式,这两种模式虽然可以使用读写分离策略对读的并发性进行扩展,但是写能力和存储能力无法得到有效的扩展,只能是主节点服务器单服务器的性能上限。如果面对海量数据的存储,就要构建主节点之间的集群,同时要兼具上面两种模式的优点,也就是每个主节点必须有自己的从节点来进行数据冗余存储,这就是Redis Cluster模式。

Redis Cluster主要模块介绍

哈希槽(Hash Slot)

        Redis Cluster没有使用一致性Hash,而是引入了哈希槽的概念。Redis Cluster中有16384(2^14)个哈希槽,每个key通过CRC16校验后对16383取模来决定放置到哪个槽。Cluster中的每个节点负责一部分Hash槽。

        假设集群中存在3个主节点,则可能按照以下数量进行哈希槽的分配:

        主节点1负责0~5400号的哈希槽,主节点2负责5401~10800号的哈希槽,主节点3负责10801~16383号的哈希槽。

Keys Hash Tags

        Hash Tags提供了一种途径,用来将多个相关的key分配到相同的哈希槽中,这是Redis Cluster中实现multi-key操作的基础。

        Hash Tag规则如下,如果满足如下规则,那么“{”和“}”之间的字符将用来计算Hash Slot,以保证这样的key储存在同一个哈希槽中。规则如下:

        (1)key包含一个“{”字符;

        (2)并且如果在这个“{”字符的右边还有一个“}”字符;

        (3)并且如果在“{”和“}”字符之间存在至少一个字符。

        举个例子:

        {id888}.a和{id888}.b这两个key会被存放在同一个哈希槽中,因为哈希值在计算时只考虑“{}”内的值。如果不满足上面的三条规则,则不会启用Hash Tags。

Cluster Nodes属性

        每个节点在Cluster中有一个唯一的名字。这个名字由160bit随机十六进制数字表示,并在节点启动时第一次获得(通常通过/dev/urandom)。节点在配置文件中保留他的ID,并永远使用这个ID,直到被管理员使用CLUSTER RESET HARD命令hard reset这个节点。

        节点ID被用来在整个Cluster中标识每个节点。一个节点可以修改自己的IP地址而不需要修改自己的ID。Cluster可以检测到IP/port的改动并通过运行在Cluster Bus上的gossip协议重新配置该节点。

        节点ID并不是唯一与节点绑定的信息,但是他是唯一的一个总是保持全局一致的字段。每个节点都拥有一系列相关的信息。一些信息是关于本节点在集群中配置的细节,并最终在Cluster内部保持一致。而其他信息,比如节点最后被ping的时间,是节点的本地信息。

        每个节点维护着集群内其他节点的以下信息:节点id、节点的IP和Port、节点标签,主节点id(表明该节点为从节点),最后被挂起的ping的发送时间(如果没有挂起的ping则为0),最后一次收到pong的时间,当前的节点configuration epoch,链接状态,以及最后是该节点服务的哈希槽。

        对节点字段更详细的描述,可以参考对命令CLUSTER NODES的描述。

Cluster总线

        每个Redis Cluster节点有一个额外的TCP端口用来接受其他节点的连接。这个端口与用来接收Client命令的普通TCP端口有一个固定的offset。该端口等于普通命令端口+10000。

        节点到节点的通信只使用集群总线,同时使用集群总线协议:有不同的类型和大小的帧组成的二进制协议。

集群拓扑

        Redis Cluster是一张全网拓扑,节点与其他每个节点之间都保持着TCP连接。在一个拥有N个节点的集群中,每个节点由N-1个TCP传出连接,和N-1个TCP传入连接。这些TCP连接总是保持活性。当一个节点在集群总线上发送了ping请求并期待对方回复pong,如果没有得到回复,在等待足够长时间以便将对方标记为不可达之前,它将先尝试重新连接对方以刷新与对方的连接。而在全网拓扑中的Redis Cluster节点,节点使用gossip协议和配置更新机制来避免在正常情况下节点之间交换过多的消息,因此集群内交换的消息数目(相对节点数目)不是指数级的。

节点握手

        节点总是接受集群总线端口的连接,并且总是会回复ping请求,即使ping来自一个不可信节点。然而,如果发送节点被认为不是当前集群的一部分,那么其他包将被抛弃。

        节点认定其他节点是当前集群的一部分有两种方式:

        (1)如果一个节点出现在一条MEET消息中。一条meet消息非常像一个ping消息,但是它会强制接收者接收一个节点作为集群的一部分。节点只有在接收到系统管理员的CLUSTER MEET ip port命令,才会向其他节点发送MEET消息。

        (2)如果一个被信任的节点gossip了某个节点,那么接收到gossip消息的节点也会将那个节点标记为集群的一部分。也就是说,如果在集群中,A知道B,B知道C,B发送gossip消息到A,告诉A:C是集群的一部分。这时,A会把C注册为网络的一部分,并尝试与C建立连接。

        这就意味着,一旦我们把某个节点加入了连接图,它们最终会自动形成一张全连接图。这意味着只要系统管理员强制加入一条信任关系,集群可以自动发现发现其他节点。

请求重定向

        Redis Cluster采用去中心化的架构,集群的主节点各自负责一部分哈希槽,客户端如何确定key到底会映射到哪个节点上呢?这就是下面我们要介绍的请求重定向。

        在Cluster模式下,节点对请求的处理过程如下:

        (1)检查当前key是否存在当前的节点下(通过CRC16校验后取模,得到对应的Slot值;查询该Slot值负责的节点,得到节点指针;将得到的指针与自身进行比较);

        (2)如果Slot不是自身负责的,则返回MOVED重定向;        

        (3)如果Slot是自身负责的,并且key在Slot中,则返回该key对应的结果;

        (4)如果key不在此Slot中,检查该Slot是否正在迁出(MIGRATING);

        (5)如果key正在迁出,返回ASK错误,重定向客户端到迁移的目的服务器上;

        (6)如果Slot未迁出,检查Slot是否导入中;

        (7)如果Slot导入中且有ASKING标记,则直接操作;

        (8)否则返回MOVED重定向。

        我们来讲解一下什么是MOVED重定向和ASK重定向。

MOVED重定向

        

        MOVED具体的流程如下:

        (1)客户端发送键命令给任意节点;

        (2)任意节点对键进行Slot值的计算并得到对应节点的指针;

        (3)接着判断得到的指针是否指向自身,并判断是否槽命中。如果是,则执行命令,如果不是,则返回MOVED重定向命令给客户端。

        (4)客户端根据重定向重新发送键命令到对应节点。

        槽命中:指的是所找的键在当前节点负责的哈希槽中可以找到。

ASK重定向

        ASK重定向发生于集群伸缩(集群中节点数量扩充或缩减)时,集群伸缩会导致哈希槽的迁移,当我们去源节点访问时,此时的数据可能已经迁移到了目标节点,使用ASK重定向来解决此问题。

Smart客户端

        上述两种重定向机制使得客户端的实现更加复杂,通过Smart客户端(Jedis Cluster)来减低复杂性,追求更好的性能。客户端内部负责计算/维护键\rightarrow\rightarrow节点的映射,用于快速定位目标节点。具体的实现原理如下:

        (1)从集群中选取一个可运行节点,使用Cluster Slots得到槽和节点的映射关系。

        (2)将上述映射关系储存到本地,通过映射关系就可以直接对目标节点进行操作(CRC16(key)\rightarrowSlot\rightarrowNode),很好地避免了MOVED重定向,并且为每个节点创建Jedis Pool。

        至此,客户端就可以用来命令操作了,具体的流程图如下:

        

        本篇文章我们主要介绍了Redis Cluster要解决的问题、Redis Cluster中的一些基本概念和Redis Cluster中的重定向机制,大家有什么问题或者勘误可以在评论区留言,笔者看到都会回复的。

相关文章:

  • 推荐一个 github加速器
  • 【深度学习-Day 27】模型调优利器:掌握早停、数据增强与批量归一化
  • 体育赛事直播平台需要有哪些数据?
  • Python第八周作业
  • windows下载postman后安装失败,提示installation has failed,解决方案亲测有效
  • C# 动态管理控件和事件,批量查询管理同类控件
  • 通信网络编程2.0——JAVA
  • ES集群的故障转移
  • 工厂模式demo
  • qemu-guest-agent详解
  • Python训练营-Day29-复习日
  • 应对人口老龄化:智慧养老驱动高质量发展新范式
  • 遍历对象属性,for...in和Object.keys到底用哪个?
  • 网络安全之RCE简单分析
  • C#事件基础模型代码
  • Java面试避坑指南:牛客网最新高频考点+答案详解
  • Verilog基础:$timeformat系统任务的使用
  • 火山引擎扣子的具体作用
  • docker 02网络
  • Java从入门到精通 - 面向对象高级(一)
  • 镇江教育云平台网站建设/seo优化的搜索排名影响因素主要有
  • 如何上传自己做的网站/竞价推广课程
  • 少儿编程入门教学/百度自然搜索排名优化
  • cms网站后台管理系统/外贸seo推广
  • 深圳市做网站的有那些公司/北京it培训机构哪家好
  • 谷歌网站统计/查询网站