作为一个编程新手,我再也不怕Flink迷了我的眼!

2023-11-14

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由kyledong 发表于云+社区专栏

使用 Flink 编写处理逻辑时,新手总是容易被林林总总的概念所混淆:

为什么 Flink 有那么多的类型声明方式?

BasicTypeInfo.STRING_TYPE_INFO、Types.STRING 、Types.STRING() 有何区别?

TypeInfoFactory 又是什么?

TypeInformation.of 和 TypeHint 是如何使用的呢?

接下来本文将逐步解密 Flink 的类型和序列化机制。

img图 1:Flink 类型分类

Flink 的类型系统源码位于 org.apache.flink.api.common.typeinfo 包,让我们对图 1 深入追踪,看一下类的继承关系图:

img图 2:TypeInformation 类继承关系图

可以看到,图 1 和 图 2 是一一对应的,TypeInformation 类是描述一切类型的公共基类,它和它的所有子类必须可序列化(Serializable),因为类型信息将会伴随 Flink 的作业提交,被传递给每个执行节点。

由于 Flink 自己管理内存,采用了一种非常紧凑的存储格式(见官方博文),因而类型信息在整个数据处理流程中属于至关重要的元数据。

TypeExtractror 类型提取

Flink 内部实现了名为 TypeExtractror 的类,可以利用方法签名、子类信息等蛛丝马迹,自动提取和恢复类型信息(当然也可以显式声明,即本文所介绍的内容)。

然而由于 Java 的类型擦除,自动提取并不是总是有效。因而一些情况下(例如通过 URLClassLoader 动态加载的类),仍需手动处理;例如下图中对 DataSet 变换时,使用 .returns() 方法声明返回类型。

这里需要说明一下,returns() 接受三种类型的参数:字符串描述的类名(例如 “String”)、TypeHint(接下来会讲到,用于泛型类型参数)、Java 原生 Class(例如 String.class) 等;不过字符串形式的用法即将废弃,如果确实有必要,请使用 Class.forName() 等方法来解决。

img图 3:使用 .returns 方法声明返回类型

下面是 ExecutionEnvironment 类的 registerType 方法,它可以向 Flink 注册子类信息(Flink 认识父类,但不一定认识子类的一些独特特性,因而需要注册),下面是 Flink-ML 机器学习库代码的例子:

img图 4:Flink-ML 注册子类类型信息

从下图可以看到,如果通过 TypeExtractor.createTypeInfo(type) 方法获取到的类型信息属于 PojoTypeInfo 及其子类,那么将其注册到一起;否则统一交给 Kryo 去处理,Flink 并不过问(这种情况下性能会变差)。

img图 5:Flink 允许注册自定义类型

声明类型信息的常见手段

通过 TypeInformation.of() 方法,可以简单地创建类型信息对象。

1. 对于非泛型的类,直接传入 Class 对象即可

img图 6:class 对象作为参数

2. 对于泛型类,需要借助 TypeHint 来保存泛型类型信息

TypeHint 的原理是创建匿名子类,运行时 TypeExtractor 可以通过 getGenericSuperclass(). getActualTypeArguments() 方法获取保存的实际类型。

img图 7:TypeHint 作为参数,保存泛型信息

3. 预定义的快捷方式

例如 BasicTypeInfo,这个类定义了一系列常用类型的快捷方式,对于 String、Boolean、Byte、Short、Integer、Long、Float、Double、Char 等基本类型的类型声明,可以直接使用。

img图 8:BasicTypeInfo 快捷方式

例如下面是对 Row 类型各字段的类型声明,使用方法非常简明,不再需要 new XxxTypeInfo<>(很多很多参数)

img图 9:使用 BasicTypeInfo 快捷方式来声明一行(Row)每个字段的类型信息

当然,如果觉得 BasicTypeInfo 还是太长,Flink 还提供了完全等价的 Types 类(org.apache.flink.api.common.typeinfo.Types):

img图 10:Types 类

特别需要注意的是,flink-table 模块也有一个 Types 类(org.apache.flink.table.api.Types),用于 table 模块内部的类型定义信息,用法稍有不同。使用 IDE 的自动 import 时一定要小心:

img图 11:flink-table 模块的 Types 类

