【微服务】springboot3 集成 Flink CDC 1.17 实现mysql数据同步

目录

一、前言

二、常用的数据同步解决方案

2.1 为什么需要数据同步

2.2 常用的数据同步方案

2.2.1 Debezium

2.2.2 DataX

2.2.3 Canal

2.2.4 Sqoop

2.2.5 Kettle

2.2.6 Flink CDC

三、Flink CDC介绍

3.1 Flink CDC 概述

3.1.1 Flink CDC 工作原理

3.2  Flink CDC数据同步优势

3.3 Flink CDC 适用范围

四、Java集成Flink CDC同步mysql数据

4.1 组件版本选择

4.2 数据准备

4.3 导入组件依赖

4.4 Java代码实现过程

4.4.1 自定义反序列化器

4.4.2 自定义Sink输出

4.4.3 启动任务类

4.4.4 效果测试

五、与springboot整合过程

5.1 自定义监听类

5.2 效果测试

六、写在文末


一、前言

在微服务开发模式下,系统的数据源往往不是一个单一的来源,在实际项目中,往往是多种异构数据源的组合,比如核心业务数据在mysql,日志分析数据在hbase,clickhouse,es等,但是不同的数据源需要配合完成某一类业务的时候,就涉及到数据的整合或数据同步问题,尤其是数据同步的场景可以说是非常常见的,那么有哪些解决方案呢?

二、常用的数据同步解决方案

2.1 为什么需要数据同步

当系统发展到一定阶段,尤其是系统的规模越来越大,业务体量也不断扩大的时候,一个系统可能会用到多种数据存储中间件,而不再是单纯的mysql,pgsql等,甚至一个系统中一个或多个微服务无法再满足业务的需求,而需要单独做数据存储的服务,在类似的场景下,很难避免新的服务需要从原有的微服务中抽取数据,或定期做数据的同步处理,诸如此类的场景还有很多。

2.2 常用的数据同步方案

下图列举了几种主流的用于解决数据同步场景的方案

关于图中几种技术,做如下简单的介绍,便于做技术选型作为对比

2.2.1 Debezium

Debezium是国外⽤户常⽤的CDC组件,单机对于分布式来说,在数据读取能力的拓展上,没有分布式的更具有优势,在大数据众多的分布式框架中(Hive、Hudi等)Flink CDC 的架构能够很好地接入这些框架。

2.2.2 DataX

DataX无法支持增量同步。如果一张Mysql表每天增量的数据是不同天的数据,并且没有办法确定它的产生时间,那么如何将数据同步到数仓是一个值得考虑的问题。DataX支持全表同步,也支持sql查询的方式导入导出,全量同步一定是不可取的,sql查询的方式没有可以确定增量数据的字段的话也不是一个好的增量数据同步方案。

2.2.3 Canal

Canal是用java开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件。Canal主要支持了MySQL的Binlog解析,将增量数据写入中间件中(例如kafka,Rocket MQ等),但是无法同步历史数据,因为无法获取到binlog的变更。

2.2.4 Sqoop

Sqoop主要用于在Hadoop(Hive)与传统的数据库(mysql、postgresql...)间进行数据的传递。Sqoop将导入或导出命令翻译成mapreduce程序来实现,这样的弊端就是Sqoop只能做批量导入,遵循事务的一致性,Mapreduce任务成功则同步成功,失败则全部同步失败。

2.2.5 Kettle

Kettle是一款开源的数据集成工具,主要用于数据抽取、转换和加载(ETL)。它提供了图形化的界面,使得用户可以通过拖拽组件的方式来设计和执行数据集成任务。

  • Kettle 被广泛应用于数据仓库构建、数据迁移、数据清洗等多种场景。
  • 虽然 Kettle 在处理中小型数据集时表现良好,但在处理大规模数据集时可能会遇到性能瓶颈,尤其是在没有进行优化的情况下。
  • Kettle 在运行时可能会消耗较多的内存和 CPU 资源,特别是当处理复杂的转换任务时。

虽然 Kettle 的基本操作相对简单,但对于高级功能和复杂任务的设计,用户仍需投入一定的时间和精力来学习和掌握。

2.2.6 Flink CDC

