Flink资料(4) -- 类型抽取和序列化
类型抽取和序列化
本文翻译自Type Extraction and Serialization
Flink处理类型的方式比较特殊,包括它自己的类型描述,一般类型抽取和类型序列化框架。该文档描述这些概念并解释其机理。
Java API和Scala API处理类型信息的方式有根本性的区别,所以本文描述的问题仅与其中一种API相关
一、Flink中对类型的处理
一般处理类型时,我们并不干涉,而是让编程语言和序列化框架来自动处理类型。与之相反的,Flink想要尽可能掌握进出用户函数的数据类型的信息。
1. 为了可以使用持久化类(POJO)以及通过成员名来grouping/joining,Flink需要数据类型信息来在job被执行前进行检查(拼写错误和类型兼容性)
2. 信息知道得越多,编译器/优化器就可以开发出更好的序列化(serialization)和数据分布模式(data layout scheme)。这对Flink的“memory usage paradigm”是非常重要的(它用于序列化从堆中出入的数据,并使得序列化开销变得十分低)
3. 对于即将推出的逻辑程序(logic program),我们需要这些信息来识别函数的“模式(scheme)”
4. 最后,这些信息使得用户免于考虑序列化框架,以及考虑将类型注册到这些框架中去
二、Flink的TypeInformation类
类TypeInformation是所有类型描述类的基类。它包括了一些类型的基本属性,并可以动过它来生成序列化器(serializer),特殊情况下可以生成类型的比较器。(Note:Flink中的比较器不仅仅是定义大小,它们是处理keys时的基本辅助工具)
Flink对类型做出如下区分:
1. 基本类型:所有Java基本数据类型和对应装箱类型,加上void, String, Date
2. 基本数组和Object数组
3. 复合类型:
a. Flink Java Tuple(Flink Java API的一部分)
b. Scala case 类(包括Scala Tuple)
c. POJO类:遵循类bean模式的类
4. Scala辅助类型(Option,Either,Lists,Maps…)
5. 泛型(Generic):这些类型将不会由Flink自己序列化,而是借助Kryo来序列化
POJO类支持复杂类型的创建,并且在定义keys时可以使用成员的名字:dataSet.join(another).where("name").equalTo("personName")。同时,POJO类对于运行时是透明的,这使得Flink可以十分高效地处理它们。
POJO类型的规则
当以下条件满足时,Flink将以POJO类型识别一个数据类型,并允许以成员名引用:
1. 该类是public并且独立的(即没有非静态的内部类)
2. 该类拥有一个public的无参数构造函数
3. 该类(以及该类的超类)的成员要么是public的,要么拥有public的符合Java bean对Getter和Setter命名规则的Getter和Setter函数。
三、Scala API中的类型信息
略
四、Java API中的类型信息
Java一般会清除泛型信息。仅对泛型类的子类,由子类存储泛型变量捆绑的类型。
Flink对实现用户函数的(匿名anonymous)类使用反射(reflection)来确定该函数的泛型参数的类型。该逻辑还包含简单的类型推论,用于函数返回的类型由输入类型决定的情况,例如如下的泛型函数:
public class AppendOne<T> extends MapFunction<T, Tuple2<T, Long>>
{
public Tuple2<T, Long> map(T value)
{
return new Tuple<T, Long>(value, 1L);
}
}
Flink并不可能在所有情况下都可靠地识别出函数的数据类型。在泛型Lambda表达式(我们试图在Java社区解决这个问题,见下)和泛型变量推断上仍然存在一些问题。
4.1 Java API中的Type Hints
为了帮助Flink无法重建被清除的泛型信息的情况,自版本0.9后提供了type hint的Java API。Type hint通知系统一个函数产生的数据集的类型。下面是一个Type hint的例子:
DataSet<SomeType> result = dataSet
.map(new MyGenericNonInferrableFunction<Long, SomeType>())
.returns(SomeType.class);
在本例中,returns语句通过一个类指定了产生的类型。Type hint支持如下几种方法进行类型定义:
1. 类,针对无参数的类型(非泛型)
2. String,语法为returns("Tuple2<Integer, my.SomeType>"),该字符串将被分析并转换为TypeInformation对象
3. 一个TypeInfomation对象
4.2 针对Java 8 Lambda表达式的类型抽取
由于Lambda表达式不涉及继承函数接口的实现类,Java 8 Lambda的类型抽取与非lambda表达式的机理并不相同。
现在,Flink正尝试确定如何实现Lambda表达式,并使用Java的泛型签名(generic signature)来决定参数类型和返回类型。但是,并不是所有的编译器中的签名都是为Lambda表达式生成的(本文写作时该文档仅完全适用在Milestone 2的Eclipse JDT编译器4.5及以前的编译器下)
4.2.1 类型信息对Java Lambda的改善
Flink的提交者之一(Timo Walther)活跃于Eclipse JDT 编译器社区和OpenJDK社区,并向编译器提交了改善类型信息对Java 8 Lambda表达式可用性的补丁。
Eclipse JDT 编译器在版本4.5 M4添加了对该方面的支持,而有关OpenJDK编译器的有关方面正在讨论当中。
4.3 POJO类型的序列化
类PojoTypeInfomation用于创建针对POJO中所有成员的序列化器。Flink自带了针对诸如int,long,String等标准类型的序列化器,对于所有其他的类型,我们交给Kryo处理。
如果Kryo不能处理某类型,则我们可以通过PojoTypeInfo来使用Avro来序列化POJO,为了达成该目的,我们需要调用如下接口:
1 final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
2 env.getConfig().enableForceAvro();
注意Flink自动序列化POJO对象,该对象由Avro用Avro序列化器产生。
如果我们想使得整个POJO类型都由Kryo序列化器处理,则我们如下设置:
final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
env.getConfig().enableForceKryo();
如果Kryo不能序列化该POJO对象,我们可以添加一个自定义序列化器到Kryo,使用代码如下:
env.getConfig().addDefaultKryoSerializer(Class<?> type, Class<? extends Serializer<?>> serializerClass)
这些方法还有许多不同的重载形式可用
Flink资料(4) -- 类型抽取和序列化的更多相关文章
- c# (ENUM)枚举组合类型的谷歌序列化Protobuf
c# (ENUM)枚举组合类型的谷歌序列化Protobuf,必须在序列化/反序列化时加上下面: RuntimeTypeModel.Default[typeof(Alarm)].EnumPassthru ...
- Flink资料(6) -- 如何添加一个新的Operator
false false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-n ...
- Json.NET序列化后包含类型,保证序列化和反序列化的对象类型相同(转载)
This sample uses the TypeNameHandlingsetting to include type information when serializing JSON and r ...
- 调用webservices中 枚举类型没有被序列化问题
引用服务后,代理类为自动为所有枚举类型生成了一个Bool类型相关字段,命名方式:比如枚举类名为“PayType”,生成的相关字段为“PayTypeSpecified”,此字段有何作用? PayType ...
- Apache Flink - 常见数据流类型
DataStream: DataStream 是 Flink 流处理 API 中最核心的数据结构.它代表了一个运行在多个分区上的并行流.一个 DataStream 可以从 StreamExecutio ...
- SrpingMVC通过JSON注入from数据到实体自定义(LocalDateTime,LocalDate,Boolean类型)字段的序列化、反序列化方法
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingExcept ...
- jackson对Exception类型对象的序列化与反序列化
发现问题 今天在调试系统错误通知的时候遇到了一个问题.我们在系统异常时候要通过队列系统发送各种通知到团队内部成员. 因此我写了一个通用接口.接口中有传递Exception对象到队列中,再由队列消费者解 ...
- 【django后端分离】mysql原生查询命令后,RawQueryset类型的自定义序列化返回json格式
1:设置mysql原生分页 # 监控系统首页显示分页 def MyPagination(limitid,offsetid): limitid =str(limitid) offsetid =str(o ...
- Flink资料(8) -- Flink代码贡献的指导及准则
本文翻译自Contributing Code ----------------------------------------- Apache Flink是由自愿的代码贡献者维护.优化及扩展的.Apa ...
随机推荐
- Parallel多线程
随着多核时代的到来,并行开发越来越展示出它的强大威力!使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Tas ...
- chrome浏览器的桌面通知
最近在使用朋友网(不加链接,避免有打广告的嫌疑),发现会出现提示“是否允许网站显示桌面通知?”,如下图所示: 这种做法,在页面加载完时直接调用请求,比起开心网的这种提示感觉有些野蛮了.开心网的桌面通知 ...
- 蜗牛爱课 -- iOS 设置UIButton的字体的大小、显示位置、大小
/设置按钮上的自体的大小 //[btn setFont: [UIFont systemFontSize: 14.0]]; //这种可以用来设置字体的大小,但是可能会在将来的SDK版本中去除改方法 ...
- iOS开发之设置界面的抽取
几乎每款app都会有一个设置的界面!!! 那么我们的设置界面到底要怎么写才能最方便使用呢?下面我就来说说我的想法. 1.观察原型图 2.找出相同的东西,目的是抽出一个基类模块,只要我写好了这个控制器, ...
- BZOJ 1564: [NOI2009]二叉查找树( dp )
树的中序遍历是唯一的. 按照数据值处理出中序遍历后, dp(l, r, v)表示[l, r]组成的树, 树的所有节点的权值≥v的最小代价(离散化权值). 枚举m为根(p表示访问频率): 修改m的权值 ...
- Qt使用快捷键
在说快捷键之前先来说一个QtCreator调试的过程中经常发生的一个问题. 问题描述: 用QtCreator建立了一个纯C++的项目,但是在F5调试时,竟然提示ptrace不允许的操作,修改工程配置为 ...
- Mvc Webapi+Fiddler调试 (WebAPI 一)
Fiddler Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据(指cookie,html,js, ...
- Android 混淆文件project.properties和proguard-project.txt
参考文档:http://blog.csdn.net/xueyepiaoling/article/details/8202359 http://glblong.blog.51cto.com/305861 ...
- accordion
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- SQL Server 数据库游标选项
背景: 游标控制服务器端游标的行为,相关的T-SQL如下: declare , open , fetch , close , deallocate. 1. cursor_close_on_commit ...