【入门Flink】- 08Flink时间语义和窗口概念
Flink-Windows
是将无限数据切割成有限的“数据块”进行处理,这就是所谓的“窗口”(Window)。
注意
:Flink 中窗口并不是静态准备好的,而是动态创建——当有落在这个窗口区间范围的数据达到时,才创建对应的窗口。【事件驱动
,没有数据到达永远都不会创建窗口】
1)窗口分类
(1)按照驱动类型分
(1)时间窗口
时间窗口以时间点来定义窗口的开始(start)和结束(end)
,截取出的就是某一时间段的数据。
(2)计数窗口
计数窗口基于元素的个数
截取数据,到达固定的个数时就触发计算并关闭窗口。
(2)按照窗口分配数据的规则分类
根据分配数据的规则,窗口的具体实现可以分为 4 类:滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)、会话窗口(Session Window),以及全局窗口(Global Window)。
(1)滚动窗口(Tumbling Windows)
滚动窗口有固定的大小,是一种对数据进行“均匀切片”的划分方式。窗口之间没有重叠,也不会有间隔
,是
“首尾相接”
的状态。这是最简单的窗口形式,每个数据都会被分配到一个窗口,而且只会属于一个窗口
。
滚动窗口应用非常广泛,可以对每个时间段做聚合统计
,很多BI分析指标都可以用它来实现。
(2)滑动窗口(Sliding Windows)
滑动窗口的大小也是固定的。但是窗口之间并不是首尾相接的
,而是可以“错开”一定的位置。定义滑动窗口的参数有两个:除去窗口大小(window size)
之外,还有一个“滑动步长”
(window slide),它其实就代表了窗口计算的频率。窗口在结束时间触发计算输出结果,那么滑动步长就代表了计算频率
。
滚动窗口也可以看作是一种特殊的滑动窗口
一一窗口大小等于滑动步长(size=slide)
滑动窗口适合计算结果更新频率非常高
的场景。
(3)会话窗口(Session Windows)
会话窗口,是基于“会话”(session)来来对数据进行分组的
。会话窗口只能基于时间来定义。
会话窗口中,最重要的参数就是会话的超时时间
,也就是两个会话窗口之间的最小距离
。如果相邻两个数据到
来的时间间隔(gap)小于指定的大小(size),那说明还在保持会话,它们就属于同一个窗口;如果gap大于size,
那么新来的数据就应该属于新的会话窗口,而前一个窗口就应该关闭了。
会话窗口之间一定是不会重叠
的,而且会留有至少为size的间隔(session)
在一些类似保持会话的场景下
,可以使用会话窗口来进行数据的处理统计。
(4)全局窗口(Global Windows)
“全局窗口”,这种窗口全局有效,会把相同key的所有数据都分配到同一个窗口中。这种窗口没有结束的时侯, 默认是不会做触发计算的
,如果希望它能对数据进行计算处理,还需要自定义“触发器”(Trigger)。
2)窗口 API
(1)按键分区(Keyed)和非按键分区(Non-Keyed)
(1)按键分区窗口(Keyed Windows)
经过按键分区 keyBy 操作后,数据流会按照 key 被分为多条逻辑流(logical streams),这就是 KeyedStream。
stream.keyBy(...)
.window(...)
(2)非按键分区(Non-Keyed Windows)
如果没有进行 keyBy,那么原始的 DataStream 就不会分成多条逻辑流。这时窗口逻辑只能在一个任务(task)上执行,就相当于并行度变成了 1。
stream.windowAll(...)
注意:对于非按键分区的窗口操作,手动调大窗口算子的并行度也是无效的
,windowAll本身就是一个非并行的操作。
(2)窗口分配器(Window Assigners)和窗口函数(WindowFunctions)
stream.keyBy(<key selector>)
.window(<window assigner>)
.aggregate(<window function>)
窗口分配器
(1)时间窗口
滚动处理时间窗口
stream.keyBy(...)
.window(TumblingProcessingTimeWindows.of(Time.seconds(5))).aggregate(...)
.of()还有一个重载方法,可以传入两个 Time 类型的参数:size 和offset。第一个参数当然还是窗口大小,第二个参数则表示窗口起始点的偏移量。
滑动处理时间窗口
stream.keyBy(...)
.window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
.aggregate(...)
滑动窗口同样可以追加第三个参数,用于指定窗口起始点的偏移量,用法与滚动窗口完全一致。
处理时间会话窗口
stream.keyBy(...)
.window(ProcessingTimeSessionWindows.withGap(Time.seconds(10)))
.aggregate(...)
还可以调用 withDynamicGap()方法定义 session gap 的动态提取逻辑。
滚动事件时间窗口
stream.keyBy(...)
.window(TumblingEventTimeWindows.of(Time.seconds(5))).aggregate(...)
滑动事件时间窗口
stream.keyBy(...)
.window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))
.aggregate(...)
事件时间会话窗口
stream.keyBy(...)
.window(EventTimeSessionWindows.withGap(Time.seconds(10))).aggregate(...)
(2)计数窗口
滚动计数窗口
stream.keyBy(...)
.countWindow(10)
滑动计数窗口
stream.keyBy(...)
.countWindow(10, 3)
全局窗口
stream.keyBy(...)
.window(GlobalWindows.create());
注意:使用全局窗口,必须自行定义触发器才能实现窗口计算
,否则起不到任何作用。
窗口函数
(1)增量聚合函数(ReduceFunction / AggregateFunction)
归约函数(ReduceFunction)
类似Reduce算子,只不过固定时间才会输出
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);DataStreamSource<String> stream = env.socketTextStream("124.222.253.33", 7777);stream.map(new WaterSensorMapFunction()).keyBy(WaterSensor::getId)// 设置滚动事件时间窗口.window(TumblingProcessingTimeWindows.of(Time.seconds(10))).reduce(new ReduceFunction<WaterSensor>() {@Overridepublic WaterSensor reduce(WaterSensor value1, WaterSensor value2) throws Exception {System.out.println("调用reduce 方法,之前的结果:" + value1 + ",现在来的数据:" + value2);return new WaterSensor(value1.getId(), System.currentTimeMillis(), value1.getVc() + value2.getVc());}}).print();env.execute();
聚合函数(AggregateFunction)
ReduceFunction
可以解决大多数归约聚合的问题,但是这个接口有一个限制,就是聚合状态的类型、输出结果的类型都必须和输入数据类型一样
。
有三种类型:输入类型(IN)、累加器类型(ACC)和输出类型(OUT)。
输入类型IN 就是输入流中元素的数据类型;累加器类型 ACC 是进行聚合的中间状态类型;而输出类型OUT是最终计算结果的类型。
接口中有四个方法:
- createAccumulator():创建一个累加器,为聚合创建了一个初始状态,每个聚合任务只会调用一次。
- add():将输入的元素添加到累加器中。
- getResult():从累加器中提取聚合的输出结果。
- merge():合并两个累加器,并将合并后的状态作为一个累加器返回。
AggregateFunction 的工作原理
:首先调用createAccumulator()为任务初始化一个状态(累加器);而后每来一个数据就调用一次 add()方法,对数据进行聚合,得到的结果保存在状态中;等到了窗口需要输出时,再调用 getResult()方法得到计算结果。很明显,与 ReduceFunction 相同,AggregateFunction 也是增量式的聚合;而由于输入、中间状态、输出的类型可以不同,使得应用更加灵活方便。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);SingleOutputStreamOperator<WaterSensor> sensorDS = env.socketTextStream("124.222.253.33", 7777).map(new WaterSensorMapFunction());KeyedStream<WaterSensor, String> sensorKS = sensorDS.keyBy(WaterSensor::getId);WindowedStream<WaterSensor, String, TimeWindow> sensorWS = sensorKS.window(TumblingProcessingTimeWindows.of(Time.seconds(10)));SingleOutputStreamOperator<String> aggregate = sensorWS.aggregate(new AggregateFunction<WaterSensor, Integer, String>() {@Overridepublic Integer createAccumulator() {System.out.println("创建累加器");return 0;}@Overridepublic Integer add(WaterSensor value, Integer accumulator) {System.out.println(" 调用add方法,value=" + value);return accumulator + value.getVc();}@Overridepublic String getResult(Integer accumulator) {System.out.println("调用getResult方法");return accumulator.toString();}@Overridepublic Integer merge(Integer a, Integer b) {System.out.println("调用merge方法");return null;}});aggregate.print();env.execute();
(2)全窗口函数(full window functions)
基于全部的数据计算
全窗口函数有两种:WindowFunction
和 ProcessWindowFunction
。
窗口函数(WindowFunction)
基于 WindowedStream 调用.apply()方法,传入一个 WindowFunction 的实现类。
stream
.keyBy(<key selector>)
.window(<window assigner>)
.apply(new MyWindowFunction());
该类中可以获取到包含窗口所有数据的可迭代集合(Iterable),还可以拿到窗口(Window)本身的信息。
不过 WindowFunction 能提供的上下文信息较少,也没有更高级的功能。事实上,它的作用可以被 ProcessWindowFunction 全覆盖
,所以之后可能会逐渐弃用
。
处理窗口函数(ProcessWindowFunction)
ProcessWindowFunction 还可以获取到一个“上下文对象”(Context)。上下文对象非常强大,不仅能够获取窗口信息,还可以访问当前的时间和状态信息。
时间就包括了处理时间(processing time)和事件时间水位线(event time watermark)。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);SingleOutputStreamOperator<WaterSensor> sensorDS = env.socketTextStream("124.222.253.33", 7777).map(new WaterSensorMapFunction());KeyedStream<WaterSensor, String> sensorKS = sensorDS.keyBy(WaterSensor::getId);WindowedStream<WaterSensor, String, TimeWindow> sensorWS = sensorKS.window(TumblingProcessingTimeWindows.of(Time.seconds(10)));SingleOutputStreamOperator<String> process = sensorWS.process(new ProcessWindowFunction<WaterSensor,String, String, TimeWindow>() {@Overridepublic void process(String s, Context context, Iterable<WaterSensor> elements, Collector<String> out) throws Exception {long count = elements.spliterator().estimateSize();long windowStartTs = context.window().getStart();long windowEndTs = context.window().getEnd();String windowStart = DateFormatUtils.format(windowStartTs, "yyyy-MM-dd HH:mm:ss.SSS");String windowEnd = DateFormatUtils.format(windowEndTs, "yyyy-MM-dd HH:mm:ss.SSS");out.collect("key=" + s + "的窗口[" + windowStart + "," + windowEnd + ") 包含 " + count + " 条数据===>" + elements);}});process.print();env.execute();
增量聚合和全窗口函数结合使用
// ReduceFunction 与 WindowFunction 结合
public <R> SingleOutputStreamOperator<R> reduce(
ReduceFunction<T> reduceFunction,WindowFunction<T,R,K,W>function)
// ReduceFunction 与 ProcessWindowFunction 结合
public <R> SingleOutputStreamOperator<R> reduce(
ReduceFunction<T> reduceFunction,ProcessWindowFunction<T,R,K,W> function)// AggregateFunction 与 WindowFunction 结合
public <ACC,V,R> SingleOutputStreamOperator<R> aggregate(AggregateFunction<T,ACC,V> aggFunction,WindowFunction<V,R,K,W> windowFunction)
// AggregateFunction 与 ProcessWindowFunction 结合
public <ACC,V,R> SingleOutputStreamOperator<R> aggregate(AggregateFunction<T,ACC,V> aggFunction,
ProcessWindowFunction<V,R,K,W>
结合使用
public class WindowAggregateAndProcessDemo {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);SingleOutputStreamOperator<WaterSensor> sensorDS = env.socketTextStream("124.222.253.33", 7777).map(new WaterSensorMapFunction());KeyedStream<WaterSensor, String> sensorKS = sensorDS.keyBy(sensor -> sensor.getId());WindowedStream<WaterSensor, String, TimeWindow> sensorWS = sensorKS.window(TumblingProcessingTimeWindows.of(Time.seconds(10)));// 2. 窗口函数:/*增量聚合 Aggregate + 全窗口 process1、增量聚合函数处理数据: 来一条计算一条2、窗口触发时, 增量聚合的结果(只有一条)传递给全窗口函数3、经过全窗口函数的处理包装后,输出结合两者的优点:1、增量聚合: 来一条计算一条,存储中间的计算结果,占用的空间少2、全窗口函数: 可以通过 上下文 实现灵活的功能*/// sensorWS.reduce() //也可以传两个SingleOutputStreamOperator<String> result = sensorWS.aggregate(new MyAgg(),new MyProcess());result.print();env.execute();}public static class MyAgg implements AggregateFunction<WaterSensor, Integer, String> {@Overridepublic Integer createAccumulator() {System.out.println("创建累加器");return 0;}@Overridepublic Integer add(WaterSensor value, Integer accumulator) {System.out.println("调用 add 方法,value=" + value);return accumulator + value.getVc();}@Overridepublic String getResult(Integer accumulator) {System.out.println("调用 getResult 方法");return accumulator.toString();}@Overridepublic Integer merge(Integer a, Integer b) {System.out.println("调用 merge 方法");return null;}}// 全窗口函数的输入类型 = 增量聚合函数的输出类型public static class MyProcess extends ProcessWindowFunction<String, String, String, TimeWindow> {@Overridepublic void process(String s, Context context, Iterable<String> elements, Collector<String> out) throws Exception {long startTs = context.window().getStart();long endTs = context.window().getEnd();String windowStart = DateFormatUtils.format(startTs, "yyyy-MM-dd HH:mm:ss.SSS");String windowEnd = DateFormatUtils.format(endTs, "yyyyMM-dd HH:mm:ss.SSS");long count = elements.spliterator().estimateSize();out.collect("key=" + s + "的窗口[" + windowStart + "," + windowEnd + ")包含" + count + "条数据===>" + elements);}}
}
Flink-Time
Event Time
:事件时间,一个是数据产生的时间(时间戳Timestamp)Processing time
:处理时间,数据真正被处理的时间
事件时间在实际应用中更为广泛,从Flink 1.12版本开始,Flink已经将事件时间作为默认的时间语义
。
相关文章:

