Redis 7.x 系列【27】集群原理之通信机制

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • 1. 概述
    • 2 节点和节点
      • 2.1 集群拓扑
      • 2.2 集群总线协议
      • 2.3 流言协议
      • 2.4 心跳机制
      • 2.5 节点握手
    • 3. 客户端和节点
      • 3.1 RESP 协议
      • 3.2 重定向
        • 3.2.1 MOVED
        • 3.2.2 ASK
        • 3.2.3 客户端重定向处理

1. 概述

官方文档

Redis 集群中,节点负责存储数据,并管理集群的状态,包括将键映射到正确的节点。集群节点还能够自动发现其他节点,检测非工作节点,并在需要时提升副本节点为主节点,以便在发生故障时继续运行。

节点和节点之间,节点和客户端之间,都需要高效安全的通信机制,确保整个集群能如期正常运行。

2 节点和节点

所有集群节点之间都是互相连接的,并使用以下协议进行通信:

  • 集群总线协议:节点之间的连接协议
  • 流言协议(‌Gossip Protocol)‌:传播集群信息,以便发现新节点、发送 Ping 数据包
  • 发布/订阅(Pub/Sub):

2.1 集群拓扑

Redis 集群是一个网状结构,其中每个节点通过 TCP 连接与其他每个节点连接,类似于网络中的网状拓扑结构:

在这里插入图片描述

在一个包含 N 个节点的集群中,每个节点有 N-1 个出站连接和 N-1 个入站连接。这些 TCP 连接始终保持活动状态,不是按需创建的。当一个节点在集群总线上期待收到对 Pong 回复时,在等待足够长时间标记节点为不可达之前,会尝试通过从头重新连接来刷新与节点的连接。

网状拓扑结构具有较高的可靠性,但其结构复杂,实现起来费用较高,不易管理和维护。但是 Redis 节点在正常情况下使用 Gossip 协议和配置更新机制,以避免在节点之间交换过多的消息,因此交换的消息数量不会呈指数增长。

2.2 集群总线协议

节点之间的通信完全通过集群总线集群总线协议进行,集群总线协议是一种二进制协议,仅用于内部集群通信,目前没有相关说明,需要在源码中了解。

该协议需要使用集群总线端口进行连接。每个 Redis 集群节点除了监听 6379 运行端口外,还会开放一个额外的 TCP 端口,用于接收来自其他 Redis 集群节点的连接,该端口的计算方式是将运行端口号加上 10000

例如,如果一个 Redis 节点在 6379 端口上监听客户端连接,并且在 redis.conf 中未添加 cluster-port 参数,那么集群总线端口 16379 将会被打开。

可以通过配置文件中的 cluster-port 参数指定集群总线端口:

cluster-port 20000

在安装集群时,需要注意节点默认使用 6379、16379 两个端口

2.3 流言协议

Gossip Protocol(流言协议)是一种高效的分布式信息交换协议,通过模拟流行病传播的方式,实现了节点间信息的快速传播和同步。其去中心化、可扩展性和容错性强的特点,广泛应用于多个分布式系统。

Redis 集群中的节点,会周期性地随机选择一些节点,通过 Ping 将当前节点的信息传递过去。收到信息的节点,也会使用同样的方式传播自己的节点信息。这个过程会持续进行,直到信息被传播到集群中的每一个节点,每个节点都会保存所有其他节点的信息。

2.4 心跳机制

Redis Cluster 会通过心跳检测迅速感知到节点故障,并且在节点故障时自动进行恢复,以确保数据在集群中的可用性。

Redis 集群节点不断地交换 PingPong 数据包,用于检测其他节点的存活状态。这两种数据包总称为心跳数据包,它们具有相同的结构,并且都携带重要的配置信息。

集群节点发送心跳的几种触发方式:

  • 每秒钟向几个随机节点发送 Ping
  • 尝试重新建立与其他节点的 TCP 连接,以确保节点不会因为当前的 TCP 连接问题而被认为是不可达的
  • 向在 NODE_TIMEOUT 时间内没有发送过 Ping 的节点进行发送

