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

解读 Flink Source 接口重构后的 KafkaSource

前言

Apache Kafka 和 Apache Flink 的结合,为构建实时流处理应用提供了一套强大的解决方案[1]。Kafka 作为高吞吐量、低延迟的分布式消息队列,负责数据的采集、缓冲和分发;而 Flink 则是功能强大的流处理引擎,负责对数据进行实时计算和分析。两者相辅相成,优势互补,共同构成了实时流处理应用的坚实基础。

其中 Flink Kafka Source 成为了连接 Kafka 与 Flink 的桥梁, 为 Apache Flink 提供了从 Apache Kafka 读取数据流的功能。它作为 Flink 数据输入的起点,负责高效、可靠地将 Kafka Topic 中的消息数据接入 Flink 流处理程序,为后续的实时计算、分析和处理提供数据基础。

值得一提的是,AutoMQ 作为 Apache Kafka 的社区分叉项目,对其存储层进行了重新设计与实现,但是完整保留了 Apache Kafka 计算层的代码。对于 Apache Kafka 具有 100% 的兼容性。这意味着在 Flink 生态系统中,专为 Kafka 开发的 Flink Kafka Source/Sink 可以与 AutoMQ 完全兼容。

在这里插入图片描述

Flink Source 接口重构动机

从 Flink 1.12 开始,基于 new source API(FLIP-27)[2]和 new sink API (FLIP-143)[3]开发的 KafkaSourceKafkaSink 是推荐的 Kafka 连接器。 FlinkKafkaConsumerFlinkKafkaProducer 则已被弃用。

在 FLIP-27: Refactor Source Interface 中旨在解决当前 streaming source 接口(SourceFunction)中的诸多问题与缺点,并同时统一批处理和 streaming APIs 之间的 source 接口。

在 FLIP-27 中,具体阐述 SourceFunction 中存在的问题,总结下来,可以分为如下:

  1. 批处理和流处理的 Source 实现不一致: Flink 为批处理和流处理提供了不同的 Source 接口,导致代码重复,维护困难。

  2. 逻辑耦合: “work discovery”(例如,发现 Kafka 的分区或文件系统的 Split )和实际读取数据的逻辑在 SourceFunction 接口和 DataStream API 中混合在一起,导致实现复杂,例如 Kafka 和 Kinesis 的 Source 实现。

  3. 缺乏对分区/ Split 的显式支持: 当前接口没有明确表示分区或 Split 的概念。这使得难以以独立于 Source 的方式实现某些功能,例如事件时间对齐、每个分区的 watermark、动态 Split 分配和工作窃取。例如,Kafka 和 Kinesis 消费者都支持每个分区的 watermark,但截至 Flink 1.8.1,只有 Kinesis 消费者支持事件时间对齐(选择性地从 Split 读取数据,以确保事件时间均匀地推进)。

  4. Checkpoint 锁的问题

    • SourceFunction 持有 checkpoint 锁,导致实现必须确保在锁下进行元素发送和状态更新,限制了 Flink 对锁的优化空间。

    • 锁不是公平锁,在锁竞争激烈的情况下,某些线程(例如 checkpoint 线程)可能无法及时获取锁。

    • 当前的锁机制也阻碍了基于无锁 Actor/Mailbox 模型的 operator 实现。

  5. 缺乏统一线程模型: 每个 Source 都需要自己实现复杂的线程模型,导致开发和测试新 Source 变得困难。

重构后的 KafkaSource

核心抽象

在这里插入图片描述

Split:Flink 中的可追踪数据单元

在 Flink 中,记录分片 (Record Split) 是指一个具有唯一标识符的有序记录集合,它代表了数据源中的一段连续数据。记录分片是 Flink 进行并行处理、容错恢复和状态管理的基本单元。

分片的定义灵活可变,以 Kafka 为例:

  • 分片可以是一个完整的分区。

  • 分片也可以是分区内的一部分,例如 offset 100 到 200 的记录。

同时以 Kafka 为例,来解释 Split 的特征:

  1. 有序的记录集合: 分片中的记录是有序的,例如按照 Kafka 中的 offset 排序。

  2. 唯一标识符: 每个分片都有一个唯一的 ID,用于区分不同的分片,例如 Topic-PartitionId。

  3. 进度可追踪: Flink 会记录每个分片的处理进度,以便在发生故障时进行恢复,例如某个分区的消费位点。

Split Enumerator:Flink 数据读取的指挥官

Flink 中的记录分片枚举器 (Split Enumerator) 负责管理和分配数据源中的记录分片给 Source Reader 读取数据,它在 Flink 数据读取过程中扮演着“指挥官”的角色。

主要职责:

  1. 发现记录分片 (Split Discovery):

    • 定期扫描外部数据源,例如 Kafka、文件系统等,检测新增的记录分片。

    • 例如,Kafka 的 Split Enumerator 会监听 topic 的分区变化,并在新增分区时创建新的分片。

  2. 分配记录分片 (Split Assignment):

    • 将发现的记录分片分配给 Source Reader 进行读取。

    • 协调多个 Source Reader 之间的分片分配,尽量保证负载均衡。

    • 监控 Source Reader 的处理进度,动态调整分片分配,例如将部分分片从过载的 Reader 转移到空闲的 Reader。

  3. 协调 Source Reader:

    • 控制 Source Reader 的读取速度,避免个别 Reader 读取过快或过慢,影响整体的 watermark 推进和数据处理进度。

    • 处理 Source Reader 的故障,例如将故障 Reader 负责的分片重新分配给其他 Reader。

