Flink 窗口触发器(Trigger)(二)

Flink 窗口触发器(Trigger)(一)
Flink 窗口触发器(Trigger)(二)

Apache Flink 是一个开源流处理框架,用于处理无界和有界数据流。在 Flink 的时间窗口操作中,触发器(Trigger)是一个非常重要的概念,它决定了窗口何时应该被计算并输出结果。触发器定义了窗口何时准备好被处理(即何时触发计算)的条件。
窗口类型

  • 时间窗口(Time Windows):基于时间划分的窗口,如滚动时间窗口(Tumbling Time Windows)和滑动时间窗口(Sliding Time Windows)。
  • 事件时间窗口(Event Time Windows):基于事件时间戳的窗口,它可以处理乱序数据。

Trigger

触发器用于定义窗口何时准备好进行计算的条件。Flink 提供了一些内置的触发器,同时允许用户根据需要自定义触发器。

内置触发器

  • ProcessingTimeTrigger:基于处理时间的触发器,每当达到指定的时间间隔时触发。
  • EventTimeTrigger:基于事件时间的触发器,当窗口的结束时间到达时触发。这适用于处理有序或乱序的事件时间数据流。
  • CountTrigger:基于元素数量的触发器,当窗口中的元素数量达到指定阈值时触发。

自定义触发器

用户可以通过实现 Trigger 接口来创建自定义触发器。自定义触发器可以基于复杂的逻辑来决定何时触发窗口的计算。自定义触发器通常需要实现以下几个方法:

  • onElement(element, timestamp, window, ctx): 当元素被添加到窗口时调用。
  • onEventTime(time, window, ctx, out): 当窗口的事件时间到达时调用。
  • onProcessingTime(time, window, ctx, out): 当窗口的处理时间到达时调用。
  • onMerge(other): 当两个窗口合并时调用(例如,在会话窗口中使用)。
  • canMerge(): 表示触发器是否支持窗口合并。

作用

  • 触发器的主要作用是控制窗口的计算时机,使得 Flink 的窗口操作更加灵活和强大。通过选择合适的触发器,可以优化流处理应用的性能和资源利用率。

示例

以下是一个使用 Flink 窗口和触发器的简单示例(假设使用 Java API):

DataStream<Tuple2<String, Integer>> dataStream = ...;  dataStream  .keyBy(value -> value.f0)  .window(TumblingEventTimeWindows.of(Time.seconds(10)))  .trigger(ContinuousEventTimeTrigger.of(Time.seconds(5))) // 自定义触发间隔  .sum(1)  .print();

在这个示例中,使用了基于事件时间的滚动窗口,但自定义了触发间隔为 5 秒,这意味着每 5 秒,即使窗口没有结束,也会触发一次计算。

注意:ContinuousEventTimeTrigger 并不是 Flink 的一个内置触发器,这里只是为了说明如何可能自定义触发器行为。实际上,可能需要实现自己的 Trigger 逻辑或使用现有的内置触发器。

触发器

EventTimeTrigger

EventTimeTrigger 是一个基于事件时间的触发器,它通常用于事件时间窗口(如滚动时间窗口、滑动时间窗口或会话窗口)。当窗口的结束时间(对于滚动窗口和滑动窗口)或窗口的“活动”结束时间(对于会话窗口)根据事件时间戳到达时,EventTimeTrigger 会触发窗口的计算。
下面是一个使用 TumblingEventTimeWindows 的示例,它隐式地使用了事件时间触发器:

DataStream<Tuple2<String, Integer>> input = ...; // 输入数据流  // 假设已经设置了TimeCharacteristic为EventTime,并且数据流中的元素有事件时间戳  
input  .assignTimestampsAndWatermarks(...) // 设置时间戳和水印  .keyBy(value -> value.f0) // 根据键进行分组  .window(TumblingEventTimeWindows.of(Time.seconds(10))) // 定义10秒滚动事件时间窗口  .sum(1) // 对窗口内的元素进行求和  .print(); // 输出结果