【入门Flink】- 08Flink时间语义和窗口概念
Flink-Windows 是将无限数据切割成有限的“数据块”进行处理,这就是所谓的“窗口”(Window)。 注意:Flink 中窗口并不是静态准备好的,而是动态创建——当有落在这个窗口区间范围的数据达到时,才创建对应的窗…...
【 OpenGauss源码学习 —— 列存储(CStore)(六)】
列存储(CStore)(六) 概述CStore::GetCUDataFromRemote 函数CStore::CheckConsistenceOfCUDescCtl 函数CStore::CheckConsistenceOfCUDesc 函数CStore::CheckConsistenceOfCUData 函数额外补充 声明:本文的部分内容参考…...

MUYUCMS v2.1:一款开源、轻量级的内容管理系统基于Thinkphp开发
MuYuCMS:一款基于Thinkphp开发的轻量级开源内容管理系统,为企业、个人站长提供快速建站解决方案。它具有以下的环境要求: 支持系统:Windows/Linux/Mac WEB服务器:Apache/Nginx/ISS PHP版本:php > 5.6 (…...

SDL2 显示文字
1.简介 SDL本身没有显示文字功能,它需要用扩展库SDL_ttf来显示文字。ttf是True Type Font的缩写,ttf是Windows下的缺省字体,它有美观,放大缩小不变形的优点,因此广泛应用很多场合。 使用ttf库的第一件事要从Windows的…...
c++ future 使用详解
c future 使用详解 std::future 头文件 #include <future>。 类模板,定义如下: template<class T> class future; template<class T> class future<T&>; template<> class future<void>;作用ÿ…...
好用的C C++ 日志宏 OutputDebugStringA 写到文件或界面
日志宏 #include <cstdio> #define OUTPUT_DEBUG_STRING(fmt, ...) do { \char szOutMsgFinal[10240] {0}; \std::snprintf(szOutMsgFinal, sizeof(szOutMsgFinal), "[%s|%d] " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \OutputDebugString…...

如何在ModelScope社区魔搭下载所需的模型
本篇文章介绍如何在ModelScope社区下载所需的模型。 若您需要在ModelScope平台上有感兴趣的模型并希望能下载至本地,则ModelScope提供了多种下载模型的方式。 使用Library下载模型 若该模型已集成至ModelScope的Library中,则您只需要几行代码即可加载…...

NLP在网安领域中的应用(初级)
NLP在网安领域的应用 写在最前面1. 威胁情报分析1.1 社交媒体情报分析(后面有详细叙述)1.2 暗网监测与威胁漏洞挖掘 2. 恶意软件检测2.1 威胁预测与趋势分析 3. 漏洞管理和响应4. 社交工程攻击识别4.1 情感分析与实时监测4.2 实体识别与攻击者画像构建4.…...
03.UDP套接字与原始套接字
UDP套接字 注意在UDP套接字中,要使用recvfrom和sendto API: recvfrom: 接收数据包,并存储源地址(UDP) 函数原型: int WSAAPI recvfrom([in] SOCKET s,[out] char *buf,[in] int len,[...

「NLP+网安」相关顶级会议期刊 投稿注意事项+会议等级+DDL+提交格式
「NLP网安」相关顶级会议&期刊投稿注意事项 写在最前面一、会议ACL (The Annual Meeting of the Association for Computational Linguistics)IH&MMSec (The ACM Workshop on Information Hiding, Multimedia and Security)CCS (The ACM Conference on Computer and Co…...

Python开源项目RestoreFormer(++)——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践
有关 Python 和 Anaconda 及 RestoreFormer 运行环境的安装与设置请参阅: Python开源项目CodeFormer——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践https://blog.csdn.net/beijinghorn/article/details/134…...
设计模式 -- 命令模式(Command Pattern)
命令模式:一种数据驱动的设计模式也属于行为型模式,请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。你认为是命令的地方都可以使用…...

【数据分享】2021-2023年我国主要城市逐月轨道交通运营数据
以地铁为代表的轨道交通是大城市居民的主要交通出行方式之一,轨道交通的建设和运营情况也是一个城市发展水平的重要体现。本次我们为大家带来的是2021-2023年我国主要城市的逐月的轨道交通运营数据! 数据指标包括:运营线路条数(条…...
大数据-之LibrA数据库系统告警处理(ALM-12034 周期备份任务失败)
告警解释 周期备份任务执行失败,则上报该告警,如果下次备份执行成功,则恢复告警。 告警属性 告警ID 告警级别 可自动清除 12034 严重 是 告警参数 参数名称 参数含义 ServiceName 产生告警的服务名称。 RoleName 产生告警的角色…...
tx-前端笔试题记录
目录 目录 1.你最熟悉的前端框架是什么说说你对它的理解。 2.请简单实现一下js对象深度拷贝。 3.CSS 有几种方法实现垂直水平居中?请简要写一下。 4.这段程序执行之后控制台会打印什么内容? 5.下列程序的输出结果是多少?为什么? 6.有ABCDE 五个火车站,单向…...

详解Redis持久化(上篇——RDB持久化)
Redis持久化的作用和意义 Redis 持久化是一种机制,用于将内存中的数据写入磁盘,以保证数据在服务器重启时不会丢失。持久化是为了解决内存数据库(如 Redis)在服务器关闭后,数据丢失的问题。 Redis 持久化的主要作用和…...
爬虫常见风控
一.ip风控 单位时间内接口访问频率。 二.设备指纹风控 设备注册时候设备特征是否完整,信息主要包含硬件、网络、系统三部分。 硬件属性:设备品牌、型号、IMEI(国际移动设备识别码)、处理器、内存、分辨率、亮度、摄像头、电池、…...

华为ensp:边缘端口并启动BUDU保护
如上图前提是三个交换机都做了rstp,则在边缘的地方做 边缘端口并启动BUDU保护,也就是我用绿色圈出来的地方 边缘1 进入交换机的系统视图 interface e0/0/3 进入接口 stp edged-port enable quit 再退回系统视图 stp bpdu-protection 这样就可以了…...
分布式id生成数据库号段算法的golang实现
分布式id生成数据库号段算法的golang实现 介绍项目结构使用说明核心流程说明1. 定义id生成器结构体2. id生成器共有Monitor,GetOne, Close三个对外暴露的方法。3. 数据表结构 参与贡献 介绍 项目地址:gitee;github 本项目主要利用go语言(go1…...

【算法 | 模拟No.4】AcWing 756. 蛇形矩阵 AcWing 40. 顺时针打印矩阵
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程&a…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...