Redis核心技术与实战【学习笔记】 - 27.限制Redis Cluster规模的因素(通信开销)

简述

Redis Cluster 能保存的数据量以及支撑的吞吐量,跟集群实例规模相关。 Redis 官方给出了 Redis Cluster 的规模上线,就是一个集群运行 1000 个实例。

其实,限定 Redis Cluster 集群规模的一个关键因素就是,实例间的通信开销会随着实例规模的增加而增大,在集群超过一定规模时(比如 800 节点),集群吞吐量反而会下降。所以,集群的实际规模会受到限制。


1.实例间通信方法和对集群规模的影响

Redis Cluster 在运行时,每个实例上都会保存 Slot 和实例的对应关系(也就是 Slot 映射表),以及自身的状态信息。

为了让集群中的每个实例都知道所有实例的状态信息,实例之间会按照一定的规则进行通信。这个规则就是 Gossip 协议。

Gossip 协议的工作原理可以概括成两点:

  • 一是,每个实例之间会按照一定的频率,从集群中挑选一些实例,把 PING 消息发送给挑选出来的实例,用来检测这些实例是否在线,并交换彼此的状态信息。PING 消息中封装了发送消息的的实例自身状态信息部分其他实例的状态信息以及 Slot 映射表
  • 二是,一个实例在接受到 PING 消息后,会给发送 PING 消息的实例,发送一个 PONG 消息。PONG 消息的内容和 PING 消息的内容一样。

在这里插入图片描述

Gossip 协议可以保证在一段时间后,集群中的每一个实例都能获得其他所有实例的状态信息。

这样,即使有新节点加入、节点故障、Slot 变更等时间发生,实例间也可以通过 PING 、PONG 消息的传递,完成集群状态在每个实例上的同步。

经过刚刚的分析,我们知道,实例间使用 Gossip 协议进行通信,通信的开销受到通信消息大小通信频率这两方的影响。

消息越大、频率越高,相应的通信开销就越大。如果想要实现高效的通信,可以从这两方面入手去调优。

2.Gossip 消息大小

Redis 实例发送的 PING 消息的消息体是由 dusterMsgDataGossip 结构体组成的,这个结构体的定义如下所示:

typedef struct {char nodename[CLUSTER_NAMELEN]; //40字节uint32_t ping_sent; //4字节uint32_t pong_received; //4字节char ip[NET_IP_STR_LEN]; //46字节uint16_t port; //2字节uint16_t cport; //2字节uint16_t flags; //2字节uint32_t notused1; //4字节
} dusterMsgDataGossip 

其中,CLUSTER_NAMELEN 和 NET_IP_STR_LEN 的值分别是 40 和 46,分别表示 nodename 和 ip 这两个字节数组的长度是 40 字节和 46 字节,我们在把结构体中其他信息的大小加起来,就可以得到一个 Gossip 消息的大小了,104 字节

每个实例在发送一个 Gossip 消息时,除了会传递自身的状态信息,默认会还会传递集群十分之一实例的状态信息

所以,对于一个包含了 1000 个实例的集群来说,每个实例发送一个 PING 消息时,会包含 100 个实例的状态信息,总的数据量是 10400 字节,再加上实例自身的信息,一个 Gossip 消息大约 10KB

此外,为了让 Slot 映射表能够在不同实例间传播,PING 消息中还带有一个长度为 16384 bit 的 Bitmap,这个 Bitmap 的每一位对应了一个 Slot,如果某位为 1 ,表示这个 Slot 属于当前实例。这个 Bitmap 大小换算成字节后,是 2KB 。我们把实例状态信息和 Slot 分配信息相加,就可以得到一个 PING 消息的大小了,大约是 12KB

PONG 消息和 PING 消息的内容一样,所以,它的大小约是 12KB。每个实例发送了 PING 消息后,还会收到 PONG 消息,两个消息加起来有 24KB

虽然从绝对值上来看,24KB 并不算大,但是,如果实例正常处理的单个请求只有几 KB 的话,那么,实例为了维护集群状态一致传输的 PING/PONG 消息,就要比单个业务请求大了。而且,每个实例都会给其他实例发送 PING/PONG 消息。随着集群规模增加,这些心跳消息的数量也会越多,会占据一部分集群的网络通信带宽,进而会降低集群服务正常客户端请求的吞吐量。

