大数据-玩转数据-FLINK快速上手

news2024/11/23 19:33:00

一、环境准备

⚫系统环境为 Windows 10。
⚫需提前安装 Java 11。
⚫集成开发环境(IDE)使用 IntelliJ IDEA,具体的安装流程参见 IntelliJ 官网。
⚫安装 IntelliJ IDEA 之后,还需要安装一些插件——Maven 和 Git。Maven 用来管理项目依赖;通过 Git 可以轻松获取我们的示例代码,并进行本地代码的版本控制。
另外需要特别说明的是:
⚫本书全部 Flink 程序全部基于 Flink 1.13.0。

二、创建项目

首先我们要做的,就是在 IDEA 中搭建一个 Flink 项目的骨架。我们会使用 Java 项目中常见的 Maven 来进行依赖管理。
创建工程
(1)打开 IntelliJ IDEA,创建一个 Maven 工程,如图 2-1 所示。
在这里插入图片描述
(2)将这个 Maven 工程命名为 FlinkTutorial,如图 2-2 所示。
在这里插入图片描述
(3)选定这个 Maven 工程所在存储路径,并点击 Finish,Maven 工程即创建成功。

添加项目依赖在项目的 pom 文件中,增加标签设置属性,然后增加标签引入需要的依赖。我们需要添加的依赖最重要的就是 Flink 的相关组件,包括 flink-java、 flink-streaming-java,以及 flink-clients(客户端,也可以省略)。另外,为了方便查看运行日志,我们引入 slf4j 和 log4j 进行日志管理。

<properties> 
    <flink.version>1.13.0</flink.version> 
    <java.version>11</java.version> 
    <scala.binary.version>2.12</scala.binary.version> 
    <slf4j.version>1.7.30</slf4j.version> 
</properties> 
 
<dependencies> 
<!-- 引入Flink相关依赖--> 
    <dependency> 
        <groupId>org.apache.flink</groupId> 
        <artifactId>flink-java</artifactId> 
        <version>${flink.version}</version> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.flink</groupId>         <artifactId>flink-streaming-java_${scala.binary.version}</artifactId> 
        <version>${flink.version}</version> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.flink</groupId> 
        <artifactId>flink-clients_${scala.binary.version}</artifactId> 
        <version>${flink.version}</version> 
</dependency> 
<!-- 引入日志管理相关依赖--> 
    <dependency> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-api</artifactId> 
        <version>${slf4j.version}</version> 
    </dependency> 
    <dependency> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-log4j12</artifactId> 
        <version>${slf4j.version}</version> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.logging.log4j</groupId> 
        <artifactId>log4j-to-slf4j</artifactId> 
        <version>2.14.0</version> 
</dependency> 
</dependencies> 

这里做一点解释:
在属性中,我们定义了<scala.binary.version>,这指代的是所依赖的 Scala 版本。这有一点奇怪:Flink 底层是 Java,而且我们也只用 Java API,为什么还会依赖 Scala 呢?这是因为 Flink 的架构中使用了 Akka 来实现底层的分布式通信,而 Akka 是用 Scala 开发的。我们本书中用到的 Scala 版本为 2.12。

配置日志管理
在目录 src/main/resources 下添加文件:log4j.properties,内容配置如下:

log4j.rootLogger=error, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

三、编写代码

搭好项目框架,接下来就是我们的核心工作——往里面填充代码。我们会用一个最简单的示例来说明 Flink 代码怎样编写:统计一段文字中,每个单词出现的频次。这就是传说中的WordCount 程序——它是大数据领域非常经典的入门案例,地位等同于初学编程语言时的 Hello World。
我们的源码位于 src/main/java 目录下。首先新建一个包,命名为 com.lyh.wc,在这个包下我们将编写 Flink 入门的 WordCount 程序。
我们已经知道,尽管 Flink 自身的定位是流式处理引擎,但它同样拥有批处理的能力。所以接下来,我们会针对不同的处理模式、不同的输入数据形式,分别讲述 WordCount 代码的实现。

