使用方式,

dataStream.coGroup(otherStream)
.where(0).equalTo(1)
.window(TumblingEventTimeWindows.of(Time.seconds(3)))
.apply (new CoGroupFunction () {...});

 

可以看到coGroup只是产生CoGroupedStreams

    public <T2> CoGroupedStreams<T, T2> coGroup(DataStream<T2> otherStream) {
return new CoGroupedStreams<>(this, otherStream);
}

 

而where, equalTo只是添加keySelector,对于两个流需要分别指定

keySelector1,keySelector2

 

window设置双流的窗口,很容易理解

 

apply,

       /**
* Completes the co-group operation with the user function that is executed
* for windowed groups.
*
* <p>Note: This method's return type does not support setting an operator-specific parallelism.
* Due to binary backwards compatibility, this cannot be altered. Use the
* {@link #with(CoGroupFunction, TypeInformation)} method to set an operator-specific parallelism.
*/
public <T> DataStream<T> apply(CoGroupFunction<T1, T2, T> function, TypeInformation<T> resultType) {
//clean the closure
function = input1.getExecutionEnvironment().clean(function); UnionTypeInfo<T1, T2> unionType = new UnionTypeInfo<>(input1.getType(), input2.getType());
UnionKeySelector<T1, T2, KEY> unionKeySelector = new UnionKeySelector<>(keySelector1, keySelector2); DataStream<TaggedUnion<T1, T2>> taggedInput1 = input1 //将input1封装成TaggedUnion,很简单,就是赋值到one上
.map(new Input1Tagger<T1, T2>())
.setParallelism(input1.getParallelism())
.returns(unionType);
DataStream<TaggedUnion<T1, T2>> taggedInput2 = input2 //将input2封装成TaggedUnion
.map(new Input2Tagger<T1, T2>())
.setParallelism(input2.getParallelism())
.returns(unionType); DataStream<TaggedUnion<T1, T2>> unionStream = taggedInput1.union(taggedInput2); //由于现在双流都是TaggedUnion类型,union成一个流,问题被简化 // we explicitly create the keyed stream to manually pass the key type information in
WindowedStream<TaggedUnion<T1, T2>, KEY, W> windowOp = //创建窗口
new KeyedStream<TaggedUnion<T1, T2>, KEY>(unionStream, unionKeySelector, keyType)
.window(windowAssigner); if (trigger != null) { //如果有trigger,evictor,设置上
windowOp.trigger(trigger);
}
if (evictor != null) {
windowOp.evictor(evictor);
} return windowOp.apply(new CoGroupWindowFunction<T1, T2, T, KEY, W>(function), resultType); //调用window的apply
}

关键理解,他要把两个流变成一个流,这样问题域就变得很简单了

最终调用到WindowedStream的apply,apply是需要保留window里面的所有原始数据的,和reduce不一样

apply的逻辑,是CoGroupWindowFunction

 

private static class CoGroupWindowFunction<T1, T2, T, KEY, W extends Window>
extends WrappingFunction<CoGroupFunction<T1, T2, T>>
implements WindowFunction<TaggedUnion<T1, T2>, T, KEY, W> { private static final long serialVersionUID = 1L; public CoGroupWindowFunction(CoGroupFunction<T1, T2, T> userFunction) {
super(userFunction);
} @Override
public void apply(KEY key,
W window,
Iterable<TaggedUnion<T1, T2>> values,
Collector<T> out) throws Exception { List<T1> oneValues = new ArrayList<>();
List<T2> twoValues = new ArrayList<>(); for (TaggedUnion<T1, T2> val: values) {
if (val.isOne()) {
oneValues.add(val.getOne());
} else {
twoValues.add(val.getTwo());
}
}
wrappedFunction.coGroup(oneValues, twoValues, out);
}
}
}

逻辑也非常的简单,就是将该key所在window里面的value,放到oneValues, twoValues两个列表中

最终调用到用户定义的wrappedFunction.coGroup

 

DataStream.join就是用CoGroup实现的

            return input1.coGroup(input2)
.where(keySelector1)
.equalTo(keySelector2)
.window(windowAssigner)
.trigger(trigger)
.evictor(evictor)
.apply(new FlatJoinCoGroupFunction<>(function), resultType);

 

FlatJoinCoGroupFunction

private static class FlatJoinCoGroupFunction<T1, T2, T>
extends WrappingFunction<FlatJoinFunction<T1, T2, T>>
implements CoGroupFunction<T1, T2, T> {
private static final long serialVersionUID = 1L; public FlatJoinCoGroupFunction(FlatJoinFunction<T1, T2, T> wrappedFunction) {
super(wrappedFunction);
} @Override
public void coGroup(Iterable<T1> first, Iterable<T2> second, Collector<T> out) throws Exception {
for (T1 val1: first) {
for (T2 val2: second) {
wrappedFunction.join(val1, val2, out);
}
}
}
}