Flink CDC 基本都弥补了以上框架的不足,将数据库的全量和增量数据一体化地同步到消息队列和数据仓库中;也可以用于实时数据集成,将数据库数据实时入湖入仓;无需像其他的CDC工具一样需要在服务器上进行部署,减少了维护成本,链路更少;完美套接Flink程序,CDC获取到的数据流直接对接Flink进行数据加工处理,一套代码即可完成对数据的抽取转换和写出,既可以使用flink的DataStream API完成编码,也可以使用较为上层的FlinkSQL API进行操作。

三、Flink CDC介绍

3.1 Flink CDC 概述

Flink CDC(Change Data Capture)是指使用 Apache Flink 流处理框架来捕获数据库中的变更记录(即数据变更日志)。这种方式允许开发者实时监控并处理数据库表中的更改事件,比如插入、更新或删除操作。通过这种方式,可以实现数据库之间或者数据库与外部系统的实时数据同步。

3.1.1 Flink CDC 工作原理

Flink CDC 主要依赖于数据库提供的日志或者事务记录,如 MySQL 的 Binlog、PostgreSQL 的 WAL(Write-Ahead Logs)等。Flink CDC 使用专门的连接器(Connector)读取这些日志文件,并将其转换成 Flink 可以处理的数据流。之后,这些数据流可以被进一步处理,如过滤、聚合、转换等,最终输出到目标系统,如另一个数据库、消息队列或其他存储系统。

3.2  Flink CDC数据同步优势

Flink CDC(Change Data Capture)是一种用于捕获数据库变更事件的技术,它能够实现实时的数据同步和流式处理。使用 Apache Flink CDC 进行数据同步具有以下几个主要优势:

  1. 实时性:Flink CDC 能够捕捉到数据库中的任何更改(如插入、更新、删除等),并立即将这些更改作为事件流发送出去,实现了真正的实时数据同步。

  2. 高性能:Flink 是一个高度可扩展的流处理框架,其内置的优化机制使得即使在处理大规模数据流时也能保持高性能。Flink CDC 利用了这些优化技术来保证数据同步的高效执行。

  3. 易用性:Flink 提供了丰富的 API 和预构建的连接器(Connectors),使得集成数据库变得简单。使用 Flink CDC 可以通过配置文件或简单的编程接口轻松设置数据捕获任务。

  4. 灵活性:除了基本的 CDC 功能之外,Flink 还支持各种复杂的流处理操作,如窗口计算、状态管理等。这意味着不仅可以捕获变更数据,还可以在数据同步过程中加入各种数据处理逻辑。

  5. 兼容性广泛:Flink CDC 支持多种数据库系统,包括 MySQL、PostgreSQL、Oracle、SQL Server 等,提供了广泛的兼容性和选择空间。

  6. 容错能力:Flink 内置了强大的状态管理和检查点机制,即使在发生故障的情况下也能保证数据的一致性和准确性。这对于需要高可靠性的数据同步场景非常重要。

  7. 无侵入性:Flink CDC 通常是无侵入性的,不需要对源数据库进行任何修改或添加额外的触发器等组件,减少了对现有系统的干扰。

  8. 支持多种部署方式:无论是部署在本地集群还是云端,Flink 都能很好地支持,这为不同规模的企业提供了灵活的选择。

  9. 社区支持:Apache Flink 拥有一个活跃的开源社区,这不仅意味着有丰富的文档和教程可供参考,也意味着遇到问题时可以快速获得帮助和支持。

Flink CDC 在数据同步方面提供了一个强大且灵活的解决方案,适合那些需要高性能、实时数据处理的应用场景。

3.3 Flink CDC 适用范围

Flink CDC(Change Data Capture)连接器是 Apache Flink 社区为 Flink 提供的一种用于捕获数据库变更事件的工具。它允许用户从关系型数据库中实时捕获表的数据变更,并将这些变更事件转化为流式数据,以便进行实时处理,比如你需要将mysql的数据同步到另一个mysql数据库,就需要使用mysql连接器,如果需要同步mongodb的数据,则需要使用mongodb的连接器。截止到Flink CDC 2.2 为止,支持的连接器:

支Flink CDC 持的Flink版本,在实际使用的时候需要根据版本的对照进行选择:

四、Java集成Flink CDC同步mysql数据

4.1 组件版本选择

网上很多关于Flink CDC的版本都是1.13左右的,这个在当前JDK比较新的版本下已经出现了较多的不兼容,本文以JDK17为基础版本进行说明

编号组件名称版本
1