Source Reader:Flink 数据读取的执行者

Source Reader 是 Flink 中真正执行数据读取操作的组件,它负责从 Split Enumerator 分配的记录分片中读取数据,并将数据传递给下游算子进行处理。

主要职责:

  1. 从记录分片读取数据:

    • 根据 Split Enumerator 分配的记录分片信息,连接到外部数据源。

    • 从指定位置开始读取数据,例如从 Kafka 的指定 offset 开始消费数据。

    • 持续读取数据,直到分片结束或者收到停止信号。

  2. 事件时间水印处理:

    • 从读取的记录中提取事件时间信息。

    • 根据事件时间生成水印 (Watermark),并将其发送到下游算子,用于处理乱序数据和事件时间窗口。

  3. 数据反序列化:

    • 将从外部数据源读取的原始数据(例如字节流)反序列化成 Flink 内部可以处理的数据结构(例如 DataStream 中的元素)。
  4. 数据发送:

    • 将反序列化后的数据发送给下游算子进行处理。

将 Work Discovery 与 Reading 分离

将 Source 的功能拆分为两个主要组件:

在这里插入图片描述

  • SplitEnumerator( Split 枚举器):

    • 负责发现和分配 Split (splits),例如文件、Kafka 分区等。

    • 可以在 JobManager 或 TaskManager 上运行。

  • Reader(读取器):

    • 负责从分配的 Split 中读取实际数据。

    • 包含了当前 Source 接口的大部分功能。

    • 可以按顺序读取一系列有界 Split ,也可以并行读取多个(无界) Split 。

之前 FlinkKafkaConsumerBase [4]的设计中,集中了 kafka partition 发现逻辑(KafkaPartitionDiscoverer)、数据读取逻辑(KafkaFetcher)、基于阻塞队列实现的生产者消费者模型等等。整体设计相对来说代码复杂,难以维护和扩展。

在这里插入图片描述

@Override
public void run(SourceContext<T> sourceContext) throws Exception {// ... (省略部分初始化代码)// ... (省略部分逻辑)this.kafkaFetcher =createFetcher(// ... (省略部分参数));// ... (省略部分逻辑)// 根据是否开启分区发现机制,选择不同的执行路径if (discoveryIntervalMillis == PARTITION_DISCOVERY_DISABLED) {// 直接运行数据读取循环kafkaFetcher.runFetchLoop(); } else {// 运行包含分区发现逻辑的代码runWithPartitionDiscovery(); }
}

在该思路下就可以分离并设计为:

KafkaSourceEnumerator:

  • 发现分区: 定期或一次性地发现 Kafka 主题中的所有分区。

  • 初始化分区: 获取每个分区的起始偏移量和结束偏移量。

  • 分配分区: 将分区分配给不同的 Source Reader,并管理分区的分配状态

KafkaSourceReader 负责从分配的 Kafka 分区中读取数据,并处理 checkpoint 相关的逻辑。

  • 接收并处理 SplitEnumerator 分配的分区

  • 处理读取到的数据

  • 处理 checkpoint

将 “Work Discovery” 和数据读取逻辑分离,提高了代码的模块化和可重用性。例如,可以为不同的分区发现策略实现不同的 SplitEnumerator,而无需修改 Reader 的代码

KafkaSourceEnumerator

在这里插入图片描述

SourceCoordinator 启动
  • 当 Flink 作业启动时,会为每个 Kafka Source 任务创建一个 SourceCoordinator 实例。

  • SourceCoordinatorstart() 方法会被调用,开始执行以下操作:

    • 如果是第一次启动(非从 Checkpoint 恢复),则调用 source.createEnumerator() 创建一个 KafkaSourceEnumerator 实例。

    • 调用 enumerator.start() 启动 KafkaSourceEnumerator

KafkaSourceEnumerator 启动
  • KafkaSourceEnumeratorstart() 方法会被调用:

    • 初始化 Kafka 消费者和 Kafka 管理客户端。

    • 根据配置决定分区发现模式(周期性或单次)。

    • 异步调用 discoverAndInitializePartitionSplit() 方法进行初始分区发现。

分区发现与初始化
  • discoverAndInitializePartitionSplit() 方法执行以下操作:

    • 获取 Kafka 分区变化信息。

    • 获取新增分区的起始和终止偏移量(针对有限制的流)。

    • 为每个新增分区创建 KafkaPartitionSplit 对象。

    • 将新增分片添加到待分配列表 (pendingPartitionSplitAssignment) 中。

    • 调用 assignPendingPartitionSplits() 方法分配分片。

分片分配
  • assignPendingPartitionSplits() 方法执行以下操作:

    • 将待分配分片分配给可用的 Source Reader。

    • 如果禁用了周期性分区发现,则在初始分片分配完成后,向 Source Reader 发送 NoMoreSplitsEvent 事件。

Enumerator-Reader 通信机制