除了心跳信息大小会影响到通信开销,如果实例间通信非常频繁,也会导致集群网络带宽被频繁占用。那么,Redis Cluster 中实例的通信频率是什么样的呢?

3.实例间通信频率

Redis Cluster 的实例启动后,默认会每秒从本地的实例表中随机选出 5 个实例,再从这 5 个实例中找出一个最久没有通信的实例,把 PING 消息发送给该实例。这是周期性发送 PING 消息的基本做法。

但是,这里有一个问题:实例被选出来的这个最久没有通信的实例,毕竟是从随机选出的 5 个实例中挑选的,这并不能保证这个实例就一定是真个集群中最久没有通信的实例。

所以,这可能会出现,有些实例一直没有被发送 PING 消息,导致它们维护的集群状态已经过期了

为了避免这种情况,Redis Cluster 的实例会按照每 100ms 一次的频率,扫描本地的实例列表,如果发现有实例最近一次接受 PONG 消息的时间,已经大于配置项 cluster-node-timeout 的一半了(cluster-node-timeout / 2),就会立刻给该实例发送 PING 消息,更新这个实例上的集群状态信息

在集群规模扩大之后,因为网络拥塞或是不同服务器间的流量竞争,会导致实例间的网络通信延迟增加。如果有部分实例无法收到其他实例发送的 PONG 消息,就会引起实例之间频繁的发送 PING 消息,这又会对集群网络通信带来额外的开销了。

我们来总结下单实例每秒发送的 PING 消息数量,如下所示:

PING 消息发送数量 = 1 + 10*实例数(最近一次接受 PONG 消息的时间超出 cluster-node-timeout / 2)

  • 1 是指单实例常规按照每 1 秒发送一个 PING 消息
  • 10 是指每 1 秒内实例会执行 10 次检查,每次检查后会给 PONG 消息超时的实例发送消息。

借助一个例子,分析下在这种通信频率下,PING 消息占用集群带宽的情况。

假设单个实例检测发现,每 100 毫米有 10 个实例的 PONG 消息接受超时,那么,这个实例每秒就会发送 101 (101 = 1 + 10*10)个 PING 消息,越占 1.2MB/s 带宽。如果集群中有 30 个实例按照这种频率发送消息,就会占用 36 MB/s 带宽,这会挤占集群中用于服务正常请求的带宽。

4.如何降低实例间的通信开销

为了降低实例间的通信开销,从原理上说,我们可以减小实例传出的消息大小(PING/PONG 消息、Slot 分配信息),但是因为集群实例依赖 PING、PONG 消息和 Slot 分配信息,来维持集群状态的统一,一旦减小了传递的消息大小,就会导致实例间的通信信息减少,不利于集群维护,所以,我们不能采用这种方式。

经过刚才的学习,我们现在知道,实例间发送消息的频率有两个:

  • 每个实例每 1 秒发送一条 PING 消息。这个频率不算高,如果再降低该频率的话,集群中各实例的状态可能就没有办法及时传播了。
  • 每个实例每 100 毫秒会做一次检查,给 PONG 消息接收超过 cluster-node-timeout / 2 的节点发送 PING 消息。实例按照每 100 毫秒进行检测的频率,是 Redis 默认的周期性检查任务的统一频率,我们一般不需要修改它。

那么,就只有修改 cluster-node-timeout 这个配置项了。

配置项 cluster-node-timeout 定义了集群实例被判断为故障的心跳超时时间,默认是 15 秒。如果 cluster-node-timeout 值比较小,那么,在大规模集群中,就会比较频繁地出现 PONG 消息接收超时的情况,从而导致实例每秒要执行 10 次“给 PONG 下消息超时的实例发送 PING 消息” 这个操作。

所以,为了避免过多的心跳消息挤占集群带宽,我们可以调大 cluster-node-timeout 的值,比如说调大到 20 秒或 25 秒。这样一来,PONG 消息接收超时的情况就会有所缓解,单实例也不用频繁地每秒 执行 10 次心跳发送操作了。

当然,我们也不要把 cluster-node-timeout 调的太大,否则,如果实例真的发生故障了,我们就需要等待 cluster-node-timeout 时长后,才能检测出故障,这又会导致实际的故障恢复时间被延长,会影响到集群服务的正常使用。

为了验证调整 cluster-node-timeout 值后,是否能减少心跳消息占用的带宽,给你一个小建议:你可以在调整 cluster-node-timeout 值的前后,使用 tcpdump 命令转去实例发送心跳信息网络包的情况