JDK

17

2

springboot

3.2.2

3

mysql

8.0.23

4

flink cdc

1.17.0

4.2 数据准备

找一个可以用的mysql数据库,在下面创建两张表,一张tb_role,另一张tb_role_copy,仅表名不一样

CREATE TABLE `tb_role` (`id` varchar(32) NOT NULL COMMENT '主键',`role_code` varchar(32) NOT NULL COMMENT '版本号',`role_name` varchar(32) DEFAULT NULL COMMENT '角色名称',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='tb角色表';

4.3 导入组件依赖

pom中添加如下依赖

<!-- Flink CDC 1.17.0版本,与springboot3.0进行整合使用的版本-->
<dependency><groupId>org.apache.flink</groupId><artifactId>flink-clients</artifactId><version>1.17.1</version>
</dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-api-java</artifactId><version>1.17.1</version>
</dependency><dependency><groupId>com.ververica</groupId><artifactId>flink-connector-mysql-cdc</artifactId><version>2.4.2</version>
</dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-base</artifactId><version>1.18.0</version>
</dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-planner_2.12</artifactId><version>1.17.1</version>
</dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-jdbc</artifactId><version>3.0.0-1.16</version>
</dependency>

4.4 Java代码实现过程

案例需求场景:通过Flink CDC ,监听tb_role表数据变化,写入tb_role_copy

4.4.1 自定义反序列化器

反序列化器的目的是为了解析flink cdc监听到mysql表数据变化的日志,以json的形式进行解析,方便对日志中的关键参数进行处理

package com.congge.flink.blog;import com.alibaba.fastjson.JSONObject;
import com.alibaba.ververica.cdc.debezium.DebeziumDeserializationSchema;
import io.debezium.data.Envelope;
import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.util.Collector;
import org.apache.kafka.connect.data.Field;
import org.apache.kafka.connect.data.Schema;
import org.apache.kafka.connect.data.Struct;
import org.apache.kafka.connect.source.SourceRecord;import java.util.List;public class CustomerSchema implements DebeziumDeserializationSchema<String> {/*** 封装的数据格式* {* "database":"",* "tableName":"",* "before":{"id":"","tm_name":""....},* "after":{"id":"","tm_name":""....},* "type":"c u d"* //"ts":156456135615* }*/@Overridepublic void deserialize(SourceRecord sourceRecord, Collector<String> collector) throws Exception {//1.创建JSON对象用于存储最终数据JSONObject result = new JSONObject();//2.获取库名&表名String topic = sourceRecord.topic();String[] fields = topic.split("\\.");String database = fields[1];String tableName = fields[2];Struct value = (Struct) sourceRecord.value();//3.获取"before"数据Struct before = value.getStruct("before");JSONObject beforeJson = new JSONObject();if (before != null) {Schema beforeSchema = before.schema();List<Field> beforeFields = beforeSchema.fields();for (Field field : beforeFields) {Object beforeValue = before.get(field);beforeJson.put(field.name(), beforeValue);}}//4.获取"after"数据Struct after = value.getStruct("after");JSONObject afterJson = new JSONObject();if (after != null) {Schema afterSchema = after.schema();List<Field> afterFields = afterSchema.fields();for (Field field : afterFields) {Object afterValue = after.get(field);afterJson.put(field.name(), afterValue);}}//5.获取操作类型  CREATE UPDATE DELETEEnvelope.Operation operation = Envelope.operationFor(sourceRecord);String type = operation.toString().toLowerCase();if ("create".equals(type)) {type = "insert";}//6.将字段写入JSON对象result.put("database", database);result.put("tableName", tableName);result.put("before", beforeJson);result.put("after", afterJson);result.put("type", type);//7.输出数据collector.collect(result.toJSONString());}@Overridepublic TypeInformation<String> getProducedType() {return BasicTypeInfo.STRING_TYPE_INFO;}
}

4.4.2 自定义Sink输出

Sink即为Flink CDC的输出连接器,即监听到源表数据变化并经过处理后最终写到哪里,以mysql为例,我们在监听到tb_role表数据变化后,同步到tb_role_copy中去

package org.dromara.sync.flink.v2;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.functions.sink.RichSinkFunction;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.sync.config.SyncDsTargetDbConfig;import java.io.Serial;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;/*** 自定义一个mysql的Sink输出器,将监听到的变化数据写到指定的数据库下面的表中* @author zcy*/
@Slf4j
public class MyJdbcSink extends RichSinkFunction<String> {@Serialpublic static final long serialVersionUID = 3153039337754737517L;// 提前声明连接和预编译语句private Connection connection = null;private PreparedStatement insertStmt = null;private PreparedStatement updateStmt = null;private PreparedStatement preparedStatement = null;@Overridepublic void open(Configuration parameters) throws Exception {if(connection ==null){Class.forName("com.mysql.cj.jdbc.Driver");//加载数据库驱动connection = DriverManager.getConnection("jdbc:mysql://IP:3306/db", "root", "123");connection.setAutoCommit(false);//关闭自动提交}}@Overridepublic void invoke(String value, Context context) throws Exception {JSONObject jsonObject = JSONObject.parseObject(value);log.info("监听到数据变化,准备执行sql的变更,参数 jsonObject :【{}】",jsonObject);String type = jsonObject.getString("type");String tableName = "tb_role_copy";String database = jsonObject.getString("database");if(type.equals("insert")){JSONObject after = (JSONObject)jsonObject.get("after");Integer id = after.getInteger("id");String roleCode = after.getString("role_code");String roleName = after.getString("role_name");String sql = String.format("insert into %s.%s values (?,?,?)", database, tableName);insertStmt = connection.prepareStatement(sql);insertStmt.setInt(1, Integer.valueOf(id));insertStmt.setString(2, roleCode);insertStmt.setString(3, roleName);insertStmt.execute();connection.commit();} else if(type.equals("update")){JSONObject after = jsonObject.getJSONObject("after");Integer id = after.getInteger("id");String roleCode = after.getString("role_code");String roleName = after.getString("role_name");String sql = String.format("update %s.%s set role_code = ?, role_name = ? where id = ?", database, tableName);updateStmt = connection.prepareStatement(sql);updateStmt.setString(1, roleCode);updateStmt.setString(2, roleName);updateStmt.setInt(3, id);updateStmt.execute();connection.commit();} else if(type.equals("delete")){JSONObject after = jsonObject.getJSONObject("before");Integer id = after.getInteger("id");String sql = String.format("delete from %s.%s where id = ?", database, tableName);preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, id);preparedStatement.execute();connection.commit();}}@Overridepublic void close() throws Exception {if(insertStmt != null){insertStmt.close();}if(updateStmt != null){updateStmt.close();}if(preparedStatement != null){preparedStatement.close();}if(connection != null){connection.close();}}
}

4.4.3 启动任务类

本例先以main程序运行,在实际进行线上部署使用时,可以打成jar包或整合springboot进行启动即可

package org.dromara.sync.flink.mock;import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.connectors.mysql.table.StartupOptions;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.dromara.sync.flink.MyJdbcSchema;
import org.dromara.sync.flink.v2.MyJdbcSink;public class FlinkCdcMainTest {public static void main(String[] args) throws Exception{StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();MySqlSource<String> mysqlSource = MySqlSource.<String>builder().hostname("IP").port(3306).username("root").password("123456").databaseList("db") // 监听的数据库列表.tableList("db.tb_role") // 监听的表列表.deserializer(new MyJdbcSchema()).startupOptions(StartupOptions.latest()).serverTimeZone("UTC").build();DataStream<String> stream = env.fromSource(mysqlSource, WatermarkStrategy.noWatermarks(), "MySQL Source");// 输出到控制台
//        stream.print();stream.addSink(new MyJdbcSink());env.execute("Flink CDC Job");}
}

4.4.4 效果测试

运行上面的代码,通过控制台可以看到任务已经运行起来了,监听并等待数据源数据变更


测试之前,确保两张表数据是一致的

此时为tb_role表增加一条数据,很快控制台可以监听并输出相关的日志

而后,tb_role_copy表同步新增了一条数据

五、与springboot整合过程

在实际项目中,通常会结合springboot项目整合使用,参考下面的使用步骤

5.1 自定义监听类

可以直接基于启动类改造,也可以新增一个类,实现ApplicationRunner接口,重写里面的run方法

  • 不难发现,run方法里面的代码逻辑即是从上述main方法运行任务里面拷贝过来的;

package org.dromara.sync.flink.v2;import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.connectors.mysql.table.StartupOptions;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.dromara.sync.config.SyncDsSourceDbConfig;
import org.dromara.sync.flink.MyJdbcSchema;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** 启动加载,将该类作为一个监听任务的进程启动并执行* @author Evans*/
@Component
public class MysqlDsListener implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();MySqlSource<String> mysqlSource = MySqlSource.<String>builder().hostname("IP").port(13306).username("root").password("123456").databaseList("db").tableList("db.tb_role").deserializer(new MyJdbcSchema()).startupOptions(StartupOptions.latest()).serverTimeZone("UTC").build();DataStream<String> stream = env.fromSource(mysqlSource, WatermarkStrategy.noWatermarks(), "MySQL Source");// 输出到控制台
//        stream.print();stream.addSink(new MyJdbcSink());env.execute("Flink CDC Job");}
}

5.2 效果测试

启动工程之后,相当于是通过flink cdc启动了一个用于监听数据变更的后台进程

然后我们再在数据库tb_role表增加一条数据,控制台可以看到输出了相关的日志

此时再检查数据表,可以发现tb_role_copy表新增了一条一样的数据

六、写在文末

本文通过较大的篇幅详细介绍了Flink CDC相关的技术,最后通过一个实际案例演示了使用Flink CDC同步mysql表数据的示例,希望对看到的同学有用,本篇到此结束感谢观看。

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

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

相关文章

2014年国赛高教杯数学建模D题储药柜的设计解题全过程文档及程序

2014年国赛高教杯数学建模 D题 储药柜的设计 储药柜的结构类似于书橱&#xff0c;通常由若干个横向隔板和竖向隔板将储药柜分割成若干个储药槽(如图1所示)。为保证药品分拣的准确率&#xff0c;防止发药错误&#xff0c;一个储药槽内只能摆放同一种药品。药品在储药槽中的排列…

PHP2-CTFWeb进阶wp-攻防世界13

CTFWeb进阶wp-攻防世界-PHP2 用了御剑和dirsearch扫描了一下发现什么也没扫描到&#xff0c;其它人好像有扫描到的&#xff0c;看了大佬的wp说有index.phps,去查了下。 phps 文件就是 php 的源代码文件&#xff0c;可以当作一个知识点记住&#xff0c;直接访问/index.phps,得…

基于SSM顶岗实习管理系统JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

维生素对于生活的重要性

在探索健康奥秘的旅途中&#xff0c;维生素作为人体不可或缺的微量营养素&#xff0c;扮演着至关重要的角色。它们虽不直接提供能量&#xff0c;却是酶促反应、细胞代谢、免疫功能乃至心理健康的基石。今天&#xff0c;让我们一同深入探讨人体所需补充的维生素&#xff0c;这些…

Springboot 整合 Java DL4J 实现医学影像诊断功能

&#x1f9d1; 博主简介&#xff1a;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编程&#xff0c;…

智能生成ppt软件哪个好?如何高效生成ppt?

想要快速制作出专业且吸引人的PPT演示文稿吗&#xff1f;ai智能生成ppt工具可以帮你实现这一目标。 无需复杂的设计技巧&#xff0c;也不必花费大量时间&#xff0c;只需几个简单的步骤&#xff0c;就能创造出令人印象深刻的演示文稿。下面是一份免费版教程&#xff0c;让你轻…

Word 首行缩进 2 字符怎么设置?具体步骤演示

在日常的文档编辑和排版中&#xff0c;首行缩进是一个非常常见且重要的排版需求。尤其是在中文文档中&#xff0c;首行缩进能够提高文章的美观度和可读性&#xff0c;使文章结构更加清晰。那 Word 首行缩进 2 字符怎么设置呢&#xff1f;下面就给大家展示具体的操作步骤。 设置…

JavaScript(Web APIs 作用和分类,DOM数是什么,document是什么,根据css选择器来获取DOM元素,修改DOM元素的方式,边量声明)

变量声明 变量声明有三个 var let 和 const建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a; const 语义化更好 很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用 const呢&#xff1f; 实际开发中也是&#xff0c;…

【计网】从零开始认识https协议 --- 保证安全的网络通信

在每个死胡同的尽头&#xff0c; 都有另一个维度的天空&#xff0c; 在无路可走时迫使你腾空而起&#xff0c; 那就是奇迹。 --- 廖一梅 --- 从零开始认识https协议 1 什么是https协议2 https通信方案2.1 只使用对称加密2.2 只使用非对称加密2.3 双方都使用非对称加密2.4 …

TCP/IP协议栈

一、TCP/IP和OSI模型的比较 相同点 两者都是以协议栈的概念为基础 协议栈中的协议彼此相互独立 下层对上层提供服务 不同点 OSI是先有模型&#xff1b;TCP/IP是先有协议&#xff0c;后有模型 OSI是国际标准&#xff0c;适用于各种协议栈&#xff1b;TCP/IP实际标准&…

论文笔记:Pre-training to Match for Unified Low-shot Relation Extraction

论文来源&#xff1a;ACL 2022 论文地址&#xff1a;https://aclanthology.org/2022.acl-long.397.pdf 论文代码&#xff1a;https://github.com/fc-liu/MCMN &#xff08;笔记不易&#xff0c;请勿恶意转载抄袭&#xff01;&#xff01;&#xff01;&#xff09; 目录 A…

外卖点餐系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;外卖员管理&#xff0c;餐厅管理&#xff0c;用户管理&#xff0c;菜品分类管理&#xff0c;菜品信息管理&#xff0c;外卖订单管理&#xff0c;订单配送管理 微信端账号功能包括&#xff1a;系统首页…

linux下编译鸿蒙版curl、openssl

一.环境准备 1.参考说明 NDK开发介绍&#xff1a;https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/napi/ndk-development-overview.md 2.NDK下载 点击介绍页面中的链接可以跳转到相应下载页面&#xff1a; 下载相应版本&#xff1a; 下载完毕后解压到指定目…

.NET 通过C#设置Excel工作表的页面设置

Excel文件数据准备就绪并需要以报告形式呈现时&#xff0c;调整Excel文件的页面设置变得尤为重要&#xff0c;不仅关乎文档的专业外观&#xff0c;还直接影响到打印或电子分享时的可读性和实用性。通过C#来自动化这一过程&#xff0c;不仅可以节省大量手动配置的时间&#xff0…

python 画图|三维散点图输出

【1】引言 在前述学习进程中&#xff0c;已经初步掌握三维动画输出和散点图动画输出基本技能&#xff0c;可通过下述链接直达&#xff1a; python画图|散点图动态输出-CSDN博客 python动画教程|Animations using Matplotlib-官网教程程序解读_如何用python制作微动画-CSDN博…

Docker 教程四 (Docker 镜像加速)

Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;此时可以配置镜像加速器。 目前国内 Docker 镜像源出现了一些问题&#xff0c;基本不能用了&#xff0c;后期能用我再更新下。* Docker 官方和国内很多云服务商都提供了国内加速器服务&#xff0c;例如…

STM32 SPI串行总线

目录 STM32的SPI通信原理 SPI串行总线概述 SPI串行总线互连方式 STM32F1 SPI串行总线的工作原理 SPI串行总线的特征 SPI串行总线的内部结构 SPI串行总线时钟信号的相位和极性 STM32的SPI接口配置 STM32的SPI接口数据发送与接收过程 SPI的HAL 驱动函数 STM32的SPI通信…

vue+ElementUI—实现基础后台管理布局(sideBar+header+appMain)(附源码)

后台管理的模板很多&#xff0c;vue本身就提供了完整的vue-template-admin&#xff0c;vue-admin-beautiful等后台管理系统化框架&#xff0c;但是这些框架正是因为成体系而显得繁重。假如你想搭建一个静态的后台管理模板页面和几个单独的菜单页面&#xff0c;直接就上框架是否…

STM32CubeIDE使用ADC采用DMA重大BUG

问题描述 STM32CubeIDE 1.8.0问题 大牛攻城狮最近调试STM32L151CBT6。由于项目上使用该款芯片做控制电源使用&#xff0c;其中涉及到多路ADC的数据采样。使用STM32CubeIDE 1.8.0版本详细如下图所示 注意这里的使用的软件版本号很关键。采用该款软件搭建工程&#xff0c;第一次…

物联网如何推动工业数字化转型?

全球步入数字经济时代&#xff0c;制造业的数字化转型已成为驱动经济发展的核心引擎。物联网作为工业数字化转型的强力推手&#xff0c;其深度融入不仅促进了生产流程的智能化与自动化&#xff0c;还实现了数据的实时分析与精准决策&#xff0c;为制造业企业带来了前所未有的创…