心跳数据包 包含了一些通用的内容信息:

  • 节点 ID : 节点创建时分配的全局唯一标识
  • 当前时期(currentEpoch)和配置时期(configEpoch): 发送节点的当前时期和配置时期字段,用于解决配置冲突和故障转移
  • 节点标识: 标识节点是从节点、主节点或其他节点。
  • 哈希槽位图: 发送节点服务的哈希槽位图,或者如果节点是副本,则为其主节点服务的槽位图。
  • 发送者 TCP 数据端口: Redis 用于接受客户端命令的基本端口(6379)。
  • 集群总线端口: Redis 节点间通信使用的端口。
  • 发送者视角下的集群状态: 表示发送节点对集群状态的视角,可以是“down”或“ok”。

新加如节点时,心跳数据包 还包含一些 Gossip 信息:

  • 新节点 ID
  • 新节点的 IP 地址和端口。
  • 新节点标识。

2.5 节点握手

集群节点之间,始终通过集群总线端口保持连接,新节点加入 Redis Cluster 时,需要与集群中的其他节点进行握手,以获取集群的拓扑信息和状态。节点之间会交换握手消息,确认自身角色(主节点、从节点或未分配节点)和负责的槽分配情况。

节点握手的整个流程如下:

  • 任意主节点(例如 A )上执行 CLUSTER MEET 命令,新节点的 IP 地址(例如 X )和端口号作为参数。
  • AX 进行握手操作,以确认彼此的存在和状态。
  • 其他节点通过 Gossip 发现 X 节点,并完成握手
  • 随着时间的推移,集群中的所有节点都会通过 Gossip 协议知道新节点的存在,并将其纳入集群的元数据中。

Redis Cluster 网状拓扑中加入节点,集群能够自动发现其他节点,最终会自动形成一个完整的链路。这种机制使集群更加健壮,并确保了集群的灵活性和可扩展性。

3. 客户端和节点

3.1 RESP 协议

官方文档

Redis 客户端和服务端之间,通过 RESPRedis Serialization Protocol )协议进行通信,它是一个简单的二进制安全协议。Redis 1.2 引入了 RESP 协议的第一个版本。客户端通过创建到服务器端口的 TCP 连接(默认端口为 6379)连接到 Redis 服务端。

RESP 具有以下优点:

  • 易于实现:协议的设计简洁明了,便于开发者实现。
  • 快速解析:协议格式高效,可以迅速被解析,减少通信延迟。
  • 人类可读:尽管主要用于机器通信,但协议格式也便于人类阅读和理解。

RESP 能够序列化不同的数据类型,包括整数、字符串和数组,并且还具有一个专门用于错误的类型。客户端向 Redis 服务器发送请求时,请求以字符串数组的形式发送,数组的内容包括要执行的命令及其参数。服务器的回复类型取决于具体的命令。

RESP 是二进制安全的,并使用前缀长度来传输大量数据,因此它不需要处理从一个进程传输到另一个进程的大量数据。这种设计使得数据传输更加高效和安全。

RESP仅用于客户端与服务器之间的通信,集群使用不同的二进制协议在节点之间交换消息

3.2 重定向

由于集群节点不能代理请求,因此客户端可能会使用重定向错误( -MOVED-ASK )被重定向到其他节点。

理论上,客户端可以自由地向集群中的所有节点发送请求,并在需要时进行重定向,因此客户端不需要持有集群的状态。但是,缓存键和节点之间映射的客户端可以显著提高性能。

3.2.1 MOVED

集群节点会自动分配哈希槽,节点内部也会维护其他所有节点和哈希槽的映射关系,例如,以下三个主节点:
在这里插入图片描述
Redis 客户端可以随意的向集群中的任意一个节点发送查询命令,例如,在 192.168.56.101:6379 节点上执行插入、查询操作,当前 key 的哈希槽编号为 1180

[root@localhost ~]# redis-cli -a cluster123456 -p 6379
127.0.0.1:6379> set aa bb
127.0.0.1:6379> cluster keyslot aa
(integer) 1180
127.0.0.1:6379> get aa 
bb 

如果在 192.168.56.103:6379 节点上执行查询操作,由于该节点的哈希槽为 5461 - 10922 ,节点检查内部映射表时,发现哈希槽编号为 1180key 不属于该节点管理,会向客户端回复一个 MOVED 错误:

127.0.0.1:6379> get aa 
(error) MOVED 1180 192.168.56.101:6379

MOVED 错误中,包含了 key 的哈希槽编号,以及能够处理该查询的集群节点,客户端需要将查询重新发送到指定的节点。

一般客户端,会自动进行重定向,而且不会单独去请求某一个节点,而是维护了所有节点,并在内部维护了一个哈希槽到节点的映射,对于开发者来说,MOVED 重定向是无感知的。