(1)批处理

对于批处理而言,输入的应该是收集好的数据集。这里我们可以将要统计的文字,写入一个文本文档,然后读取这个文件处理数据就可以了。
(1)在工程根目录下新建一个 input 文件夹,并在下面创建文本文件 words.txt
(2)在 words.txt 中输入一些文字,例如:
hello world
hello flink
hello java
(3)在 com.lyh.chapter02 包下新建 Java 类 BatchWordCount,在静态 main 方法中编写测试代码。
我们进行单词频次统计的基本思路是:先逐行读入文件数据,然后将每一行文字拆分成单词;接着按照单词分组,统计每组数据的个数,就是对应单词的频次。
具体代码实现如下:

package com.lyh.chapter02;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.operators.AggregateOperator;
import org.apache.flink.api.java.operators.DataSource;
import org.apache.flink.api.java.operators.FlatMapOperator;
import org.apache.flink.api.java.operators.UnsortedGrouping;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;


public class BatchWordCount {
    public static void main(String[] args) throws Exception {
        //todo 1 创建执行环境
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        //todo 2 从文件读取数据,按行读取(存储的元素就是每行的文本)
        DataSource<String> lineDS = env.readTextFile("input/word.txt");
        //todo 3 转换数据模式
        FlatMapOperator<String, Tuple2<String, Long>> wordAndOne = lineDS
                .flatMap((String line, Collector<Tuple2<String, Long>> out) -> {
                    String[] split = line.split(" ");
                    for (String word: split) {
                        out.collect(Tuple2.of(word, 1L));
                    }
                })
                .returns(Types.TUPLE(Types.STRING, Types.LONG));

        //todo 4 按照word进行分组
        UnsortedGrouping<Tuple2<String, Long>> wordAndOneUG = wordAndOne.groupBy(0);

        //todo 5 分组内聚合统计
        AggregateOperator<Tuple2<String, Long>> sum = wordAndOneUG.sum(1);

        //todo 6 打印结果
        sum.print();
    }
}

代码说明和注意事项:
①Flink 在执行应用程序前应该获取执行环境对象,也就是运行时上下文环境。
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
②Flink 同时提供了 Java 和 Scala 两种语言的 API,有些类在两套 API 中名称是一样的。
所以在引入包时,如果有 Java 和 Scala 两种选择,要注意选用 Java 的包。
③直接调用执行环境的 readTextFile 方法,可以从文件中读取数据。
④我们的目标是将每个单词对应的个数统计出来,所以调用 flatmap 方法可以对一行文字进行分词转换。将文件中每一行文字拆分成单词后,要转换成(word,count)形式的二元组,初始 count 都为 1。returns 方法指定的返回数据类型 Tuple2,就是 Flink 自带的二元组数据类型。
⑤ 在分组时调用了 groupBy 方法,它不能使用分组选择器,只能采用位置索引或属性名称进行分组。

// 使用索引定位
dataStream.groupBy(0)
// 使用类属性名称
dataStream.groupBy(“id”)
在分组之后调用 sum 方法进行聚合,同样只能指定聚合字段的位置索引或属性名称。
(4) 运行程序,控制台会打印出结果:

(java,1)
(flink,1)
(world,1)
(hello,3)

可以看到,我们将文档中的所有单词的频次,全部统计出来,以二元组的形式在控制台打印输出了。
需要注意的是,这种代码的实现方式,是基于 DataSet API 的,也就是我们对数据的处理转换,是看作数据集来进行操作的。事实上Flink 本身是流批统一的处理架构,批量的数据集本质上也是流,没有必要用两套不同的 API 来实现。所以从Flink 1.12开始,官方推荐的做法是直接使用 DataStream API,在提交任务时通过将执行模式设为 BATCH 来进行批处理:

$ bin/flink run -Dexecution.runtime-mode=BATCH BatchWordCount.jar 