4. 自定义 TypeInfo 和 TypeInfoFactory

通过自定义 TypeInfo 为任意类提供 Flink 原生内存管理(而非 Kryo),可令存储更紧凑,运行时也更高效。

开发者在自定义类上使用 @TypeInfo 注解,随后创建相应的 TypeInfoFactory 并覆盖 createTypeInfo 方法。

注意需要继承 TypeInformation 类,为每个字段定义类型,并覆盖元数据方法,例如是否是基本类型(isBasicType)、是否是 Tuple(isTupleType)、元数(对于一维的 Row 类型,等于字段的个数)等等,从而为 TypeExtractor 提供决策依据。

img图 12:为自定义类提供类型支持(图片未展示全部字段)

更多示例,请参考 Flink 源码的 org/apache/flink/api/java/typeutils/TypeInfoFactoryTest.java

TypeSerializer

Flink 自带了很多 TypeSerializer 子类,大多数情况下各种自定义类型都是常用类型的排列组合,因而可以直接复用:

img图 13:Flink 自带的 TypeSerializer 子类概览

如果不能满足,那么可以继承 TypeSerializer 及其子类以实现自己的序列化器。

Kryo 序列化

对于 Flink 无法序列化的类型(例如用户自定义类型,没有 registerType,也没有自定义 TypeInfo 和 TypeInfoFactory),默认会交给 Kryo 处理。

如果 Kryo 仍然无法处理(例如 Guava、Thrift、Protobuf 等第三方库的一些类),有以下两种解决方案:

\1. 可以强制使用 Avro 来替代 Kryo:

env.getConfig().enableForceAvro();   // env 代表 ExecutionEnvironment 对象, 下同