在 Flink 新的 Source 设计中,SplitEnumerator 和 SourceReader 是两个独立的组件,分别负责 Split 管理和数据读取。然而,在实际应用中,这两个组件之间 often 需要进行通信,例如在 Kafka Source 场景下:

  • KafkaSourceReader 需要请求 KafkaSplitEnumerator 进行 KafkaSourceReader 注册

  • KafkaSplitEnumerator 需要通知 KafkaSourceReader 有新的 KafkaPartitionSplit 需要读取。

通用通信机制:

为了满足 SplitEnumerator 和 SourceReader 之间的通信需求,Flink 引入了一种通用的消息传递机制,其核心是 SourceEvent 接口。

  • SourceEvent: 定义了 SplitEnumerator 和 SourceReader 之间传递的消息类型。

  • OperatorEvent:是在 OperatorCoordinator 和 Operator 之间传递消息的接口。

在这里插入图片描述

消息传递链条:

  1. OperatorEventGateway: 接收 OperatorEvent,并添加 OperatorID 信息。

  2. TaskOperatorEventGateway: 接收来自 OperatorEventGateway 的事件,添加 ExecutionAttemptID 信息,并将其转发给 JobMasterOperatorEventGateway

  3. JobMasterOperatorEventGateway: Task Manager 与 JobManager 之间的 RPC 接口,负责将事件最终发送到 JobManager 上的 OperatorCoordinator。

public interface JobMasterOperatorEventGateway {CompletableFuture<Acknowledge> sendOperatorEventToCoordinator(ExecutionAttemptID task,OperatorID operatorID,SerializedValue<OperatorEvent> event);}
public interface OperatorCoordinator extends CheckpointListener, AutoCloseable {
...void handleEventFromOperator(int subtask, OperatorEvent event) throws Exception;
...
}

对于 SourceCoordinator 来说,handleOperatorEvent 内到处理逻辑如下:

  • RequestSplitEvent: 请求分配新的 Split ,调用 enumerator.handleSplitRequest() 处理。

  • SourceEventWrapper: 来自 SourceReader 的事件,调用 enumerator.handleSourceEvent() 处理。

  • ReaderRegistrationEvent: Reader 注册事件,调用 handleReaderRegistrationEvent() 处理。

  • 其他事件类型: 抛出异常,表示无法识别该事件类型。