TumblingEventTimeWindows.of(Time.seconds(10)) 创建了一个 10 秒的滚动事件时间窗口。由于我们使用了事件时间窗口,Flink 会自动使用基于事件时间的触发逻辑来触发窗口的计算。当窗口的结束时间(基于事件时间戳)到达时,窗口会被计算并输出结果。

ProcessingTimeTrigger

ProcessingTimeTrigger 是一种基于处理时间(Processing Time)的触发器。处理时间是指事件被 Flink 系统处理的时间,即事件到达 Flink 算子并被处理的时间。由于处理时间是由 Flink 系统的内部时钟决定的,因此它不受事件本身时间戳的影响,也不依赖于任何外部时间服务。
用途:
ProcessingTimeTrigger 通常用于那些对实时性要求很高,但不需要严格事件时间语义的场景。例如,可能希望每秒计算一次窗口内的数据聚合,而不关心事件的实际发生时间。
在 Flink 中,可以通过指定窗口的触发器来使用 ProcessingTimeTrigger。以下是一个简单的示例,展示了如何为 Flink DataStream API 中的时间窗口指定 ProcessingTimeTrigger:

import org.apache.flink.streaming.api.datastream.DataStream;  
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows;  
import org.apache.flink.streaming.api.windowing.time.Time;  
import org.apache.flink.streaming.api.windowing.triggers.ProcessingTimeTrigger;  DataStream<Tuple2<String, Long>> input = ...; // 你的输入数据流  // 使用 ProcessingTimeTrigger 定义一个每秒触发的滚动窗口  
DataStream<Tuple2<String, Long>> result = input  .keyBy(0) // 假设第一个字段是键  .window(TumblingProcessingTimeWindows.of(Time.seconds(1))) // 指定窗口大小  .trigger(ProcessingTimeTrigger.create()) // 使用 ProcessingTimeTrigger  .sum(1); // 对第二个字段(假设是 Long 类型)进行求和  // 输出结果  
result.print();

在这个例子中,没有显式地调用 .trigger(ProcessingTimeTrigger.create()),因为 TumblingProcessingTimeWindows 已经默认使用了 ProcessingTimeTrigger。但是,了解如何显式地指定触发器是有用的,特别是在需要自定义触发器行为时。

注意事项

  • 使用处理时间时,请注意 Flink 集群内部时钟的同步问题。虽然 Flink 在大多数情况下能够很好地处理时钟不同步的问题,但在某些极端情况下,时钟差异可能会影响处理时间的准确性。
  • 处理时间不会考虑事件的实际时间戳,因此它不适合需要严格时间顺序或事件时间语义的场景。

CountTrigger

CountTrigger 是一种基于数据量的触发器,它根据窗口内收集到的元素数量来决定是否触发窗口的计算。当窗口内的元素数量达到预设的阈值时,CountTrigger 会触发窗口的计算操作。
工作原理:
CountTrigger 内部通常使用一个计数器来跟踪窗口内元素的数量。每当有元素被添加到窗口中时,计数器就会增加。一旦计数器的值达到或超过预设的阈值,CountTrigger 就会触发窗口的计算,并可以选择性地清除窗口内的数据或状态,以便进行下一轮的计算。
使用:
在 Flink 的 DataStream API 中,可以通过调用窗口操作的 .trigger() 方法来指定 CountTrigger。但是,需要注意的是,Flink 的内置 API 可能并不直接提供一个名为 CountTrigger 的类(尽管存在类似的功能),但可以通过自定义触发器或使用 Flink 提供的窗口分配器和触发器组合来达到类似的效果。
然而,Flink 的 CountWindow 默认就是基于计数触发的,不需要显式地指定 CountTrigger。但如果想要更细粒度的控制,比如与其他类型的触发器(如时间触发器)结合使用,可能需要自定义触发器或查找 Flink 社区提供的扩展库。

以下是一个假设性的示例,展示了如何在 Flink 中使用类似于 CountTrigger 的逻辑(注意:这并非 Flink API 的直接调用方式,而是为了说明概念):