注意:这里需要使用 redis-cli 工具进行测试,其他工具可能会自动重定向

此外,还可以使用 redis-cli -c 设置自动重定向:

[root@localhost ~]# redis-cli -a cluster123456 -p 6379 -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> get aa
-> Redirected to slot [1180] located at 192.168.56.101:6379
"bb"
3.2.2 ASK

Redis 集群进行伸缩(扩容 / 缩容)时,会进行哈希槽的迁移,当访问目标节点时,数据可能已经迁移到新的节点中,这时会产生 ASK 重定向。

在哈希槽的迁移过程中,槽中对应的多个 Key 是分批次进行移动的,而不是一次性的整体迁移,因此迁移槽中的 Key 一部分在老的服务节点,一部分在新的服务节点。当访问的 Key 正在发生迁移时,ASK 仅指示将下一个查询重定下到指定节点。

MOVED 的区别:

  • MOVED :适用于哈希槽永久由另一个节点服务,接下来的查询应该尝试指定的节点。
  • ASK :适用于哈希槽正在迁移,指示仅将下一个查询发送到指定节点。
3.2.3 客户端重定向处理

为了保持高效处理能力,Redis Cluster客户端会在本地维护当前哈希槽映射表,但是这个映射表需要保持是最新的,当客户端连接到错误的节点导致重定向时,客户端可更新本地的哈希槽映射表。

客户端通常需要在以下两种情况下进行更新:

  • 在启动时初始化映射表
  • 收到 MOVED 重定向

推荐重新获取完整的映射表,而不是更新变动的某一条数据,这样更简单高效。客户端可以通过发出CLUSTER SLOTS命令来获取一个包含哈希槽范围及其对应节点的数组。

示例:

127.0.0.1:7000> cluster slots
1) 1) (integer) 5461 # 哈希槽范围的开始2) (integer) 10922 # 哈希槽范围的结束3) 1) "127.0.0.1"  # 主节点地址端口2) (integer) 70014) 1) "127.0.0.1" # 从节点地址端口2) (integer) 7004
2) 1) (integer) 02) (integer) 54603) 1) "127.0.0.1"2) (integer) 70004) 1) "127.0.0.1"2) (integer) 7003
3) 1) (integer) 109232) (integer) 163833) 1) "127.0.0.1"2) (integer) 70024) 1) "127.0.0.1"2) (integer) 7005

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3269397.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【推研小灶】复旦与南大之间:一次独特的计算机保研之旅

写在前面 上午10点填完志愿等待复试通知,利用这段时间记录一下我简短的夏令营和预推免。今年变为线下之后,部分学校的入营情况、考核方式有明显变化。加上CS方向保研名额总体变多,形势有点小乱,甚至填报系统都在9.29中秋节当天&a…

Python如何获取终端尺寸?