这样,DataSet API 就已经处于“软弃用”(soft deprecated)的状态,在实际应用中我们只要维护一套 DataStream API 就可以了。这里只是为了方便大家理解,我们依然用 DataSet API 做了批处理的实现。

(2)流处理

读取文件
我们同样试图读取文档 words.txt 中的数据,并统计每个单词出现的频次。这是一个“有界流”的处理,整体思路与之前的批处理非常类似,代码模式也基本一致。
(1)在 com.lyh.wc 包下新建 Java 类 BoundedStreamWordCount,在静态 main 方法中编写测试代码。具体代码实现如下:

package com.lyh.wc;

import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
import java.util.Arrays;
public class BoundedStreamWordCount {
    public static void main(String[] args)
            throws Exception {
    // 1. 创建流式执行环境
            StreamExecutionEnvironment 	env 	=
                StreamExecutionEnvironment.getExecutionEnvironment();
    // 2. 读取文件
            DataStreamSource<String> lineDSS = env.readTextFile("input/word.txt");
    // 3. 转换数据格式
             SingleOutputStreamOperator<Tuple2<String, Long>> wordAndOne = lineDSS
            .flatMap((String line, Collector<String> words) -> {
                Arrays.stream(line.split(" ")).forEach(words::collect);
            })
            .returns(Types.STRING)
            .map(word -> Tuple2.of(word, 1L))
            .returns(Types.TUPLE(Types.STRING, Types.LONG));
    // 4. 分组
            KeyedStream<Tuple2<String, Long>, String> wordAndOneKS = wordAndOne
            .keyBy(t -> t.f0);
    // 5. 求和
            SingleOutputStreamOperator<Tuple2<String, Long>> result = wordAndOneKS
            .sum(1);         // 6. 打印
         result.print();         // 7. 执行
         env.execute();
        }
    }

主要观察与批处理程序 BatchWordCount 的不同:
⚫创建执行环境的不同,流处理程序使用的是 StreamExecutionEnvironment。
⚫每一步处理转换之后,得到的数据对象类型不同。
⚫分组操作调用的是 keyBy 方法,可以传入一个匿名函数作为键选择器
(KeySelector),指定当前分组的 key 是什么。
⚫代码末尾需要调用 env 的 execute 方法,开始执行任务。
(2)运行程序,控制台输出结果如下:

3> (world,1)
2> (hello,1)
4> (flink,1)
2> (hello,2)
2> (hello,3)
1> (java,1)

我们可以看到,这与批处理的结果是完全不同的。批处理针对每个单词,只会输出一个最终的统计个数;而在流处理的打印结果中,“hello”这个单词每出现一次,都会有一个频次统计数据输出。这就是流处理的特点,数据逐个处理,每来一条数据就会处理输出一次。我们通过打印结果,可以清晰地看到单词“hello”数量增长的过程。

看到这里大家可能又会有新的疑惑:我们读取文件,第一行应该是“hello
flink”,怎么这里输出的第一个单词是“world”呢?每个输出的结果二元组,前面都有一个数字,这又是什么呢?

我们可以先做个简单的解释。Flink 是一个分布式处理引擎,所以我们的程序应该也是分布式运行的。在开发环境里,会通过多线程来模拟
Flink 集群运行。所以这里结果前的数字,其实就指示了本地执行的不同线程,对应着 Flink
运行时不同的并行资源。这样第一个乱序的问题也就解决了:既然是并行执行,不同线程的输出结果,自然也就无法保持输入的顺序了。

另外需要说明,这里显示的编号为 1~4,是由于运行电脑的 CPU 是 4 核,所以默认模拟的并行线程有 4
个。这段代码不同的运行环境,得到的结果会是不同的。关于 Flink
程序并行执行的数量,可以通过设定“并行度”(Parallelism)来进行配置,我们会在后续章节详细讲解这些内容。

四、读取文本流

在实际的生产环境中,真正的数据流其实是无界的,有开始却没有结束,这就要求我们需要保持一个监听事件的状态,持续地处理捕获的数据。