// 假设 Flink API 提供了类似的方法,但实际上可能需要自定义或查找扩展库  
DataStream<Tuple2<String, Integer>> input = ...; // 输入数据流  // 使用一个假设的 countWindow 方法,它内部可能使用了 CountTrigger  
DataStream<Integer> sum = input  .keyBy(0) // 假设第一个字段是键  .countWindow(10) // 假设这是一个接受计数阈值的窗口方法  .sum(1); // 对第二个字段进行求和  sum.print(); // 输出结果

然而,在 Flink 的实际 API 中,可能会使用类似 countWindow(Time.seconds(x)) 的方法来定义一个固定时间间隔内的计数窗口,但这并不是基于元素数量的直接触发。如果需要基于元素数量的触发,可能需要使用 GlobalWindows 并结合自定义触发器,或者简单地使用 countWindow(如果 Flink 版本中直接支持该方法)并接受它默认的计数触发行为。

ContinuousEventTimeTrigger

根据间隔时间周期性触发窗口或者当 Window 的结束时间小于当前的 watermark 时触发窗口计算。

ContinuousEventTimeTrigger.of(Duration.ofSeconds(3))

ContinuousProcessingTimeTrigger

ContinuousProcessingTimeTrigger 是一种基于处理时间的触发器,它允许根据设定的时间间隔周期性地触发窗口计算,而不仅仅是在窗口结束时触发。这种触发器特别适用于需要更频繁地获取窗口内数据聚合结果的场景。
原理:
ContinuousProcessingTimeTrigger 通过在窗口内设置定时器来实现周期性触发。每当有新的元素到达窗口时,触发器会检查是否需要触发计算。如果需要,它会根据当前时间和设定的时间间隔来更新定时器,并在适当的时候触发窗口计算。
使用方法:
在Flink的DataStream API中,可以通过调用窗口操作的.trigger()方法,并传入ContinuousProcessingTimeTrigger.of(Time.seconds(interval))(其中interval是希望触发的时间间隔,以秒为单位)来指定ContinuousProcessingTimeTrigger。

以下是一个使用ContinuousProcessingTimeTrigger的示例代码片段(假设已经有了一个Flink环境env和一个数据流sourceStream):

import org.apache.flink.streaming.api.datastream.DataStream;  
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows;  
import org.apache.flink.streaming.api.windowing.time.Time;  
import org.apache.flink.streaming.api.windowing.triggers.ContinuousProcessingTimeTrigger;  DataStream<String> sourceStream = ...; // 输入数据流  // 使用ContinuousProcessingTimeTrigger定义一个每隔5秒触发的滚动处理时间窗口  
DataStream<Tuple2<String, Long>> result = sourceStream  .keyBy(value -> value.substring(0, 1)) // 假设按字符串的第一个字符分组  .window(TumblingProcessingTimeWindows.of(Time.seconds(30))) // 定义一个30秒的滚动窗口  .trigger(ContinuousProcessingTimeTrigger.of(Time.seconds(5))) // 每5秒触发一次  .aggregate(new MySumAggregationFunction()); // 使用自定义的聚合函数  // 输出结果  
result.print();

**注意:**上面的代码示例是一个简化的表示,用于说明如何使用ContinuousProcessingTimeTrigger。在实际应用中,可能需要根据自己的需求调整窗口大小、分组键和聚合函数。

注意事项

  • 使用ContinuousProcessingTimeTrigger时,请确保Flink集群时间同步良好,以避免因时间差异导致的触发问题。
  • 触发间隔的设置应该根据具体需求和数据流的特点来确定。过短的间隔可能会导致过多的计算和资源消耗,而过长的间隔则可能无法满足实时性要求。
  • Flink的API和功能可能会随着版本的更新而发生变化,因此建议查阅最新的Flink文档以获取准确的信息和示例。

DeltaTrigger

DeltaTrigger具有一个DeltaFunction,该函数的逻辑需要用户自己定义。该函数比较上一次触发计算的元素和目前到来的元素。比较结果为一个double类型阈值。如果阈值超过DeltaTrigger配置的阈值,会返回TriggerResult.FIRE