\2. 为 Kryo 增加自定义的 Serializer 以增强 Kryo 的功能:

 env.getConfig().addDefaultKryoSerializer(Class<?> type, Class<? extends Serializer<?>> serializerClass

img图 14:为 Kryo 增加自定义的 Serializer

以及

env.getConfig().registerTypeWithKryoSerializer(Class<?> type, T serializer)

img图 15:为 Kryo 增加自定义的 Serializer

如果希望完全禁用 Kryo(100% 使用 Flink 的序列化机制),则可以使用以下设置,但注意一切无法处理的类都将导致异常:

env.getConfig().disableGenericTypes();

类型机制的陷阱与缺陷

金无足赤,人无完人。Flink 内置的类型系统虽然强大而灵活,但仍然有一些需要注意的点:

1. Lambda 函数的类型提取

由于 Flink 类型提取依赖于继承等机制,而 lambda 函数比较特殊,它是匿名的,也没有与之相关的类,所以其类型信息较难获取。

Eclipse 的 JDT 编译器会把 lambda 函数的泛型签名等信息写入编译后的字节码中,而对于 javac 等常见的其他编译器,则不会这样做,因而 Flink 就无法获取具体类型信息了。

2. Kryo 的 JavaSerializer 在 Flink 下存在 Bug

推荐使用 org.apache.flink.api.java.typeutils.runtime.kryo.JavaSerializer 而非 com.esotericsoftware.kryo.serializers.JavaSerializer 以防止与 Flink 不兼容。

类型机制与内存管理

img图 16:类型信息到内存块

下面以 StringSerializer 为例,来看下 Flink 是如何紧凑管理内存的:

img图 17:StringSerializer 类的 serialize() 方法

下面是具体的序列化过程:

img图 18:String 对象的序列化过程

可以看到,Flink 对于内存管理是非常细致的,层次分明,代码也容易理解。

参考阅读

Data Types & Serialization

Flink 原理与实现:内存管理

Flink 的数据类型和序列化

问答
如何使用Flink Quickstart在Eclipse IDE中缺少依赖关系?
相关阅读
Storm作业转化为Flink作业流程分析
Apache Calcite 功能简析及在 Flink 的应用
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

作为一个编程新手,我再也不怕Flink迷了我的眼! 的相关文章

  • 服务器备案问题解决思考?

    大家和我一样有没有在项目上线之后遇到服务器需要备案的问题呢 遇到这个问题的原因 域名没有备案 可是我发现我域名本案后还是无法通过域名直接解析到服务器80端口 所以我百度后发现 服务器竟然也要备案 而且备案步骤 手续与域名备案相比是真的麻烦
  • 测试人员为什么要去了解业务架构和技术架构?

    问题 在入职公司不久 我参加老员工再给新来的员工和管培生宣讲产品的业务 功能 直接拿着功能清单和实际页面在讲解 等把产品功能讲完了 我问了一下实习生和管培生怎么样 他们都说功能讲的太多 太乱 不清楚讲解产品的核心业务逻辑及操作流程 后来发现
  • 深入微服务架构 | 微服务与k8s架构解读

    微服务项目架构解读 什么是微服务 微服务是指开发一个单个小型的但有业务功能的服务 每个服务都有自己的处理和轻量通讯机制 可以部署在单个或多个服务器上 微服务也指一种种松耦合的 有一定的有界上下文的面向服务架构 也就是说 如果每个服务都要同时
  • 单个 epoll + 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景?

    本文是回答一位知友的提问 单个 epoll 线程池与每个线程一个 epoll 这两种架构哪个更适合大量短连接的场景 不少教程上都提到线程池适合大量的网络短连接的任务场景 但我总感觉这个优势有点站不住脚 单 epoll 线程池模型 主要考虑到
  • 网盘系统设计:万亿 GB 网盘如何实现秒传与限速?

    Java全能学习面试指南 https javaxiaobear cn 网盘 又称云盘 是提供文件托管和文件上传 下载服务的网站 File hostingservice 人们通过网盘保管自己拍摄的照片 视频 通过网盘和他人共享文件 已经成为了
  • 【CPU 架构】x86、x86_64、x64、arm64、aarch64

    x86 x86 64 x64 arm64 aarch64 1 服务器分类 2 CPU 架构 2 1 x86 架构 x86 x86 64 x64 2 2 arm 架构 arm64 和 aarch64 3 发展历史 1 服务器分类 按照 CPU
  • 国外免费VPS真的零成本云计算体验?

    在当今数字化时代 云计算已经成为企业和个人的热门选择之一 云计算提供了便捷 灵活和经济高效的计算资源 可以帮助人们处理数据 托管网站 运行应用程序等等 然而 对于一些初学者来说 使用云计算可能会变得有些昂贵 但是 有一种方式可以让您尝试云计
  • 每天花2小时复习Java面试指南,高级架构视频,我进了阿里定级P7

    Java进阶架构师必备 基础 容器 并发 JVM Java8 计算机网络 计算机操作系统 Linux 数据结构 算法 mysql 优化思路 系统设计 分布式 线上问题调优 虚拟机 tomcat 面试指南 工具 添加图片注释 不超过 140
  • 中国首家!腾讯云入选Gartner®视频平台服务市场指南代表厂商

    近日 Gartner正式发布 Market Guide for Video Platform Services 视频平台服务市场指南 下称 指南 凭借领先的音视频技术和产品组合优势 腾讯云成为中国首家且唯一入选的代表厂商 腾讯云VPS一站式
  • 第六章--- 实现微服务:匹配系统(下)

    0 写在前面 这一章终于完了 但是收尾工作真的好难呀QAQ 可能是我初学的缘故 有些JAVA方面的特性不是很清楚 只能依葫芦画瓢地模仿着用 特别是JAVA的注解 感觉好多但又不是很懂其中的原理 只知道要在某个时候用某个注解 我真是有够菜的
  • 阿里云一二级域名配置

    一级域名配置 二级域名配置
  • 什么是微服务

    微服务是一种架构风格 它把一个大型的复杂软件应用划分为一系列小的服务 每个服务都具有单一的功能 运行在其自己的进程中 并通常基于不同的编程语言和框架 这些服务之间通过轻量级通信机制相互通信 这种通信机制基于HTTP协议 微服务架构风格使得系
  • 浅谈小程序开源业务架构建设之路

    一 业务介绍 1 1 小程序开源整体介绍 百度从做智能小程序的第一天开始就打造真正开源开放的生态 我们的愿景是 定义移动时代最佳体验 建设智能小程序行业标准 打破孤岛 共建开源 开放 繁荣的小程序行业生态 百度智能小程序的生态玩家有三类 分
  • 专车数据层架构进化往事:好的架构是进化来的,不是设计来的

    很多年前 读了 子柳 老师的 淘宝技术这十年 这本书成为了我的架构启蒙书 书中的一句话像种子一样深埋在我的脑海里 好的架构是进化来的 不是设计来的 2015 年 我加入神州专车订单研发团队 亲历了专车数据层 架构进化 的过程 这次工作经历对
  • 天翼运行高校云盘在线扩容

    天翼云文档地址 https www ctyun cn document 10027696 10169558 1 输入 growpart命令 检查此云主机是否已安装growpart扩容工具 若出现图中回显信息 则说明已经安装 无需手动安装 注
  • 专车数据层架构进化往事:好的架构是进化来的,不是设计来的

    很多年前 读了 子柳 老师的 淘宝技术这十年 这本书成为了我的架构启蒙书 书中的一句话像种子一样深埋在我的脑海里 好的架构是进化来的 不是设计来的 2015 年 我加入神州专车订单研发团队 亲历了专车数据层 架构进化 的过程 这次工作经历对
  • 8大数字技术打造ESG发展新范式!工业“双碳”建设应该这么做

    随着国家 双碳 目标的提出 数字化 绿色化证进入历史交汇 协同发展 路径合一 相辅相成的重要阶段 在此背景下 中国信通院 中国航天航空 工业互联网产业联盟于2022年联合出版了 数字技术赋能工业碳达峰碳中和应用指南 以下简称 指南 今年又细
  • 从不同维度的调研数据,看企业数字化转型

    数字化转型逐渐成为企业增长和价值创造的新引擎 然而 在复杂的背景下 企业数字化转型也面临着前所未有的挑战和机遇 未来 我们还能做些什么 怎么做 这成为了各企业高管当前亟需厘清的问题 企业做数字化转型的原因 总体来看 大部分受访企业做数字化转
  • 盲猜你不懂H5架构和原生架构的区别

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 CSDN博客 文章浏览阅读2 3k次 点赞85次 收藏11次 你知不知道有这么一个软件测试面试的刷题小程序 里面包含了面试常问的软件测试基础题 web自
  • [机缘参悟-132] :《洞见》:为什么佛学是真的 -3- 冥想,洞见自己的内心

    目录 一 佛家修行的方法 二 冥想 2 1 冥想步骤 2 2 冥想的好处 2 3 冥想的方法 一 佛家修行的方法 佛教修行是指追求智慧 慈悲和解脱 以最终实现觉悟和解脱的过程 它包含了广泛的修行方法 以下是一些常见的佛教修行方法 冥想 冥想

随机推荐

  • timm库(CV利器)的入门教程(1)

    省流 使用timm加载CNN进行图像分类 调整CNN使之更适合你的任务 问 使用timm搭建一个可以使用的CNN或ViT拢共需要几步 答 4步 0 安装 timm 1 import timm 2 创建model 3 运行model 这一节很
  • 二叉搜索树(树状数组)

    计数函数 程序 int lowbit int k return k k 功能 可视为每个节点的编号函数 加和函数 程序 int sum int x int ret 0 while x gt 0 ret c x x lowbit x retu
  • jmeter提取token后只能使用一次的鬼问题

    今天在测试一个内部接口时 需要先登录传入token 按照正常步骤作对应参数化和参数传递 过程略 提取token的方法有很多 这里我是用的是正则表达式 提了就正常用嘛 可发现不管下边添加了多少请求 同一线程组下 永远只有登录请求的下一个可以获
  • linux常用函数和知识点博文合集

    signal SIGCHLD SIG IGN 和signal SIGPIPE SIG IGN 中断产生EINTR错误 linux中sigaction函数详解 标准I O函数库提供了popen函数 它启动另外一个进程去执行一个shell命令行
  • 2023秋招算法题每日学习(4)

    DAY 4 1 AcWing 850 Dijkstra求最短路 ii 考察点 堆优化Dijkstra 求最短路问题 适合于稀疏图 利用邻接表来存储 邻接表不需要对重边做特殊的处理 1 基础知识 时间复杂度分析 堆优化Dijkstra 堆优化
  • JUST技术:利用迁移学习生成新城市的轨迹

    市民的出行轨迹数据无论是对于城市管理 规划 还是商业活动 都是重要的参考信息 然而 获取一个城市的人群轨迹数据却非常困难 在今年4月份召开的国际顶级互联网会议WWW 2020 CCF A类 上 京东城市报告了被会议收录的论文 What is
  • 解决安装强化学习库gymnasium,box2d安装报错的问题

    gymnasium是强化学习的库 比较难安装 一 安装方法 安装Gymnasium 一定要all 这样可以安装所有依赖 pip install gymnasium all pip install gymnasium all 二 报错信息一
  • Docker安装记录

    1 卸载旧版本 yum remove docker docker client docker client latest docker common docker latest docker latest logrotate docker
  • Git版本控制

    Git 版本控制 什么是版本控制 版本控制是一种开发的过程中用于管理我们对文件 目录或工程等内容的修改历史 方便查看更改历史记录 备份以便恢复以前的版本的软件工程技术 实现跨区域多人协同开发 追踪和机载一个或者多个文件的历史记录 组织和保护
  • 成功解决VMware安装操作系统出现分辨率的问题

    文章目录 问题重现 问题原因 问题解决 方法一 拓展 1 电脑分辨率 2 xrandr命令 3 查询后如果没有合适的分辨率解决方案 参考资料 问题重现 如下图 在VMware16上安装ubuntu操作系统的时候 出现分辨率问题 导致底部的按
  • < 面试知识点:什么是 Node.js ?有哪些优缺点?应用场景? >

    文章目录 一 什么是 Node js 二 Node js 有哪些优缺点 三 Node js 能做什么 四 Node js 的 模块系统 五 Node js 应用场景 参考文献 往期内容 一 什么是 Node js Node js 是一个开源
  • 微信小程序如何获取微信昵称和头像

  • MySQL 高可用:mysql+mycat实现数据库分片(分库分表)

    什么是MYCAT 一个彻底开源的 面向企业应用开发的大数据库集群 支持事务 ACID 可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库 用来替代昂贵的Oracle集群 一个融合内存缓存技术 NoSQL技术 HDFS
  • Docker入门命令详解

    目录 一 Docker 简介 1 Docker引擎 2 Docker客户端 3 Docker镜像 4 Docker容器 5 Docker镜像注册中心 二 Docker的特点 1 快速运行 2 节省资源 3 便于交付 4 容易管理 三 Doc
  • C语言有小数乘法,十道小数乘小数的乘法竖式计算并有答案

    十道小数乘小数的乘法竖式计算并有答案以下文字资料是由 历史新知网www lishixinzhi com 小编为大家搜集整理后发布的内容 让我们赶快一起来看一下吧 十道小数乘小数的乘法竖式计算并有答案 6 5 8 4 56 1 3 3 2 2
  • C#实现串口通信

    背景 在工业控制中 工控机 一般都基于Windows平台 经常需要与智能仪表通过串口进行通信 串口通信方便易行 应用广泛 一般情况下 工控机和各智能仪表通过RS485总线进行通信 RS485的通信方式是半双工的 在Win32下 可以使用两种
  • 04_两种常见的网页反爬措施及应对方法

    一 封禁IP地址反爬 1 应对思路 理解这种反爬方法的含义 当我们用自己电脑的ip地址短时间 高频率访问某个具有此类反爬设置的网站 这种网站就会把我们的ip地址封禁 一般都是封24小时或者其他时间 解决方案 通过代理ip访问 这种方式只不过
  • SQL 语句 最大长度限制 DB2如何修改最大长度限制

    home datamart db2 get db cfg grep HEAP Sort heap thres for shared sorts 4KB SHEAPTHRES SHR AUTOMATIC Sort list heap 4KB
  • PhotonServer介绍

    官网 On Premises Cross Platform Multiplayer Game Backend Photon Engine Photon为您完全封装了每个客户端平台的复杂网络层 Photon Server支持可靠的UDP TC
  • 作为一个编程新手,我再也不怕Flink迷了我的眼!

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由kyledong 发表于云 社区专栏 使用 Flink 编写处理逻辑时 新手总是容易被林林总总的概念所混淆 为什么 Flink 有那么多的类型声明方式 BasicTypeInf