为了模拟这种场景,我们就不再通过读取文件来获取数据了,而是监听数据发送端主机的指定端口,统计发送来的文本数据中出现过的单词的个数。具体实现上,我们只要对
BoundedStreamWordCount 代码中读取数据的步骤稍做修改,就可以实现对真正无界流的处理。

(1)新建一个 Java 类 StreamWordCount,

将 BoundedStreamWordCount 代码中读取文件数据的 readTextFile 方法,替换成读取 socket 文本流的方法 socketTextStream。具体代码实现如下:

import com.lyh.StreamWordCount
import org.apache.flink.api.common.typeinfo.Types; 
import org.apache.flink.api.java.tuple.Tuple2; 
import org.apache.flink.streaming.api.datastream.DataStreamSource; 
import org.apache.flink.streaming.api.datastream.KeyedStream; 
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; 
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; 
import org.apache.flink.util.Collector; 
import java.util.Arrays; 
public class StreamWordCount {     
 	public static void main(String[] args) throws Exception { 
        // 1. 创建流式执行环境 
        StreamExecutionEnvironment 	env 	=
	         StreamExecutionEnvironment.getExecutionEnvironment(); 
        // 2. 读取文本流 
        DataStreamSource<String> lineDSS = env.socketTextStream("hadoop102", 
7777); 
        // 3. 转换数据格式 
        SingleOutputStreamOperator<Tuple2<String, Long>> wordAndOne = lineDSS 
                .flatMap((String line, Collector<String> words) -> { 
                    Arrays.stream(line.split(" ")).forEach(words::collect);                 }) 
                .returns(Types.STRING) 
                .map(word -> Tuple2.of(word, 1L)) 
                .returns(Types.TUPLE(Types.STRING, Types.LONG)); 
        // 4. 分组 
        KeyedStream<Tuple2<String, Long>, String> wordAndOneKS = wordAndOne 
                .keyBy(t -> t.f0); 
        // 5. 求和 
        SingleOutputStreamOperator<Tuple2<String, Long>> result = wordAndOneKS 
                .sum(1);    // 6. 打印  
  result.print();         // 7. 执行         
  env.execute(); 
    } 
} 

代码说明和注意事项:
⚫socket 文本流的读取需要配置两个参数:发送端主机名和端口号。这里代码中指定了主机“hadoop102”的 7777 端口作为发送数据的 socket 端口,读者可以根据测试环境自行配置。
⚫在实际项目应用中,主机名和端口号这类信息往往可以通过配置文件,或者传入程序运行参数的方式来指定。
⚫socket文本流数据的发送,可以通过Linux系统自带的netcat工具进行模拟。

(2)在 Linux 环境的主机 hadoop102 上,执行下列命令,发送数据进行测试:

[lyh@hadoop102 ~]$ nc -lk 7777 

(3)启动 StreamWordCount 程序

我们会发现程序启动之后没有任何输出、也不会退出。这是正常的——因为 Flink 的流处理是事件驱动的,当前程序会一直处于监听状态,只有接收到数据才会执行任务、输出统计结果。

(4)从 hadoop102 发送数据:

hello flink
hello world
hello java
可以看到控制台输出结果如下:

4> (flink,1)
2> (hello,1)
3> (world,1)
2> (hello,2)
2> (hello,3)
1> (java,1)

我们会发现,输出的结果与之前读取文件的流处理非常相似。而且可以非常明显地看到,每输入一条数据,就有一次对应的输出。具体对应关系是:输入“hello flink”,就会输出两条统计结果(flink,1)和(hello,1);之后再输入“hello world”,同样会将 hello 和 world 的个数统计输出,hello 的个数会对应增长为 2。

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

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

相关文章

Java实现宿舍管理系统的设计与实现【附源码】