public TriggerResult onElement(T element, long timestamp, W window, TriggerContext ctx) throws Exception {// 获取上个元素的储存状态ValueState<T> lastElementState = ctx.getPartitionedState(stateDesc);// 确保存入第一个到来的元素if (lastElementState.value() == null) {lastElementState.update(element);return TriggerResult.CONTINUE;}if (deltaFunction.getDelta(lastElementState.value(), element) > this.threshold) {// 重点:只要触发条件满足的时候,才会更新lastElementState,使用新的element替代上一个elementlastElementState.update(element);// 触发计算return TriggerResult.FIRE;}return TriggerResult.CONTINUE;
}

PurgingTrigger

PurgingTrigger 是一种特殊的触发器,它主要用于在触发窗口计算后立即清除窗口中的所有数据,从而帮助释放内存资源。这种触发器通常与其他触发器结合使用,以便在窗口计算完成后立即清理数据。
原理:
PurgingTrigger 本身并不直接决定何时触发窗口计算,而是作为一个包装器(wrapper)或修饰符(modifier),将其他触发器(如 EventTimeTrigger、ProcessingTimeTrigger、CountTrigger 等)转换为具有清除功能的触发器。当被包装的触发器触发窗口计算时,PurgingTrigger 会执行该计算,并在计算完成后清除窗口中的数据。
使用:
在Flink中,可以通过调用 .trigger() 方法并传入 PurgingTrigger.of(…) 来使用 PurgingTrigger。其中,of(…) 方法的参数是想要包装的其他触发器实例。

例如,如果想要使用基于处理时间的滚动窗口,并在每个窗口计算完成后清除数据,可以这样做:

DataStream<...> input = ...; // 输入数据流  DataStream<...> result = input  .keyBy(...) // 根据需要进行分组  .window(TumblingProcessingTimeWindows.of(Time.seconds(10))) // 定义一个10秒的滚动处理时间窗口  .trigger(PurgingTrigger.of(ProcessingTimeTrigger.create())) // 使用PurgingTrigger包装ProcessingTimeTrigger  .aggregate(...); // 使用聚合函数进行计算  result.print(); // 输出结果

**注意:**上面的代码示例是一个简化的表示,用于说明如何使用 PurgingTrigger。在实际应用中,需要根据自己的需求调整窗口分配器、分组键和聚合函数。

注意事项

  • PurgingTrigger 的主要作用是清除数据,以释放内存资源。因此,在使用它时,请确保这是期望的行为。
  • 当使用 PurgingTrigger 包装其他触发器时,被包装的触发器的行为(即何时触发窗口计算)仍然有效。PurgingTrigger 只是在此基础上添加了清除数据的操作。
  • Flink的API和功能可能会随着版本的更新而发生变化。因此,建议查阅最新的Flink文档以获取准确的信息和示例。

自定义触发器

在 Apache Flink 中,自定义触发器(Trigger)是用于定义如何在流处理中的窗口操作(如 Tumbling Windows, Sliding Windows, Session Windows 等)触发计算的。自定义触发器需要实现 Trigger 接口或继承 Trigger 的某个实现类(如 ContinuousProcessingTimeTrigger、ContinuousEventTimeTrigger 等)。

以下是一个自定义触发器的简单示例,该触发器将在每个窗口的最后一个元素到达时触发计算,并且如果窗口在一段时间内没有接收到新元素,则也会触发计算(类似于超时机制):