可以看出当前join是inner join,必须first和second都有的情况下,才会调到用户的join函数

Flink - CoGroup的更多相关文章

  1. Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树

    Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 目录 Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 0x00 摘要 0x01 背景概念 1.1 词向量基础 ...

  2. Flink学习笔记:Operators之CoGroup及Join操作

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  3. Flink入门 - CoGroup和Join

    /* *CoGroup */ final StreamExecutionEnvironment streamExecutionEnvironment = StreamExecutionEnvironm ...

  4. Flink实例(五十): Operators(十)多流转换算子(五)coGroup 与union

    参考链接:https://mp.weixin.qq.com/s/BOCFavYgvNPSXSRpBMQzBw 需求场景分析 需求场景 需求诱诱诱来了...数据产品妹妹想要统计单个短视频粒度的「点赞,播 ...

  5. Flink Program Guide (2) -- 综述 (DataStream API编程指导 -- For Java)

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  6. Flink Program Guide (1) -- 基本API概念(Basic API Concepts -- For Java)

    false false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-n ...

  7. Flink从入门到放弃(入门篇3)-DataSetAPI

    戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...

  8. Flink Java Demo(Windows)

    关于Flink相关的概念性东西就不说了,网上都有,官网也很详尽.本文主要记录一下Java使用Flink的简单例子. 首先,去官网下载Flink的zip包(链接就不提供了,你已经是个成熟的程序员了,该有 ...

  9. Flink官网文档翻译

    http://ifeve.com/flink-quick-start/ http://vinoyang.com/2016/05/02/flink-concepts/ http://wuchong.me ...

随机推荐

  1. 【Spark深入学习 -10】基于spark构建企业级流处理系统

    ----本节内容------- 1.流式处理系统背景 1.1 技术背景 1.2 Spark技术很火 2.流式处理技术介绍 2.1流式处理技术概念 2.2流式处理应用场景 2.3流式处理系统分类 3.流 ...

  2. Swift 4迁移总结:喜忧参半,新的起点

    Swift 4迁移总结:喜忧参半,新的起点 每日一篇优秀博文 这次Swift 3 到 4 的迁移代码要改动的地方比较少,花了一个下午的时间就完成了迁移.Swift 把原来 4.0 的目标从 ABI 稳 ...

  3. 【Android】GPS定位基本原理浅析

    位置服务已经成为越来越热的一门技术,也将成为以后所有移动设备(智能手机.掌上电脑等)的标配.而定位导航技术中,目前精度最高.应用最广泛的,自然非GPS莫属了.网络上介绍GPS原理的专业资料很多,而本文 ...

  4. graph radar 界面开发笔记

    首先需要了解odoo图表视图的实现是采用了前端nvd3框架,nvd3是一个以复用为目的,基于d3框架的前端框架,官方地址:nvd3.org.从官网可见,目前nvd3可以用来画的图表并不包含雷达图. 第 ...

  5. <我的股票交易知识汇总与个人感悟_v1.0 (By geman)>

    书在这里 一个完整的股票交易包括选股.买股.持股.卖股四个阶段. 右侧交易,顶是跌出来的,底是涨出来的 一定要敢于止损,设好止损位,严格执行,即使踏空也无怨无悔:资金安全第一位 坚持只买处于上升通道的 ...

  6. .io域名在申请SSL证书时被坑

    注:标题其实与最后内容不符,只是描述一个事实 - 遇到坑了,不代表观点 - io域名坑我. .io后缀的域名是英属印度洋领地的国别域名,由NIC.io(runby Internet Computer ...

  7. CLOS网络架构与FATTREE胖树拓扑

    FatTree拓扑结构是由MIT的Fares等人在改进传统树形结构性能的基础上提出的,属于switch-only型拓扑. 整个拓扑网络分为三个层次:自上而下分别为边缘层(edge).汇聚层(aggre ...

  8. findpanel 的相关代码

    https://blog.csdn.net/zengcong2013/article/details/43118189 In addition to this method, you can use ...

  9. JS中判断一个对象是否为null、undefined、0

    1.判断undefined: var tmp = undefined; if (typeof(tmp) == "undefined"){ alert("undefined ...

  10. Xcode连接TFS Git用户名和密码不正确解决方案

    团队要将原来搭建的Git服务全部迁移到TFS的Git上统一管理,迁移的过程非常顺利.当要用Xcode或者SourceTree连接TFS Git(我们的TFS身份认证是基于Windows的,使用HTTP ...