tcpdump host 127.0.0.1 port 7001 -i 网卡名 -w /tmp/r1.cap

通过分析网络包的数量和大小,可以判断调整 cluster-node-timeout 值前后,心跳消息占用的带宽情况了。

5.小结

Redis Cluster 实例间以 Gossip 协议进行通信。Redis Cluster 运行时,各实例需要通过 PING 、PONG 消息进行信息交换,这些心跳信息包括了当前实例和部分其他实例的状态信息,以及 Slot 分配信息。这种通信机制有助于 Redis Cluster 中的所有实例都拥有完成的集群状态信息。

但是,随着集群规模的增加,实例间的通信量也会增加。如果我们盲目地对 Redis Cluster 进行扩容,就可能会遇到集群性能变慢的情况。这是因为,集群中大规模的实例间心跳消息会挤占集群处理正常请求的带宽。而且,有些实例可能因为网络拥塞导致无法及时收到 PONG 消息,每个实例在运行时会周期性地(每秒 10 次)检测是否有这种情况发生,一旦发生,就会立即给这些 PONG 消息超时的实例发送心跳信息。集群规模越大,网络拥塞的概率就越高,相应的,PONG 消息超时的发生概率就越高,这就会导致集群中有大量的心跳消息,影响集群服务的正常请求。

虽然,我们可以通过调整 cluster-node-timeout 配置项减少心跳消息占用带宽情况,但是,在实际应用中,如果不是特别需要大容量集群,我建议你把 Redis Cluster 的规模控制在 400~500 个实例。

假设单个实例每秒支撑 8 万请求操作(8 万 QPS),每个主实例配置一个从实例,那么 400~500 个实例可支撑 1600 万 ~ 2000 万 QPS(200/250 个主实例 * 8 万 QPS = 1600/2000 万 QPS),这个吞吐量性能可以满足不少业务应用的需求。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue源码系列讲解——虚拟DOM篇【三】(更新子节点)

1. 前言 在上一篇文章中,我们了解了Vue中的patch过程,即DOM-Diff算法。并且知道了在patch过程中基本会干三件事,分别是:创建节点,删除节点和更新节点。创建节点和删除节点都比较简单,而更新节点因为要处理…

12个最常用的matplotlib图例 !!

文章目录 1、折线图 2、散点图 3、直方图 4、柱状图 5、箱线图 6、热力图 7、饼图 8、面积图 9、等高线图 10、3D图 11、时间序列图 12、树状图 总结 1、折线图 折线图(Line Plot):用于显示数据随时间或其他连续变量的变化趋势。在实际项目中…

【Linux驱动】块设备驱动(三)—— 块设备读写(不使用请求队列)

并非每种块设备都会用到请求队列,从上节可以知道,请求队列的作用是管理和调用IO请求,那么反过来想,如果IO请求较少,那就可以无需使用请求队列。在以下情况中,可以不使用请求队列。 单任务环境: 当系统中只有…

VRRP配置

目录 网络拓扑图 配置要求 配置步骤 网络拓扑图 配置要求 按照图示配置 IP 地址和网关在 SW1,SW2,SW3 上创建 Vlan10 和 Vlan20,对应 IP 网段如图,交换机之间链路允许所有 VLAN 通过在 SW1 和 SW2 上配置 VRRP,要求…

在windows server2016部署域控服务器DC