import org.apache.flink.streaming.api.windowing.assigners.WindowAssigner;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.triggers.Trigger;
import org.apache.flink.streaming.api.windowing.triggers.TriggerResult;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;public class CustomEventTimeTrigger<W extends WindowAssigner.Window> extends Trigger<Object, W> {private static final long serialVersionUID = 1L;// 定义超时时间(毫秒)private final long timeout;public CustomEventTimeTrigger(long timeout) {this.timeout = timeout;}@Overridepublic TriggerResult onElement(Object element, long timestamp, W window, TriggerContext ctx) throws Exception {// 在元素到达时,不做任何事情,因为我们将依赖 onProcessingTime 来触发return TriggerResult.CONTINUE;}@Overridepublic TriggerResult onProcessingTime(long time, W window, TriggerContext ctx) throws Exception {// 检查是否超时if (time - window.getEnd() >= timeout) {// 如果超时,则触发窗口return TriggerResult.FIRE_AND_PURGE;}return TriggerResult.CONTINUE;}@Overridepublic TriggerResult onEventTime(long time, W window, TriggerContext ctx) throws Exception {// 当窗口的最后一个元素到达时触发if (time >= window.getEnd()) {return TriggerResult.FIRE;}return TriggerResult.CONTINUE;}@Overridepublic TriggerResult onMerge(W window, OnMergeContext ctx) throws Exception {// 在窗口合并时调用,根据你的需要来处理// 通常这里可以返回 CONTINUE 或 FIRE_AND_PURGEreturn TriggerResult.CONTINUE;}@Overridepublic void clear(W window, TriggerContext ctx) throws Exception {// 清除窗口的上下文信息}
}

在这个示例中,CustomEventTimeTrigger 继承了 Trigger 接口,并重写了所需的方法。它使用了事件时间(onEventTime)和处理时间(onProcessingTime)来触发窗口。当窗口的最后一个元素到达时(onEventTime),或者当窗口在处理时间中超时(onProcessingTime)时,窗口会被触发。

要使用这个自定义触发器,可以在 Flink 的 DataStream API 中创建一个窗口分配器,并将其与自定义触发器一起使用:

DataStream<...> input = ...; // 输入流input.keyBy(...) // 按键分区.timeWindow(Time.seconds(10), new CustomEventTimeTrigger<>(Time.seconds(5))) // 使用自定义触发器.apply(...); // 窗口函数

在使用 Apache Flink 的 Trigger 时,需要注意以下几个事项

  1. 理解Trigger的作用:
    Trigger 决定了窗口中的数据何时可以被 window function 处理。每个窗口分配器(WindowAssigner)都有一个默认的触发器,但也可以根据需要指定一个自定义的触发器。
  2. 触发器的类型:
    Flink 提供了多种内置的触发器,如 EventTimeTrigger、ProcessingTimeTrigger、CountTrigger 等,它们分别基于事件时间、处理时间和元素数量来触发窗口计算。如果需要更复杂的触发逻辑,可以自定义 Trigger。
  3. 返回值与操作:
    触发器的几个关键方法(onElement, onEventTime, onProcessingTime)都返回一个 TriggerResult 对象,它决定了窗口数据的处理方式,如 CONTINUE(不执行任何操作)、FIRE(触发计算)、PURGE(清除窗口中的元素)、FIRE_AND_PURGE(触发计算并清除窗口中的元素)等。
  4. 状态与合并:
    当使用有状态的触发器(如 SessionWindow)时,需要注意窗口合并时的状态合并逻辑。这通常通过 onMerge 方法实现。
  5. 清除操作:
    clear 方法用于执行删除相应窗口所需的任何操作。但请注意,清除操作只会移除窗口的内容,而不会移除关于窗口的元信息(meta-information)和触发器的状态。
  6. 时间属性:
    触发器可以访问流的时间属性以及定时器,并可以对 state 状态进行编程。因此,在设计触发器时,需要明确流是基于事件时间(EventTime)还是处理时间(ProcessingTime)。
  7. 自定义触发器的设计:
    如果需要自定义触发器,需要仔细考虑触发逻辑。例如,可以根据窗口内的元素数量、特定的事件或时间间隔来触发窗口计算34。
  8. 性能考虑:
    触发器在 Flink 窗口处理中起着关键作用,因此其性能可能会影响整个作业的性能。在设计触发器时,需要考虑其执行效率和资源消耗。
  9. 测试与验证:
    在实际使用触发器之前,建议进行充分的测试和验证,以确保其符合预期并能在各种情况下正常工作。
  10. 与Flink版本保持同步:
    Flink 不断更新和改进其 API 和功能,因此建议查阅最新的 Flink 文档以获取关于 Trigger 的最新信息和最佳实践。

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

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