os.get_terminal_size(),无差别获取当前终端长宽,让你为所欲为。 (笔记模板由python脚本于2024年07月27日 08:30:53创建,本篇笔记适合喜欢钻研的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Fre…

【Python系列】Parquet 数据处理与合并:高效数据操作实践

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

unity2D游戏开发08脚本化对象

创建Scriptable Object 在scripts文件夹下创建一个名为Sriptable Objects的文件夹,然后在文件夹里面创建一个名为Item的脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;//[CreateAssetMenu] 是一个属性(Attribute),用于告诉Unity编…

非UI设计师勿入,英文B端界面的确有可取之处.

作为中文的UI设计师,可以从英文B端界面中汲取设计灵感的几种方法: 观察布局和结构: 注意英文B端界面的布局和结构,包括导航栏、侧边栏、内容区域等。观察它们的排列方式、比例和空白间隙的运用,可以借鉴到自己的设计中…

GeoHash原理介绍以及在redis中的应用

GeoHash将二维信息编码成了一个一维信息。降维后有三个好处: 编码后数据长度变短,利于节省存储。利于使用前缀检索当分割的足够细致,能够快速的对双方距离进行快速查询 GeoHash是一种地址编码方法。他能够把二维的空间经纬度数据编码成一个字符串。 1…

十一、【Python】基础教程-【Python全掌握】六大基础数据类型:布尔类型的终极指南

目录 一、基础类型“布尔型”处理方法 1. 直接赋值和使用 2. 布尔值的逻辑运算 3. 条件语句中的布尔值 4. 布尔值转换 5. 短路逻辑 6. 在循环和迭代中的使用 一、基础类型“布尔型”处理方法 在Python中,布尔类型是一种基本的数据类型,用于表示逻…

3DMAX一键藤球建模插件RattanBall使用方法

3DMAX一键藤球建模插件RattanBall使用教程 3DMAX藤球建模插件RattanBall,一键创建藤球模型,可以设置藤球大小、嵌套层数等,简单实用,一键生成! 【适用版本】 3dMax2018.2及更高版本 【安装方法】 3DMAX一键藤球建模插…

Animate软件基础:创建及插入关键帧

这里讲一下Animate软件中创建或插入关键帧的基本方法。 FlashASer:Animate教程及作品源文件https://zhuanlan.zhihu.com/p/677437436 FlashASer:实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer:Animat…

UE5.4内容示例(1)- 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例,可以用此示例熟悉一遍UE5的功能 模型与材质部分 StaticMeshes FBX_Import_Options Material_Advanced Material_Decals Material_Instances Material_N…

SpringBoot教程(十七) | SpringBoot集成swagger

SpringBoot教程(十七) | SpringBoot集成swagger 一、Swagger的简述二、SpringBoot集成swagger21. 引入依赖2. 新建SwaggerConfig配置类当 SpringBoot为2.6.x及以上时 需要注意 3.配置Swagger开关4. 给Controller 添加注解(正式使用&#xff0…

Radxa ROCK 5B+开发板基本配置和上手测试

目录 1.ROCK 5B Plus开发板是什么?2.烧录官方系统3.设置ROOT用户4.开发板温度情况5.VNC远程桌面配置6.WIFI模块测速7.M2接口使用注意8.总结 1.ROCK 5B Plus开发板是什么? ROCK 5B(即ROCK 5B Plus,本文用ROCK 5B指代) …

AMQP-核心概念-4

本文参考以下链接摘录翻译: https://www.rabbitmq.com/tutorials/amqp-concepts 绑定 (Bindings) 绑定是交换机用来将消息路由到队列的规则。为了让一个交换机E将消息路由到队列Q,Q必须绑定到E。绑定可以有一个可选属性routing key,有一些类…

VTX326蓝牙TTS语音合成芯片赋能电子称重一体机人机交互新革新

引言 随着科技的飞速发展,零售业正经历着前所未有的变革。北京宇音天下科技有限公司,作为行业的领跑者,推出了革命性的VTX326蓝牙TTS语音合成芯片,为超市、水果店、熟食店、麻辣烫店等零售业态带来了智能化的全新体验。 市场与趋…

【C语言】文件操作详解!!!

目录 为什么要使用文件? 文件概念 1. 什么是文件? 2. 程序文件 3. 数据文件 4. 文件名 文件的使用 1. 文件指针 2. 文件的打开与关闭 文件的顺序读写 1. 顺序读写函数 2. scanf系列与printf系列 文件的随机读写 1. fseek 2. ftell 3. …

数据结构第二讲:顺序表

数据结构第二讲:顺序表 1.线性表2.什么是顺序表3. 静态顺序表4.动态顺序表4.1顺序表基础4.2顺序表的初始化4.3顺序表的销毁4.4顺序表的尾插4.5顺序表的头插4.6顺序表的尾删4.7顺序表的头删4.8顺序表在指定位置之前插入数据4.9顺序表删除指定位置的数据4.10顺序表查找…

京东发行稳定币的背后

加密市场很热,京东也要来分一杯羹? 7月24日,据财联社报道,京东科技旗下的京东币链科技 ( 香港 ) 将在香港发行与港元 1:1锚定的加密货币稳定币,在市场上掀起广泛热议。 由于众所周知的监管原因,国内大厂在早…

深度学习的前沿主题:GANs、自监督学习和Transformer模型

💎 欢迎大家互三:2的n次方_ 💎1. 介绍 深度学习在人工智能领域中占据了重要地位,特别是生成对抗网络(GANs)、自监督学习和Transformer模型的出现,推动了图像生成、自然语言处理等多个领域的创…

【苍穹】完美解决由于nginx更换端口号导致无法使用Websocket

一、报错信息 进行到websocket开发的过程中,遇到了前端报错,无法连接的提示: 经过F12排查很明显是服务端和客户端并没有连接成功。这里就涉及到之前的坑,现在需要填上了。 二、报错原因和推导 应该还记得刚开苍穹的第一天配置前…