本科生毕业论文&#xff08;设计&#xff09; 宿舍管理系统的设计与实现 目 录 摘 要 I Abstract II 1 引言 1 1.1 研究背景 1 1.2 国内外研究现状 1 1.3 研究目的与意义 1 2 开发工具和相关技术 2 2.1 Eclipse 2 2.2 MySQL 2 2.3 Bootstrap 3 2.4 Tomcat 3 3 系统分析 3 3.1…

Java基础学习(11)

Java基础学习 一、集合进阶1.1 数据结构&#xff08;树&#xff09;1.1.1 二叉查找树1.1.2 二叉树的遍历 1.2 平衡二叉树树的演变 1.3 数据结构 ( 平衡二叉树 )左旋1.4 数据结构 ( 平衡二叉树 )右旋数据结构 (平衡二叉树)需要转的四种情况 1.5 红黑树添加节点规则 二、Set系列集…

基础算法(五):DFS、BFS与剪枝

前言 前面的基础算法笔记已经断更好久了&#xff0c;因为荔枝觉得还是得先学一下基础的数据结构知识之后才能更好的入门算法。在这篇文章中荔枝主要记录DFS和BFS的相关基础知识、答题的模板以及自己的一些浅薄理解&#xff0c;同样的也会涉及到相关的剪枝操作。 一、搜索算法概…

java基础学习-7

文章目录 异常小总结编译时异常和运行时异常小总结 异常在代码中的两个作用异常的方式JVM虚拟机默认处理异常的方式自己处理&#xff08;捕获异常&#xff09;灵魂四问抛出异常异常中的常见方法小总结小练习 自定义异常 File----路径File的概述和构造方法小总结 File的成员方法…

线性表之顺序表(C语言实现)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:讲解数据结构的入门知识,线性结构之顺序表. 金句分享:…

机器学习笔记 基于深度学习的边缘检测

一、Holistically-Nested Edge Detection 边缘检测是视觉工作中十分常用的技术,传统边缘检测已经包含了很多经典的诸如Canny、Robert等等,都是各有擅场,不过有一点问题,就是很多参数需要人工调试,所以深度学习研究人员提出了基于卷积神经网络的边缘检测算法。 即HED,该算…

uniapp拍照离线定位,获取图片信息,经纬度解析地址

✅作者简介&#xff1a; 我是痴心阿文&#xff0c;你们的学友哥&#xff0c;今天给大家分享uniapp拍照离线定位&#xff0c;获取图片信息&#xff0c;经纬度解析地址 &#x1f4c3;个人主页:痴心阿文的博客_CSDN博客-Vue.js,数组方法,前端领域博主 &#x1f525;本文前言&#…

【数据结构】超详细之顺序表(利用C语言实现)

文章目录 前言一、顺序表是什么&#xff1f;二、顺序表的实现步骤 1.顺序表的初始化以及开辟空间2.实现顺序表的头插、尾插以及打印3.实现顺序表的头删、尾删以及打印4.实现顺序表的查找5.实现顺序表指定位置插入6.实现顺序表指定位置删除7.释放内存总结 前言 数据结构是一个程…

离散数学_九章:关系(3)

9.3 关系的表示 1、用集合表示关系2、用矩阵表示关系矩阵表示关系⭐集合上的关系矩阵 R 自反时 R 对称时 R 反对称时 ⭐确定关系合成的矩阵 3、用有向图表示关系有向图⭐从有向图中 确定关系具有的属性 自反性对称性反对称性传递性 本节及本章的剩余部分研究的所有关系均为二…

函数(详解)——C语言

Hello&#xff0c;友友们前段时间忙拖更了这么久&#xff0c;趁着五一假期好好卷上一波哈哈哈。好的&#xff0c;我们本期主要对C语言中的函数进行讲解。 1.什么是函数 在数学中也常常用到函数&#xff0c;但你对C语言中的函数有了解吗&#xff1f; 在C语言中函数是一段可重…

数据结构学习分享之单链表详解