相关文章

Fast R-CNN(论文阅读)

论文名&#xff1a;Fast R-CNN 论文作者&#xff1a;Ross Girshick 期刊/会议名&#xff1a;ICCV 2015 发表时间&#xff1a;2015-9 ​论文地址&#xff1a;https://arxiv.org/pdf/1504.08083 源码&#xff1a;https://github.com/rbgirshick/fast-rcnn 摘要 这篇论文提出了一…

基于java+springboot+vue实现的校园外卖服务系统(文末源码+Lw)292

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;外卖信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广…

Stream流真的很好,但答应我别用toMap()

你可能会想&#xff0c;toList 和 toSet 都这么便捷顺手了&#xff0c;当又怎么能少得了 toMap() 呢。 答应我&#xff0c;一定打消你的这个想法&#xff0c;否则这将成为你噩梦的开端。 让我们先准备一个用户实体类。 Data AllArgsConstructor public class User { priv…

昇思MindSpore学习总结十——ResNet50迁移学习

1、迁移学习 &#xff08;抄自CS231n Convolutional Neural Networks for Visual Recognition&#xff09; 在实践中&#xff0c;很少有人从头开始训练整个卷积网络&#xff08;使用随机初始化&#xff09;&#xff0c;因为拥有足够大小的数据集相对罕见。相反&#xff0c;通常…

LLM - 循环神经网络(RNN)

1. RNN的关键点&#xff1a;即在处理序列数据时会有顺序的记忆。比如&#xff0c;RNN在处理一个字符串时&#xff0c;在对字母表顺序有记忆的前提下&#xff0c;处理这个字符串会更容易。就像人一样&#xff0c;读取下面第一个字符串会更容易&#xff0c;因为人对字母出现的顺序…

Linux应用---信号

写在前面&#xff1a;在前面的学习过程中&#xff0c;我们学习了进程间通信的管道以及内存映射的方式。这次我们介绍另外一种应用较为广泛的进程间通信的方式——信号。信号的内容比较多&#xff0c;是学习的重点&#xff0c;大家一定要认真学&#xff0c;多多思考。 一、信号概…

【AI资讯】可以媲美GPT-SoVITS的低显存开源文本转语音模型Fish Speech

Fish Speech是一款由fishaudio开发的全新文本转语音工具&#xff0c;支持中英日三种语言&#xff0c;语音处理接近人类水平&#xff0c;使用Flash-Attn算法处理大规模数据&#xff0c;提供高效、准确、稳定的TTS体验。 Fish Audio

驾校管理系统设计

驾校管理系统设计旨在提高驾校运营效率、学员管理、教练安排、考试预约、财务结算等方面的能力。以下是一个基本的设计框架&#xff0c;包括关键模块和数据表设计&#xff1a; 1. 系统架构设计 前端界面&#xff1a;提供给学员、教练和管理员使用的Web界面或移动应用&#xf…

【高中数学/基本不等式】当x是正实数时,求函数f(x)=x/(1+x^2)的最大值?

【问题】 当x是正实数时&#xff0c;求函数f(x)x/(1x^2)的最大值&#xff1f; 【解答】 解&#xff1a; f(x)x/(1x^2)1/(x1/x))<1/2倍根号下(x*1/x)1/2 所以函数在[0,∞)的区域最大值为0.5 【函数图像】 f(x)x/(1x^2)是奇函数&#xff0c;没有断点&#xff0c;是可以…

idea推送到gitee 401错误

在idea上推送时遇到这样的问题&#xff0c;解决方法如下&#xff1a; 在https://的后面加上 用户名:密码 然后再提交就ok啦&#xff01;

使用qt creator配置msvc环境(不需要安装shit一样的宇宙第一IDE vs的哈)