(在实际实现当中,OperatorEvent有时也可以直接传递到 SourceReader/SplitEnumerator,而不需要在转换为SourceEvent

对于 SourceOperator 来说,handleOperatorEvent 内到处理逻辑如下:

  • AddSplitEvent: 新增 Split 事件,表示 SplitEnumerator 分配了新的 Split 给该 SourceReader

  • SourceEventWrapper: 调用 sourceReader.handleSourceEvents() 将事件传递给 SourceReader 处理。

  • NoMoreSplitsEvent: 没有更多 Split 事件,表示 SplitEnumerator 已经分配完所有 Split 。

KafkaSourceReader

Reader 接口与线程模型

Flink 新 Source API 中的 SourceReader 接口,它负责从 Source Split 中读取数据,并与 SplitEnumerator 进行交互。SourceReader接口代码如下:

public interface SourceReader<T, SplitT extends SourceSplit>extends AutoCloseable, CheckpointListener {void start();InputStatus pollNext(ReaderOutput<T> output) throws Exception;CompletableFuture<Void> isAvailable();void addSplits(List<SplitT> splits);void notifyNoMoreSplits();default void handleSourceEvents(SourceEvent sourceEvent) {}List<SplitT> snapshotState(long checkpointId);@Overridedefault void notifyCheckpointComplete(long checkpointId) throws Exception {}}

SourceReader 被设计为无锁的、非阻塞的接口,以支持 Actor/Mailbox/Dispatcher 风格的 operator 实现。所有方法都在同一个线程中调用,因此实现者无需处理并发问题。

  • SourceReader 使用异步的方式读取数据,并通过 isAvailable() 方法通知运行时数据是否可读。

  • pollNext 可以非阻塞地读取下一条记录,并将记录发送到 ReaderOutput。 返回一个 InputStatus 枚举值,表示读取状态,例如 MORE_AVAILABLE (还有更多数据)、END_OF_INPUT (数据读取完毕) 等。

高层抽象简化 Source Reader 实现

  • 底层的 SourceReader 接口非常通用,但实现起来比较复杂,尤其是对于像 Kafka 或 Kinesis 这样需要处理多路复用和并发读取的 Source 来说。

  • 大多数连接器使用的 I/O 库都是阻塞式的,需要创建额外的 I/O 线程才能实现非阻塞读取。

因此在此 FP 中提出了一个解决方案:

  • 高层抽象: 提供更简单的接口,允许使用阻塞式调用,并封装了多路复用和事件时间处理等复杂逻辑。

大多数 Reader 属于以下类别之一:

  • 单 Reader 单 splits: 最简单的类型,例如读取单个文件。

  • 单 Reader 多 splits: 一个 Reader 可以读取多个 Split ,例如:

    • Sequential Single Split 读取: 单个 IO 线程依次顺序读取各个 Split,例如文件或数据库查询结果。

在这里插入图片描述

Sequential Single Split

  • 多路复用多 splits 读取: 单个 IO 线程使用多路复用技术读取多个 Split ,例如 Kafka、Pulsar、Pravega 等。

在这里插入图片描述

Multi-split Multiplexed

  • 多线程多 splits 读取: 使用多个线程并发读取多个 Split ,例如 Kinesis。

在这里插入图片描述

Multi-split Multi-threaded

以上分析,抽象如下接口,开发者可根据实际需求选择不同的高层 Reader 类型,并通过实现简单的接口来创建自定义的 Source Reader。

public interface SplitReader<E, SplitT extends SourceSplit> {RecordsWithSplitIds<E> fetch() throws InterruptedException;void handleSplitsChanges(Queue<SplitsChange<SplitT>> splitsChanges);void wakeUp();
}
  • fetch(): 从 Split 中读取数据,返回一个 RecordsWithSplitIds 对象,包含读取到的记录和对应的 Split ID。

  • handleSplitsChanges(): 处理 Split 的变化,例如新增 Split 或移除 Split。

  • wakeUp(): 唤醒阻塞的 fetch() 操作,例如在有新的 Split 可用时。

public interface RecordEmitter<E, T, SplitStateT> {void emitRecord(E element, SourceOutput<T> output, SplitStateT splitState) throws Exception;
}
  • emitRecord: 负责将 SplitReader 读取的原始记录 (E) 转换为最终的记录类型 (T

SourceReaderBase:提供了 SourceReader 的基础实现,封装了事件队列、 Split 状态管理、SplitFetcher 管理等通用逻辑

在这里插入图片描述

Split 分配流程

  1. SplitEnumerator 分配 Split : SplitEnumerator 发现新的 Split ,并将它们分配给对应的 SourceReader

  2. SourceReader 接收 Split : SourceReader 收到新的 Split 后,会进行初始化 state,随后调用 SplitFetcherManageraddSplits() 方法。

  3. SplitFetcherManager 获取或创建 SplitFetcher,将 Splits 添加到 SplitFetcher

  4. SplitFetcher 将 AddSplitsTask 添加到任务队列,唤醒 SplitFetcher 的工作线程

  5. AddSplitsTask 通知 SplitReader 处理 SplitsChanges

  6. SplitReader 更新被分配的 Split

Source 数据获取流程:

  1. SplitReader 读取数据: SplitReader 从 Split 中读取数据,并将数据封装成 RecordsWithSplitIds 对象返回给 SourceReader

  2. SourceReader 处理数据: SourceReader 遍历 RecordsWithSplitIds 中的每条记录,并根据记录所属的 Split ID 获取对应的 SplitState

  3. 调用 RecordEmitter 处理记录: SourceReader 将记录和 SplitState 传递给 RecordEmitter 进行处理。

  4. RecordEmitter 处理记录:

    • 将原始记录类型 (E) 转换为最终的记录类型 (T)。

    • 更新 SplitState,例如记录读取进度等信息。

    • 将处理后的记录加入到 SourceOutput

Checkpoint 和 Failover 流程

Flink 的容错机制依赖于 检查点 (Checkpoint),它会定期生成数据流的快照,包括数据源的读取位置和算子的状态信息。当发生故障时,Flink 可以从最近的 Checkpoint 恢复,保证 Exactly-Once 语义。

在 Flink Kafka Source 中,KafkaSourceEnumeratorKafkaSourceReader 两个关键组件分别就有自己的 Checkpoint 和 Failover 的流程。如图所示,Flink Kafka Source 通过 Checkpoint 机制记录数据源的读取位置和 Source Reader 的状态信息,并在 Failover 时利用这些信息进行恢复,保证数据不会丢失或重复处理。

在这里插入图片描述

总结

Apache Flink 与消息队列的结合是构建实时流处理应用的强大方案。本文首先介绍了 Flink 与 Kafka 的集成,并深入探讨了 Flink Kafka Source 的重构,以解决原有设计上的不足。

Flink Kafka Source 的重构主要包括:

  • 引入 Split Enumerator 和 Source Reader,实现 “Work Discovery” 与 Reading 的分离,提高代码模块化和可重用性。

  • 通过 Source Event 机制实现 Enumerator 和 Reader 之间的异步通信,提高代码可维护性。

  • 提供 SplitReader 和 RecordEmitter 等高层抽象,提供 SourceReaderBase 的实现,使得 Kafka Source 可以只需专注于 SplitReader 和 RecordEmitter 的实现。

重构后的 Flink Kafka Source 通过 Checkpoint 机制记录数据源读取位置和 Source Reader 状态信息,保证 Exactly-Once 语义。

然而,传统的 Shared Nothing 架构消息队列(如 Kafka)在面对海量数据和高并发场景时,存在存储成本高、运维复杂、扩缩容困难等挑战。

AutoMQ 作为新一代云原生消息队列,采用 Shared Storage 架构和基于对象存储的低成本存储,并与 Kafka 100% 兼容。未来,AutoMQ 与 Flink 的结合将为云原生实时流处理应用带来以下优势:

  • 更低的成本: 尤其在处理冷数据时,成本优势更加明显。

  • 更高的弹性: 支持集群自动扩缩容和流量自平衡,灵活应对业务变化,保证系统稳定运行。

  • 更简化的运维: Shared Storage 架构简化了集群部署和运维。

  • 与 Kafka 生态的无缝衔接: 方便企业平滑迁移。

AutoMQ 与 Flink 的结合将成为未来云原生实时流处理应用的重要发展方向,为企业提供更低成本、更高效、更便捷的流处理解决方案。

[1]: Apache Kafka (including Kafka Streams) + Apache Flink = Match Made in Heaven

[2]: https://cwiki.apache.org/confluence/display/FLINK/FLIP-27%3A+Refactor+Source+Interface

[3]: https://cwiki.apache.org/confluence/display/FLINK/FLIP-143%3A+Unified+Sink+API

[4]: https://github.com/apache/flink/blob/b1e7b892cc9241f568150135b8bcf7bcd9f0c125/flink-connectors/flink-connector-kafka/src/main/java/org/apache/flink/streaming/connectors/kafka/FlinkKafkaConsumerBase.java#L757-L830

相关文章:

解读 Flink Source 接口重构后的 KafkaSource

前言 Apache Kafka 和 Apache Flink 的结合&#xff0c;为构建实时流处理应用提供了一套强大的解决方案[1]。Kafka 作为高吞吐量、低延迟的分布式消息队列&#xff0c;负责数据的采集、缓冲和分发&#xff1b;而 Flink 则是功能强大的流处理引擎&#xff0c;负责对数据进行实时…...

一场始于 Selector Error 的拯救行动:企查查数据采集故障排查记

时间轴呈现事故进程 17:00&#xff1a;开发人员小李正在尝试利用 Python 爬虫从企查查&#xff08;https://www.qcc.com&#xff09;抓取公司工商信息。原本一切正常&#xff0c;但突然发现信息采集失败&#xff0c;程序抛出大量选择器错误。17:15&#xff1a;小李发现&#x…...

代码随想录刷题攻略---动态规划---子序列问题1---子序列

子序列&#xff08;不连续&#xff09;和子序列&#xff08;连续&#xff09;的问题 例题1: 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的…...

QEMU 搭建arm linux开发环境

Qemu 作为一款强大的开源虚拟化软件&#xff0c;为我们提供了一个便捷且经济实惠的方式来模拟各种硬件环境&#xff0c;从而在上面安装和学习 Linux 系统。本文将详细介绍如何使用 Qemu 搭建 Linux 学习环境&#xff0c; 环境准备 操作系统&#xff1a;建议使用 Ubuntu 20.04…...

PyQt组态软件 拖拽设计界面测试

PyQt组态软件测试 最近在研究PyQt,尝试写个拖拽设计界面的组态软件&#xff0c;目前实现的功能如下&#xff1a; 支持拖入控件&#xff0c;鼠标拖动控件位置 拖动控件边缘修改控件大小支持属性编辑器&#xff0c;修改当前选中控件的属性 拖动框选控件&#xff0c;点选控件 控…...

JAVA泛型介绍与举例

Java中&#xff0c;泛型用于编译阶段限制集合中元素的类型&#xff0c;或者限制类中某个属性的类型&#xff0c;编译过程中发生类型擦除&#xff0c;最终还是Object类型。 1. 集合中的泛型 集合默认可以存储任何类型的元素&#xff0c;即Object类型&#xff0c;当使用一个集合…...

JavaScript 内置对象-Math对象

在JavaScript中&#xff0c;Math 对象提供了一系列与数学相关的静态方法和属性&#xff0c;帮助开发者执行复杂的计算任务。无论是简单的算术运算还是高级的几何、统计计算&#xff0c;Math 对象都能提供强大的支持。本文将详细介绍 Math 对象的主要功能及其使用方法。 一、简…...

Ubuntu 22.04 Desktop企业级基础配置操作指南

一、网络配置 cd /etc/netplan vi 00-installer-config.yaml 设置如下所示&#xff1a; network:version: 2ethernets:eth0: # 替换为你的实际网络接口名称&#xff0c;如 ens33, enp0s3 等dhcp4: noaddresses:- 192.168.1.100/24 # 静态IP地址和子网掩码gateway4: 192.16…...

UE_C++ —— UObject Instance Creation

目录 一&#xff0c;UObject Instance Creation NewObject NewNamedObject ConstructObject Object Flags 二&#xff0c;Unreal Object Handling Automatic Property Initialization Automatic Updating of References Serialization Updating of Property Values …...

WPF的MVVMLight框架

在NuGet中引入该库&#xff1a; MVVMLight框架中的命令模式的使用&#xff1a; <StackPanel><TextBox Text"{Binding Name}"/><TextBox Text"{Binding Title}"/><Button Content"点我" Command"{Binding ShowCommand…...

【云安全】云原生- K8S kubeconfig 文件泄露

什么是 kubeconfig 文件&#xff1f; kubeconfig 文件是 Kubernetes 的配置文件&#xff0c;用于存储集群的访问凭证、API Server 的地址和认证信息&#xff0c;允许用户和 kubectl 等工具与 Kubernetes 集群进行交互。它通常包含多个集群的配置&#xff0c;支持通过上下文&am…...

binance python

binance-futures-connector 4.1.0 from binance.um_futures import UMFutures # U本位 USDT-M Futures /fapi/* # 币本位 COIN-M Delivery /dapi/* proxies { https: http://localhost:7890 } client UMFutures(proxiesproxies)apiKey"" apiSecret"" cl…...

LLaMA-Factory DeepSeek-R1 模型 微调基础教程

LLaMA-Factory 模型 微调基础教程 LLaMA-FactoryLLaMA-Factory 下载 AnacondaAnaconda 环境创建软硬件依赖 详情LLaMA-Factory 依赖安装CUDA 安装量化 BitsAndBytes 安装可视化微调启动 数据集准备所需工具下载使用教程所需数据合并数据集预处理 DeepSeek-R1 可视化微调数据集处…...

利用亚马逊云科技RDS for SQL Server配置向量数据存储

生成式人工智能&#xff08;AI&#xff09;正迎来又一个快速发展期&#xff0c;引起了开发者们的广泛关注。将生成式能力集成到商业服务和解决方案中变得非常重要。当前的生成式AI解决方案是机器学习和深度学习模型逐步进化迭代的结果。从深度学习到生成式AI的质变飞跃主要是由…...

ASP.NET Core SixLabors.ImageSharp v1.0 的图像实用程序类 web示例

这个小型实用程序库需要将 NuGet SixLabors.ImageSharp包&#xff08;版本 1.0.4&#xff09;添加到.NET Core 3.1/ .NET 6 / .NET 8项目中。它与Windows、Linux和 MacOS兼容。 这已针对 ImageSharp v3.0.1 进行了重新设计。 它可以根据百万像素数或长度乘以宽度来调整图像大…...

JVM 底层探秘:对象创建的详细流程、内存分配机制解析以及线程安全保障策略

文章目录 1. 类加载检查2. 内存分配① 指针碰撞② 空闲列表线程安全问题&#xff1a; 3. 内存空间初始化4. 对象头设置5. 对象初始化 当Java虚拟机遇到一条 new指令时&#xff0c;会执行以下步骤来创建对象&#xff1a; 1. 类加载检查 首先检查new指令的参数是否能在常量池中…...

SpringCloud框架下的注册中心比较:Eureka与Consul的实战解析

摘要 在探讨SpringCloud框架中的两种注册中心之前&#xff0c;有必要回顾单体架构与分布式架构的特点。单体架构将所有业务功能集成在一个项目中&#xff0c;优点是架构简单、部署成本低&#xff0c;但耦合度高。分布式架构则根据业务功能对系统进行拆分&#xff0c;每个模块作…...

应对DeepSeek总是服务器繁忙的解决方法

最近由于访问量过大&#xff0c;DeepSeek服务器官网经常弹出&#xff1a;“服务器繁忙&#xff0c;请稍后再试”的提示&#xff0c;直接卡成PPT怎么办&#xff1f;服务器繁忙直接看到视觉疲劳&#xff1a; 解决DeepSeek卡顿问题 DeepSeek使用卡顿问题&#xff0c;是因为访问量…...

C++ 实践扩展(Qt Creator 联动 Visual Studio 2022)

​ 这里我们将在 VS 上实现 QT 编程&#xff0c;实现如下&#xff1a; 一、Vs 2022 配置&#xff08;若已安装&#xff0c;可直接跳过&#xff09; 点击链接&#xff1a;​​​​​Visual Studio 2022 我们先去 Vs 官网下载&#xff0c;如下&#xff1a; 等待程序安装完成之…...

JENKINS(全面)

一.linux系统中JENKINS的安装 注意&#xff1a;安装jenkins需要安装jdk&#xff0c;而且具体版本的jenkins有相对应的jdk版本。可参考以下链接。 Redhat Jenkins 软件包https://pkg.jenkins.io/redhat-stable/https://pkg.jenkins.io/redhat-stable/https://pkg.jenkins.io/r…...

72.git指南(简单)

Git 操作指南 在开始之前&#xff0c;请确保你已经提前配置好 .gitignore 文件&#xff0c;以避免不必要的文件被 Git 跟踪。如果在初始化仓库后再配置 .gitignore 文件&#xff0c;之前添加的文件仍会被跟踪&#xff0c;需要手动移除。 如下例子忽略了文件夹及文件夹内所有内…...

LeetCode 232: 用栈实现队列

LeetCode 232: 用栈实现队列 题目描述 使用栈实现队列的操作。支持以下操作&#xff1a; MyQueue()&#xff1a;初始化队列。push(x)&#xff1a;将元素 x 推入队列。pop()&#xff1a;从队列中移除元素。peek()&#xff1a;返回队列头部的元素。empty()&#xff1a;检查队列…...

C#关于静态关键词static详解

Demo代码&#xff1a; public class HomeController : Controller {private DateTime time1 DateTime.Now; // 实例字段private static DateTime time2 DateTime.Now; // 静态字段[HttpGet("index")]public async Task Index(){Console.WriteLine($"now&am…...

【Pico】使用Pico进行无线串流搜索不到电脑

使用Pico进行无线串流搜索不到电脑 官串方式&#xff1a;使用Pico互联连接电脑。 故障排查 以下来自官方文档 请按照以下步骡排除故障&#xff1a; 确认电脑和一体机连接了相同的路由器WiFi网络(相同网段) IP地址通常为192.168.XX&#xff0c;若两设备的IP地址前三段相同&…...

细说STM32F407单片机RTC的基本原理及闹钟和周期唤醒功能的使用方法

目录 一、RTC基础知识 1、 RTC的功能 2、RTC工作原理 &#xff08;1&#xff09;RTC的时钟信号源 &#xff08;2&#xff09;预分频器 &#xff08;3&#xff09;实时时钟和日历数据 &#xff08;4&#xff09;周期性自动唤醒 &#xff08;5&#xff09;可编程闹钟 &a…...

ES用脚本更新异常

因为需要向原有的es结构中增加一个检索字段&#xff0c;但因为历史es数据都没有该字段&#xff0c;需要批量刷新es的该字段&#xff0c;本地使用了脚本的方式进行刷新&#xff0c;在测试环境测试&#xff0c;出现了以下错误&#xff1a; 500 Internal Server Error: [{"e…...

Navicat导入海量Excel数据到数据库(简易介绍)

目录 前言正文 前言 此处主要作为科普帖进行记录 原先Java处理海量数据的导入时&#xff0c;由于接口超时&#xff0c;数据处理不过来&#xff0c;后续转为Navicat Navicat 是一款功能强大的数据库管理工具&#xff0c;支持多种数据库系统&#xff08;如 MySQL、PostgreSQL、…...

C++学习

C对C语言的加强 1.命名空间&#xff08;namespace&#xff09; 为了避免&#xff0c;在大规模程序的设计中&#xff0c;以及在程序员使用各种各样的C库时&#xff0c;这些标识符的命名发送冲突。 标准C引入了关键字namespace&#xff0c;可以更好地控制标识符的作用域。 st…...

Linux Mem -- Where the mte store and check in the real hardware platform

目录 1 前言 2 MTE tag分类 3 Address tag 4 Memory tag 5 Tag Check 6 Cortex-A710 和 CI-700 系统示例&#xff1a; 1 前言 ARM的MTE允许分配、设置、比较一个 4bit的allocation tag 为16字节粒度的物理地址。当对MTE有一定了解后&#xff0c;应该会产生如下疑问&#…...

老牌软件,如今依旧坚挺

今天给大家介绍一个非常好用的老牌电脑清理软件&#xff0c;这个软件好多年之前就有人使用了。 今天找出来之后&#xff0c;发现还是那么的好用&#xff0c;功能非常强大。 Red Button 电脑清理软件 软件是绿色版&#xff0c;无需安装&#xff0c;打开这个图标就能直接使用了…...

springboot整合modbus实现通讯

springboot整合modbus4j实现tcp通讯 前言 本文基于springboot和modbus4j进行简单封装&#xff0c;达到开箱即用的目的&#xff0c;目前本方案仅实现了tcp通讯。代码会放在最后&#xff0c;按照使用方法操作后就可以直接使用 介绍 在使用本方案之前&#xff0c;有必要对modb…...

【java面试】线程篇

1.什么是线程&#xff1f; 线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。 2.线程和进程有什么区别&#xff1f; 线程是进程的子集&#xff0c;一个进程可以有很多线程&#xff0c;每条线程并行执行不同的任…...

DeepSeek官方发布R1模型推荐设置

今年以来&#xff0c;DeepSeek便在AI领域独占鳌头&#xff0c;热度一骑绝尘。其官方App更是创造了惊人纪录&#xff0c;成为史上最快突破3000万日活的应用&#xff0c;这一成绩无疑彰显了它在大众中的超高人气与强大吸引力。一时间&#xff0c;各大AI及云服务厂商纷纷投身其中&…...

Vue CLI 配置与插件

Vue CLI 配置与插件 今天我们来聊聊 Vue CLI 的配置与插件。随着项目复杂度的增加&#xff0c;合理配置 Vue CLI 可以帮助我们更高效地管理项目&#xff0c;同时利用插件机制快速集成各种功能。下面我就和大家详细介绍如何配置 Vue CLI&#xff0c;以及如何使用和开发插件&…...

Spring Boot (maven)分页3.0版本 通用版

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…...

pip 与 conda 的故事

pip 换源 pip 官方源 -i https://pypi.python.org/simple pip 清华源 -i https://pypi.tuna.tsinghua.edu.cn/simple pip 阿里源 -i https://mirrors.aliyun.com/pypi/simple PyTorch 安装 pip3 install torch torchvision torchaudio pip3 install torch torchvision torchaud…...

清华大学KVCache.AI团队联合趋境科技联合的KTransformers开源项目为什么那么厉害

KTransformers是一个由清华大学KVAV.AI团队开发的开源项目&#xff0c;旨在优化大语言模型&#xff08;LLM&#xff09;的推理性能&#xff0c;特别是在有限显存资源下运行大型模型。以下是KTransformers的详细介绍&#xff1a; 1. 核心特点 高性能优化&#xff1a;KTransfor…...

DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”_deepseek ddos

当算力博弈升级为网络战争&#xff1a;拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下&#xff0c;网络已然成为人类社会运转的关键基础设施&#xff0c;深刻融入经济、生活、政务等各个领域。从金融交易的实时清算&#xf…...

4090单卡挑战DeepSeek r1 671b:尝试量化后的心得的分享

引言&#xff1a; 最近&#xff0c;DeepSeek-R1在完全开源的背景下&#xff0c;与OpenAI的O1推理模型展开了激烈竞争&#xff0c;引发了广泛关注。为了让更多本地用户能够运行DeepSeek&#xff0c;我们成功将R1 671B参数模型从720GB压缩至131GB&#xff0c;减少了80%&#xff…...

【动态路由】系统Web URL资源整合系列(后端技术实现)【apisix实现】

需求说明 软件功能需求&#xff1a;反向代理功能&#xff08;描述&#xff1a;apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 业务应用等多个web资…...

【Elasticsearch】通过运行时字段在查询阶段动态覆盖索引字段

在 Elasticsearch 中&#xff0c;Override field values at query time是指通过运行时字段&#xff08;runtime fields&#xff09;在查询阶段动态覆盖索引字段的值&#xff0c;而无需修改原始索引数据。这种功能特别适用于以下场景&#xff1a; 1. 动态修改字段值&#xff1a…...

【stm32】定时器

stm32f4xx&#xff1a; APB2 ----> TIM1,TIM8,TIM9,TIM10,TIM11 APB1 ----> TIM2,TIM3,TIM4,TIM5,TIM6,TIM7,TIM12,TIM13,TIM14 一、定时器介绍 1、基本定时器 1.1、TIM6 和 TIM7 的主要特性 ● 16 位自动重载递增计数器 ● 16 位可编程…...

滑动窗口算法篇:连续子区间与子串问题

1.滑动窗口原理 那么一谈到子区间的问题&#xff0c;我们可能会想到我们可以用我们的前缀和来应用子区间问题&#xff0c;但是这里对于子区间乃至子串问题&#xff0c;我们也可以尝试往滑动窗口的思路方向去进行一个尝试&#xff0c;那么说那么半天&#xff0c;滑动窗口是什么…...

华三交换机-链路聚合配置案例

目录 1.链路聚合简述:2.链路聚合的作用:3.链路聚合的模式:4.网络拓扑:5.实验需求:6.网络配置&#xff1a;6.1 链路聚合配置(静态聚合)6.1.1 链路聚合配置:6.1.2 查看链路聚合状态: 6.2 链路聚合配置(动态聚合)6.2.1 链路聚合配置:6.2.2 查看链路聚合状态: 7.网络连通性测试:(接…...

Qwen2-VL 的重大省级,Qwen 发布新旗舰视觉语言模型 Qwen2.5-VL

Qwen2.5-VL 是 Qwen 的新旗舰视觉语言模型&#xff0c;也是上一代 Qwen2-VL 的重大飞跃。 Qwen2.5-VL主要特点 视觉理解事物&#xff1a;Qwen2.5-VL不仅能够熟练识别花、鸟、鱼、昆虫等常见物体&#xff0c;而且还能够分析图像中的文本、图表、图标、图形和布局。 代理性&…...

关系数据库标准语言SQL

1.SOL称为结构化查询语言&#xff0c;它是由1974年由Boyce和Chamberlin提出的&#xff0c;1975年至1979年IBM公司的San Jose Research Laboratory研制了关系数据库管理系统的原型系统SystemR,并实现了这种语言。 2.SQL(Structured Ouery Language)称为结构化查询语言 3.SQL数…...

mysql8.0使用MGR实现高可用与利用MySQL Router构建读写分离MGR集群

MGR是MySQL Group Replication的缩写&#xff0c;即MySQL组复制。 在以往&#xff0c;我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案&#xff0c;但这存在以下几个比较严重的问题&#xff1a; 主从复制间容易发生复制延迟&#xff0c;尤其是在5.6以前的版本…...

《AI大模型开发笔记》MoE模型技术对比(Mixtral,Qwen2-MoE,DeepSeek-v3)

MoE模型技术对比(Mixtral,Qwen2-MoE,DeepSeek-v3) MoE(混合专家)大模型进入爆发期!本期我们对比三大开源MoE LLM:Mixtral、Qwen2-MoE 和最新爆火的 DeepSeek-V3。从 2023 年 Mixtral 开启风潮,到 2024 年 DeepSeek-V3 让全球瞩目,MoE 模型到底经历了怎样的进化? De…...

Vue.js 组件开发深入解析:Vue 2 vs Vue 3

Vue.js 是一个渐进式框架&#xff0c;旨在通过声明式渲染和组件化开发来提高开发效率和可维护性。组件是 Vue 应用的基本组成部分&#xff0c;几乎所有的功能都可以通过组件来实现。随着 Vue 3 的发布&#xff0c;Vue.js 引入了许多新的特性&#xff0c;使得组件的开发变得更加…...

DeepSeek大模型一键部署解决方案:全平台多机分布式推理与国产硬件优化异构计算私有部署

DeepSeek R1 走红后&#xff0c;私有部署需求也随之增长&#xff0c;各种私有部署教程层出不穷。大部分教程只是简单地使用 Ollama、LM Studio 单机运行量化蒸馏模型&#xff0c;无法满足复杂场景需求。一些操作配置也过于繁琐&#xff0c;有的需要手动下载并合并分片模型文件&…...