数据结构第三课 1. 前言2. 链表的概念以及结构3. 链表的分类4.链表的实现4.1 初始化结构4.2 尾插函数4.3 尾删函数4.4 头插函数4.5 头删函数4.6 开辟新节点4.7 销毁链表 5. 单链表OJ题目6. 顺序表和链表的区别7. 总结 1. 前言 &#x1f493;博主CSDN:杭电码农-NEO&#x1f493;…

五年开发经验前端程序员,刚入职一个月就要离职,我来聊聊看法

最近有一个新来的同事&#xff0c;估计又要离职了吧。从他的工作经历来看&#xff0c;大概有5年的前端工作经验&#xff0c;但是头发看起来挺少的&#xff0c;不知道是工作加班导致的&#xff0c;看他的性格不太像是经常加班的。 他这个人就是我们公司人事面试的&#xff0c;虽…

操作系统——进程管理

0.关注博主有更多知识 操作系统入门知识合集 目录 0.关注博主有更多知识 4.1进程概念 4.1.1进程基本概念 思考题&#xff1a; 4.1.2进程状态 思考题&#xff1a; 4.1.3进程控制块PCB 4.2进程控制 思考题&#xff1a; 4.3线程 思考题&#xff1a; 4.4临界资源与临…

躺平减脂减重法补充篇——无需控制碳水摄入的有效方法,另推一种健康的运动和防止老年慢性病的方式...

本文此前已经连续发表了六篇相关文章&#xff0c;内容确实比较多&#xff0c;最近又做了一组实验&#xff0c;进食了大量的锅巴&#xff0c;看看是否会带来体重的增加&#xff0c;每天进食量都不少于200克锅巴&#xff0c;对&#xff0c;4两重&#xff0c;而且是在每天正常进食…

SAPUI5 之XML Views (视图) 笔记

文章目录 官网 Walkthrough学习-XML Views视图案例要求&#xff1a;我们把上面通过index.html body的展示放在XML中展示1.0.1 新增view文件夹1.0.2 在xml文件中新增一个Text 文本1.0.3 在index.js中实例化view视图1.0.4 执行刷新浏览器1.0.5 调试界面分析结果 官网 Walkthrough…

假期给朋友介绍如何学习java和找工作的建议?

Java学习 一、学习Java的建议1. 学习Java基础知识2. 学习Java框架3. 学习Java Web开发4. 学习Java数据库编程5. 学习Java工具6.学习Java中的多线程技术6. 练习编程 二、找工作的建议1. 准备好简历2. 寻找工作机会3. 准备面试4. 提高自己的技能5. 关注行业动态 学习Java和找工作…

第十九章 观察者模式

文章目录 前言普通方式解决问题CurrentConditions 显示当前天气情况WeatherData 管理第三方Clint 测试 一、观察者模式(Observer)原理完整代码SubjectObserverWeatherData implements SubjectCurrentConditions implements ObserverBaiduSite implements ObserverClint 前言 普…

《软件工程教程》(第2版) 主编:吴迪 马宏茹 丁万宁 第十章课后习题参考答案

第十章 面向对象设计 课后习题参考答案 一、单项选择题 &#xff08;1&#xff09;A &#xff08;2&#xff09;B &#xff08;3&#xff09;B &#xff08;4&#xff09;D &#xff08;5&#xff09;A &#xff08;6&#xff09;C&#xff08;7&#xff09;D &#xff0…

【学习心得】Python多版本控制

问题描述&#xff1a;本文主要解决Windows系统下的多个Python版本共存问题。 &#xff08;一&#xff09;安装不同版本Python 官方下载链接&#xff1a;Python Releases for Windows | Python.org 下载如图中所示的版本&#xff08;64位Windows系统可执行安装包版本&#xff0…

赞!数字中国建设峰会上的金仓风采

4月30日&#xff0c;第六届数字中国建设成果展览会圆满落幕。人大金仓深度参与本届峰会&#xff0c;在会上发布产品新版本&#xff0c;展出国产数据库前沿的行业解决方案和创新应用成果&#xff0c;出席国资央企SaaS应用服务共享平台伙伴签约仪式&#xff0c;吸引众多用户、伙伴…