1.正常配置vmware虚拟机基础环境 2.启动虚拟机,会先到efi network,等待几分钟 3.进入boot manager,选择启动方式,记得提示CD启动的时候需要按回车,不然又会回到这个界面 4.选择安装版本为桌面版(开始直接…

无题2024

念旧 阿悠悠 专辑:念旧 发行时间 2019-08-25 念旧 播报编辑讨论1上传视频 阿悠悠演唱歌曲 《念旧》是由一博作词,一博和张池作曲,阿悠悠演唱的歌曲,发行于2019年8月25日。 [1]收录于同名专辑《念旧》中。 相关星图 查…

(四)elasticsearch 源码之索引流程分析

https://www.cnblogs.com/darcy-yuan/p/17024341.html 1.概览 前面我们讨论了es是如何启动,本文研究下es是如何索引文档的。 下面是启动流程图,我们按照流程图的顺序依次描述。 其中主要类的关系如下: 2. 索引流程 (primary) 我们用postman发送请求&…

Windows Server 2025 Hyper-V 新变化

今天简单跟大家聊聊Windows Server 2025 Hyper-V一些新功能新变化,具体如下: 在 VM 之间共享 GPU 随着图形处理器的重要性日益增加,特别是由于它们在 AI 应用程序中的核心作用,Hyper-V 中对 GPU 的现有支持已不再足够。到目前为…

[Java][算法 哈希]Day 01---LeetCode 热题 100---01~03

LeetCode 热题 100---01~03 ------->哈希 第一题 两数之和 思路 最直接的理解就是 找出两个数的和等于目标数 这两个数可以相同 但是不能是同一个数字(从数组上理解就是内存上不是同一位置) 解法一:暴力法 暴力解万物 按照需求 …

报错ValueError: Unknown CUDA arch (8.6) or GPU not supported

文章目录 问题描述解决方案参考文献 问题描述 报错 ValueError: Unknown CUDA arch (8.6) or GPU not supported 本人显卡为 RTX 3060,CUDA 为 10.2,PyTorch 为 1.5 解决方案 修改 C:\Users\Administrator\Envs\test\Lib\site-packages\torch\utils\c…

【PyQt】08 - 编辑Tab顺序

文章目录 前言一、Tab顺序二、编辑Tab顺序总结 前言 介绍了什么是Tab顺序,以及如何修改Tab顺序。 一、Tab顺序 当你的界面设计好之后,在输入栏按住Tab按键,他会按照你摆放的顺序一次转跳 二、编辑Tab顺序 方法一 然后鼠标左击就可以改变…

前端JavaScript篇之对this对象的理解

目录 对this对象的理解1. 函数调用模式:2. 方法调用模式:3. 构造器调用模式:4. apply、call和bind调用模式: 对this对象的理解 在JavaScript中,this关键字是一个非常重要的概念,它用于指向当前执行上下文中…

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View 0.论文摘要 多视图聚合有望克服多目标检测和跟踪中的遮挡和漏检挑战。多视图检测和3D对象检测中的最新方法通过将所有视图投影到地平面并在鸟瞰视图(BEV)中执…

面试经典150题 -- 栈(总结)

总的链接 面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台 关于栈 -- stack 的学习链接 c的STL中的栈 -- stack-CSDN博客 20 . 有效的括号 这题直接用栈模拟就好了; 这里用一种取巧的方法 , 当遇见左括号,加入右…

JAVA设计模式之建造者模式详解

建造者模式 1 建造者模式介绍 建造者模式 (builder pattern), 也被称为生成器模式 , 是一种创建型设计模式. 定义: 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。 **建造者模式要解决的问题 ** 建造者模式可以将部件和其组装过程分开…

Dynamo批量处理多个Revit文件?

Hello大家好!我是九哥~ 最近很多小伙伴都在咨询Dynamo如何批量处理多个Revit文件,之前写过一篇《Dynamo批量修改多文件项目基点参数》,利用的是后台打开Revit的方式,可以实现一些批量操作的功能。 但是这个方法,对于一…

物理信息神经网络(PINN): 将物理知识融合到深度学习中

物理信息神经网络(PINN): 将物理知识融合到深度学习中 物理信息神经网络(PINN)简介PINN的工作原理PINN模型如何利用物理法则指导模型训练1. 定义物理问题和相应的物理定律2. 构建神经网络3. 定义损失函数数据误差项 (Data-fidelit…

IoC原理

Spring框架的IOC是基于Java反射机制实现的,那具体怎么实现的,下面研究一下 反射 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法…

多 split 窗口 in Gtkmm4

文章目录 效果预览实现概要源代码 效果预览 实现概要 使用Gtk::Paned虽然 Paned 只能装两个子控件, 但是我可以嵌套 paned1 装 box1 和 box2 paned2 装 paned1 和 box3 源代码 #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public:ExampleWindow()…

大模型基础架构的变革:剖析Transformer的挑战者(下)

上一篇文章中&#xff0c;我们介绍了UniRepLKNet、StripedHyena、PanGu-π等有可能会替代Transformer的模型架构&#xff0c;这一篇文章我们将要介绍另外三个有可能会替代Transformer的模型架构&#xff0c;它们分别是StreamingLLM、SeTformer、Lightning Attention-2&#xff…