1. 背景 习惯使用Qt编程的童鞋&#xff0c;尤其是linux下开发Qt的童鞋一般都是使用qt creator作为首选IDE的&#xff0c;通常在windows上使用Qt用qt creator作为IDE的话一般编译器有mingw和msvc两种&#xff0c;使用mingw版本和在linux下的方式基本上一样十分简单&#xff0c;不…

Alt与Tab切换窗口时将Edge多个标签页作为一个整体参与切换的方法

本文介绍在Windows电脑中&#xff0c;使用Alt与Tab切换窗口时&#xff0c;将Edge浏览器作为一个整体参与切换&#xff0c;而不是其中若干个页面参与切换的方法。 最近&#xff0c;需要将主要使用的浏览器由原本的Chrome换为Edge&#xff1b;但是&#xff0c;在更换后发现&#…

数据结构与算法笔记:实战篇 - 剖析微服务接口鉴权限流背后的数据结构和算法

概述 微服务是最近几年才兴起的概念。简单点将&#xff0c;就是把复杂的大应用&#xff0c;解耦成几个小的应用 。这样做的好处有很多。比如&#xff0c;这样有利于团队组织架构的拆分&#xff0c;比较团队越大协作的难度越大&#xff1b;再比如&#xff0c;每个应用都可以独立…

mybatis-plus参数绑定异常

前言 最近要搞个发票保存的需求&#xff0c;当发票数据有id时说明是发票已经保存只需更新发票数据即可&#xff0c;没有id时说明没有发票数据需要新增发票&#xff1b;于是将原有的发票提交接口改造了下&#xff0c;将调用mybatis-plus的save方法改为saveOrUpdate方法&#xff…

从零开始实现大语言模型(四):简单自注意力机制

1. 前言 理解大语言模型结构的关键在于理解自注意力机制(self-attention)。自注意力机制可以判断输入文本序列中各个token与序列中所有token之间的相关性&#xff0c;并生成包含这种相关性信息的context向量。 本文介绍一种不包含训练参数的简化版自注意力机制——简单自注意…

Spark快速大数据分析PDF下载读书分享推荐

《Spark 快速大数据分析》是一本为 Spark 初学者准备的书&#xff0c;它没有过多深入实现细节&#xff0c;而是更多关注上层用户的具体用法。不过&#xff0c;本书绝不仅仅限于 Spark 的用法&#xff0c;它对 Spark 的核心概念和基本原理也有较为全面的介绍&#xff0c;让读者能…

clickhouse高可用可拓展部署

clickhouse高可用&可拓展部署 1.部署架构 1.1高可用架构 1.2硬件资源 部署服务 节点名称 节点ip 核数 内存 磁盘 zookeeper zk-01 / 4c 8G 100G zk-02 / 4c 8G 100G zk-03 / 4c 8G 100G clikehouse ck-01 / 32c 128G 2T ck-02 / 32c 128G 2T ck-03 / 32c 128G 2T ck-04 /…

昇思25天学习打卡营第13天 | LLM原理和实践:文本解码原理--以MindNLP为例

1. 文本解码原理--以MindNLP为例 1.1 自回归语言模型 根据前文预测下一个单词 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积 W 0 W_0 W0​:初始上下文单词序列 t t t: 时间步 当生成EOS标签时&#xff0c;停止生成。 MindNLP/huggingface Transfor…

13.SQL注入-宽字节

SQL注入-宽字节 含义&#xff1a; MySQL是用的PHP语言&#xff0c;然后PHP有addslashes()等函数&#xff0c;这类函数会自动过滤 ’ ‘’ null 等这些敏感字符&#xff0c;将它们转义成’ ‘’ \null&#xff1b;然后宽字节字符集比如GBK它会自动把两个字节的字符识别为一个汉…

解决分布式环境下session共享问题

在分布式环境下&#xff0c;session会存在两个问题 第一个问题:不同域名下&#xff0c;浏览器存储的jsessionid是没有存储的。比如登录时认证服务auth.gulimall.com存储了session&#xff0c;但是搜索服务search.gulimall.com是没有这个session的&#xff1b; 第二个问题&…