大数据学习之Flink算子、了解(Transformation)转换算子(基础篇三)

Transformation转换算子(基础篇三)


目录

Transformation转换算子(基础篇三)

三、转换算子(Transformation)

1.基本转换算子

1.1 映射(Map)

1.2 过滤(filter)

1.3 扁平映射(flatmap)

1.4基本转换算子的例子

2.聚合算子(Aggregation)

2.1 按键分区(keyBy)

2.2 简单聚合

2.3 归约聚合(reduce)

3.用户自定义函数(UDF)

3.1 函数类(Function Classes)

3.2 富函数类(Rich Function Classes)

4.物理分区(Physical Partitioning)

4.1 随机分区(shuffle)

4.2 轮询分区(Round-Robin)

4.3 重缩放分区(rescale)

4.4 广播(broadcast)

4.5 全局分区(global)

4.6 自定义分区(Custom)


三、转换算子(Transformation)

数据源读入数据之后,我们就可以使用各种转换算子,将一个或多个 DataStream 转换为新的 DataStream,如图所示。一个Flink程序的核心,其实就是所有的转换操作,它们决定了处理的业务逻辑。

1.基本转换算子

1.1 映射(Map)

map算子接收一个函数作为参数,并把这个函数应用于DataStream的每个元素,最后将函数的返回结果作为结果DataStream中对应元素的值,即将DataStream的每个元素转换成新的元素。

1.2 过滤(filter)

filter 转换操作,顾名思义是对数据流执行一个过滤,通过一个布尔条件表达式设置过滤条件,对于每一个流内元素进行判断,若为 true 则元素正常输出,若为 false 则元素被过滤掉。

1.3 扁平映射(flatmap)

flatMap 操作又称为扁平映射,主要是将数据流中的整体(一般是集合类型)拆分成一个一个的个体使用。消费一个元素,可以产生 0 到多个元素。flatMap 可以认为是“扁平化”(flatten)和“映射”(map)两步操作的结合,也就是先按照某种规则对数据进行打散拆分,再对拆分后的元素做转换处理

1.4基本转换算子的例子

代码如下:

import org.apache.flink.streaming.api.scala._object Practice_of_Simple_Operators {def main(args: Array[String]): Unit = {val env = StreamExecutionEnvironment.getExecutionEnvironmentenv.setParallelism(1) //设置并行度为1//常见的简单算子 有:map、flatmap、filter//map//从集合中获取不同数据类型数据val dataStream1 = env.fromCollection(List(1,2,3))//对每一个数 都乘以2val resultStream1 = dataStream1.map(data => data * 2)resultStream1.print("resultStream1")//flatmapval dataStream2 = env.fromCollection(List("hello word","hello flink","hello spark"))val resultStream2 = dataStream2.flatMap(_.split(" "))resultStream2.print("resultStream2")//filterval resultStream3 = dataStream1.filter(_%2==0)resultStream3.print("resultStream3")env.execute("Stream Transform")//启动flink作业}
}

运行结果:

2.聚合算子(Aggregation)

  • 直观上看,基本转换算子确实是在“转换”——因为它们都是基于当前数据,去做了处理和输出。

  • 而在实际应用中,我们往往需要对大量的数据进行统计或整合,从而提炼出更有用的信息。比如之前 word count 程序中,要对每个词出现的频次进行叠加统计。这种操作,计算的结果不仅依赖当前数据,还跟之前的数据有关,相当于要把所有数据聚在一起进行汇总合并——这就是所谓的“聚合”(Aggregation),也对应着 MapReduce 中的 reduce 操作。

2.1 按键分区(keyBy)
  • 对于 Flink 而言,DataStream是没有直接进行聚合的API 的。因为我们对海量数据做聚合肯定要进行分区并行处理,这样才能提高效率。所以在 Flink 中,要做聚合,需要先进行分区; 这个操作就是通过keyBy来完成的。

  • keyBy 是聚合前必须要用到的一个算子。keyBy 通过指定键(key),可以将一条流从逻辑上划分成不同的分区(partitions)。这里所说的分区,其实就是并行处理的子任务,也就对应着任务槽(task slot)。

  • 基于不同的key,流中的数据将被分配到不同的分区中去;这样一来,所有具有相同的key 的数据,都将被发往同一个分区,那么下一步算子操作就将会在同一个 slot 中进行处理了。

  • keyBy算子主要作用于元素类型是元组或数组的DataStream上。使用该算子可以将DataStream中的元素按照指定的key(字段)进行分组,具有相同key的元素将进入同一个分区中(不进行聚合),并且不改变原来元素的数据结构。在逻辑上将流划分为不相交的分区,在内部是通过哈希分区实现的。

//配置执行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
//fromElements --> 给一个固定的元素集合 创建一个数据流(DataStream)
//数据流是以键值对的形式存在的
val source = env.fromElements((1, 2), (2, 1),(1, 6), (1, 9), (1, 7),  (2, 2), (2, 10), (3, 1))
//keyby算子
source.keyBy(temp => temp._1).print("result")// 执行 Flink 作业
env.execute("Flink FromElements Example")

运行结果:

2.2 简单聚合
  • 有了按键分区的数据流 KeyedStream,我们就可以基于它进行聚合操作了。Flink 为我们 内置实现了一些最基本、最简单的聚合 API,主要有以下几种:

    • sum():在输入流上,对指定的字段做叠加求和的操作。

    • min():在输入流上,对指定的字段求最小值。

    • max():在输入流上,对指定的字段求最大值。

    • minBy():与 min()类似,在输入流上针对指定字段求最小值。

      不同的是,min()只计算指定字段的最小值,其他字段会保留最初第一个数据的值;

      而 minBy()则会返回包含字段最小值的整条数据。

    • maxBy():与 max()类似,在输入流上针对指定字段求最大值。

      不同的是,max()只计算指定字段的最大值,其他字段会保留最初第一个数据的值;

      而 maxBy()则会返回包含字段最大值的整条数据。

  • 简单聚合算子使用非常方便,语义也非常明确。这些聚合方法调用时,也需要传入参数; 但并不像基本转换算子那样需要实现自定义函数,只要说明聚合指定的字段就可以了。指定字 段的方式有两种:指定位置,和指定名称。 对于元组类型的数据,同样也可以使用这两种方式来指定字段。需要注意的是,元组中字 段的名称,是以1、2、_3、…来命名的。 例如,下面就是对元组数据流进行聚合的测试:

  • 对于元组类型的数据,同样也可以使用这两种方式来指定字段。需要注意的是,元组中字 段的名称,是以1、2、_3、…来命名的。

测试:

import org.apache.flink.streaming.api.scala._object TransTupleAggregation {def main(args: Array[String]): Unit = {val env = StreamExecutionEnvironment.getExecutionEnvironmentenv.setParallelism(1)val stream = env.fromElements(("a", 1), ("a", 3), ("b", 3), ("b", 4))stream.print("原数据")stream.keyBy(_._1).sum(1).print() //对元组的索引 1 位置数据求和stream.keyBy(_._1).sum("_2").print() //对元组的第 2 个位置数据求和stream.keyBy(_._1).max(1).print() //对元组的索引 1 位置求最大值stream.keyBy(_._1).max("_2").print() //对元组的第 2 个位置数据求最大值stream.keyBy(_._1).min(1).print() //对元组的索引 1 位置求最小值stream.keyBy(_._1).min("_2").print() //对元组的第 2 个位置数据求最小值stream.keyBy(_._1).maxBy(1).print() //对元组的索引 1 位置求最大值stream.keyBy(_._1).maxBy("_2").print() //对元组的第 2 个位置数据求最大值stream.keyBy(_._1).minBy(1).print() //对元组的索引 1 位置求最小值stream.keyBy(_._1).minBy("_2").print() //对元组的第 2 个位置数据求最小值env.execute()}
}

而如果数据流的类型是样例类,那么就只能通过字段名称来指定,不能通过位置来指定了。

import org.apache.flink.streaming.api.scala._
object TransAggregationCaseClass {def main(args: Array[String]): Unit = {val env = StreamExecutionEnvironment.getExecutionEnvironmentenv.setParallelism(1)val stream = env.fromElements(Event("Mary", "./home", 1000L),Event("Bob", "./cart", 2000L))// 使用 user 作为分组的字段,并计算最大的时间戳stream.keyBy(_.user).max("timestamp").print()env.execute()}
}

一个聚合算子,会为每一个key保存一个聚合的值,在Flink中我们把它叫作“状态”(state)。 所以每当有一个新的数据输入,算子就会更新保存的聚合结果,并发送一个带有更新后聚合值 的事件到下游算子。对于无界流来说,这些状态是永远不会被清除的,所以我们使用聚合算子, 应该只用在含有有限个 key 的数据流上。

2.3 归约聚合(reduce)
  • 与简单聚合类似,reduce()操作也会将 KeyedStream 转换为 DataStream。它不会改变流的 元素数据类型,所以输出类型和输入类型是一样的。

  • 调用 KeyedStream 的 reduce()方法时,需要传入一个参数,实现 ReduceFunction 接口。接 口在源码中的定义如下:

public interface ReduceFunction<T> extends Function, Serializable {T reduce(T value1, T value2) throws Exception;
}

ReduceFunction 接口里需要实现 reduce()方法,这个方法接收两个输入事件,经过转换处 理之后输出一个相同类型的事件;所以,对于一组数据,我们可以先取两个进行合并,然后再 将合并的结果看作一个数据、再跟后面的数据合并,最终会将它“简化”成唯一的一个数据, 这也就是 reduce“归约”的含义。在流处理的底层实现过程中,实际上是将中间“合并的结果” 作为任务的一个状态保存起来的;之后每来一个新的数据,就和之前的聚合状态进一步做归约。

下面我们来看一个稍复杂的例子。

我们将数据流按照用户 id 进行分区,然后用一个 reduce()算子实现 sum()的功能,统计每 个用户访问的频次;进而将所有统计结果分到一组,用另一个 reduce()算子实现 maxBy()的功 能,记录所有用户中访问频次最高的那个,也就是当前访问量最大的用户是谁。

import org.apache.flink.streaming.api.scala._object TransReduce {def main(args: Array[String]): Unit = {val env = StreamExecutionEnvironment.getExecutionEnvironmentenv.setParallelism(1)env.addSource(new ClickSource).map(r => (r.user, 1L))//按照用户名进行分组.keyBy(_._1)//计算每个用户的访问频次.reduce((r1, r2) => (r1._1, r1._2 + r2._2))//将所有数据都分到同一个分区.keyBy(_ => true)//通过 reduce 实现 max 功能,计算访问频次最高的用户.reduce((r1, r2) => if (r1._2 > r2._2) r1 else r2).print()env.execute()}
}

reduce()同简单聚合算子一样,也要针对每一个 key 保存状态。因为状态不会清空,所以 我们需要将 reduce()算子作用在一个有限 key 的流上。

3.用户自定义函数(UDF)

3.1 函数类(Function Classes)
3.2 富函数类(Rich Function Classes)

4.物理分区(Physical Partitioning)

4.1 随机分区(shuffle)

4.2 轮询分区(Round-Robin)

4.3 重缩放分区(rescale)

4.4 广播(broadcast)
4.5 全局分区(global)
4.6 自定义分区(Custom)

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

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

相关文章

Redis应用(1)缓存(1.2)------Redis三种缓存问题

三者出现的根本原因是&#xff1a;Redis缓存命中率下降&#xff0c;请求直接打到DB上了。 一、 缓存穿透&#xff1a; 1、定义&#xff1a; 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。…

C++PythonC# 三语言OpenCV从零开发(4):视频流读取

文章目录 相关链接视频流读取CCSharpPython 总结 相关链接 C&Python&Csharp in OpenCV 专栏 【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程&#xff08;附带课程课件资料课件笔记&#xff09; OpenCV 教程中文文档|OpenCV中文 OpenCV教程中文文档|W3Csc…

RabbitMQ 入门到精通

RabbitMQ入门到精通 一、了解RabbitMQ1.基础知识2.多种交换机模型详解 二、服务端搭建1.简单搭建2.信息持久化到容器外部 三、消息生产者和消费者1.消息生产者2.消息消费者3.RabbitTemplate 详解4.RabbitListener详解5.其他注解 四、如何保证消息可靠性1.发送方进行消息发送成功…

Go 虚拟环境管理工具 gvm 原理介绍与使用指南

本文谈下我对 Go 版本管理的一些想法。让后&#xff0c;我将介绍一个小工具&#xff0c;gvm。这个话题说起来也很简单&#xff0c;但如果想用的爽&#xff0c;还是要稍微梳理下。 背景介绍 Go 的版本管理&#xff0c;并非包的依赖管理&#xff0c;而且关于如何在不同的 Go 版…

期待已久!阿里云容器服务 ACK AI 助手正式上线

作者&#xff1a;行疾 大模型技术的蓬勃发展持续引领 AI 出圈潮流&#xff0c;各行各业都在尝试采用 AI 工具实现智能增效。 2023 年云栖大会上&#xff0c;阿里云容器服务团队正式发布 ACK AI 助手&#xff0c;带来大模型增强智能诊断&#xff0c;帮助企业和开发者降低 K8s …

Spark运行架构以及容错机制

Spark运行架构以及容错机制 1. Spark的角色区分1.1 Driver1.2 Excuter 2. Spark-Cluster模式的任务提交流程2.1 Spark On Yarn的任务提交流程2.1.1 yarn相关概念2.1.2 任务提交流程 2.2 Spark On K8S的任务提交流程2.2.1 k8s相关概念2.2.2 任务提交流程 3. Spark-Cluster模式的…

BACnet网关BA100实现Modbus转BACnet,专为Modbus协议设备与BA系统的高效对接设计

随着物联网技术的迅猛发展&#xff0c;人们深刻认识到在智能化生产和生活中&#xff0c;实时、可靠、安全的数据传输至关重要。在此背景下&#xff0c;高性能的物联网数据传输解决方案——协议转换网关应运而生&#xff0c;广泛应用于工业自动化和数字化工厂应用环境中。 钡铼…

搜维尔科技:【简报】元宇宙数字人赛道,《莉思菱娜》

个性有些古灵精怪时儿安静时而吵闹&#xff0c;虽然以人类寿命来算已经200多岁但在 吸血鬼中还只是个小毛头&#xff0c;从中学开始喜欢打扮偏爱黑白灰色系的服装喜欢时 尚圈&#xff0c;立志想成为美妆或时尚网红不过目前还是学生&#xff0c;脸上的浅色血迹是纹身 贴纸&#…

深度学习-循环神经网络-RNN实现股价预测-LSTM自动生成文本

序列模型(Sequence Model) 基于文本内容及其前后信息进行预测 基于目标不同时刻状态进行预测 基于数据历史信息进行预测 序列模型:输入或者输出中包含有序列数据的模型 突出数据的前后序列关系 两大特点: 输入(输出)元素之间是具有顺序关系。不同的顺序,得到的结果应…

安全基础~通用漏洞1

文章目录 知识补充Acess数据库注入MySQL数据库PostgreSQL-高权限读写注入MSSQL-sa高权限读写执行注入Oracle 注入Mongodb 注入sqlmap基础命令 知识补充 order by的意义&#xff1a; union 操作符用于合并两个或多个 select语句的结果集。 union 内部的每个 select 语句必须拥有…

哈希--73. 矩阵置零/medium 理解度A

73. 矩阵置零 1、题目2、题目分析3、复杂度最优解代码示例4、适用场景 1、题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,…

$.ajax与同源策略

1.jQuery中的ajax请求 学习Jquery中的ajax,我们借助官方文档 $.ajax(url,[settings]) | jQuery API 3.2 中文文档 | jQuery API 在线手册 使用$.ajax()方法完成图书案例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&quo…

mc我的世界服务器多少钱一个月?

我的世界服务器多少钱一个月&#xff1f;低至7元一个月&#xff0c;阿里云和腾讯云均可以选择mc服务器&#xff0c;阿里云2核2G3M轻量服务器87元一年、腾讯云轻量2核2G3M服务器88元一年&#xff0c;阿里云ECS云服务器2核2G3M带宽99元一年&#xff0c;腾讯云2核4G5M带宽轻量应用…

RabbitMQ中交换机的应用 ,原理 ,案例的实现

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《RabbitMQ中交换机的应用及原理&#xff0c;案…

8.Gateway服务网关

3.Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式…

JVM工作原理与实战(二十五):堆的垃圾回收-垃圾回收算法

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、垃圾回收算法介绍 1.垃圾回收算法的历史和分类 2.垃圾回收算法的评价标准 二、垃圾回收算法详解 1.标记清除算法 2.复制算法 3.标记整理算法 4.分代垃圾回收算法 总结 前言…

密码学的100个基本概念

密码学作为信息安全的基础&#xff0c;极为重要,本文分为上下两部分&#xff0c;总计10个章节&#xff0c;回顾了密码学的100个基本概念&#xff0c;供小伙伴们学习参考。本文将先介绍前五个章节的内容。 一、密码学历史 二、密码学基础 三、分组密码 四、序列密码 五、哈希…

生命在于折腾——WeChat机器人的研究和探索

一、前言 2022年&#xff0c;我玩过原神&#xff0c;当时看到了云崽的QQ机器人&#xff0c;很是感兴趣&#xff0c;支持各种插件&#xff0c;查询游戏内角色相关信息&#xff0c;当时我也自己写了几个插件&#xff0c;也看到很多大佬编写的好玩的插件&#xff0c;后来因为QQ不…

数据结构:搜索二叉树 | 红黑树 | 验证是否为红黑树

文章目录 1.红黑树的概述2.红黑树的性质3.红黑树的代码实现3.1.红黑树的节点定义3.2.红黑树的插入操作3.3.红黑树是否平衡 黑红树是一颗特殊的搜索二叉树&#xff0c;本文在前文的基础上&#xff0c;图解红黑树插入&#xff1a;前文 链接&#xff0c;完整对部分关键代码展示&a…

SG-8506CA 可编程晶体振荡器 (SPXO)

输出: LV-PECL频率范围: 50MHz ~ 800MHz电源电压: 2.5V to 3.3V外部尺寸规格: 7.0 5.0 1.5mm (8引脚)特性:用户指定一个起始频率, 7-bit I2C 地址:用户可编程: I2C 接口:基频的高频晶体:低抖动PLL技术应用:OTN, BTS, 测试设备 规格&#xff08;特征&#xff09; *1 这包括初…