1、reduce操作,在分组的dataset上使用,也可以在不分组的dataset上使用

应用于分组DataSet的Reduce转换使用用户定义的reduce函数将每个组减少为单个元素。对于每组输入元素,reduce函数连续地将元素对组合成一个元素,直到每个组只剩下一个元素。

注意,对于ReduceFunction,返回对象的key字段应与输入值匹配。这是因为reduce是可隐式组合(combine)的,并且从combine运算符发出的对象在传递给reduce运算符时再次按key分组。

1.1 使用key表达式的dataset进行reduce

key表达式指定DataSet的每个元素的一个或多个字段。每个key表达式都是公共字段的名称或getter方法。用点被用于向下钻取对象。key表达式“*”选择所有字段。以下代码显示如何使用key表达式对POJO DataSet进行分组,并使用reduce函数对其进行规约。

// some ordinary POJO
public class WC {
public String word;
public int count;
// [...]
} // ReduceFunction that sums Integer attributes of a POJO
public class WordCounter implements ReduceFunction<WC> {
@Override
public WC reduce(WC in1, WC in2) {
return new WC(in1.word, in1.count + in2.count);
}
} // [...]
DataSet<WC> words = // [...]
DataSet<WC> wordCounts = words
// DataSet grouping on field "word"
.groupBy("word")
// apply ReduceFunction on grouped DataSet
.reduce(new WordCounter());

1.2 使用KeySelector函数的dataset上进行reduce

key选择器函数从DataSet的每个元素中提取键值。提取的key用于对DataSet进行分组。以下代码显示如何使用键选择器函数对POJO DataSet进行分组,并使用reduce函数对其进行规约操作。

// some ordinary POJO
public class WC {
public String word;
public int count;
// [...]
} // ReduceFunction that sums Integer attributes of a POJO
public class WordCounter implements ReduceFunction<WC> {
@Override
public WC reduce(WC in1, WC in2) {
return new WC(in1.word, in1.count + in2.count);
}
} // [...]
DataSet<WC> words = // [...]
DataSet<WC> wordCounts = words
// DataSet grouping on field "word"
.groupBy(new SelectWord())
// apply ReduceFunction on grouped DataSet
.reduce(new WordCounter()); public class SelectWord implements KeySelector<WC, String> {
@Override
public String getKey(Word w) {
return w.word;
}
}

1.3 在Tuple元组上应用的reduce,可以使用数字来指明字段位置,类似索引

字段位置键指定一个或多个字段用于分组

DataSet<Tuple3<String, Integer, Double>> tuples = // [...]
DataSet<Tuple3<String, Integer, Double>> reducedTuples = tuples
// group DataSet on first and second field of Tuple
.groupBy(0, 1)
// apply ReduceFunction on grouped DataSet
.reduce(new MyTupleReducer());

1.4 在整个数据集上应用reduce

Reduce转换可以将用户定义的reduce函数应用于DataSet的所有元素。 reduce函数随后将元素对组合成一个元素,直到只剩下一个元素。

使用Reduce转换规约完整的DataSet意味着最终的Reduce操作不能并行完成。但是,reduce函数可以自动组合,因此Reduce转换不会限制大多数用例的可伸缩性

以下代码显示如何对Integer DataSet的所有元素求和:

// ReduceFunction that sums Integers
public class IntSummer implements ReduceFunction<Integer> {
@Override
public Integer reduce(Integer num1, Integer num2) {
return num1 + num2;
}
} // [...]
DataSet<Integer> intNumbers = // [...]
DataSet<Integer> sum = intNumbers.reduce(new IntSummer());

2、分组reduce,即GroupReduce

应用于分组DataSet的GroupReduce调用用户定义的group-reduce函数转换每个分组。
这与Reduce的区别在于用户定义的函数会立即获得整个组。在组的所有元素上使用Iterable调用该函数,并且可以返回任意数量的结果元素。

2.1 GroupReduce对于分组的键于redeuce相同

以下代码显示如何从Integer分组的DataSet中删除重复的字符串。

public class DistinctReduce
implements GroupReduceFunction<Tuple2<Integer, String>, Tuple2<Integer, String>> { @Override
public void reduce(Iterable<Tuple2<Integer, String>> in, Collector<Tuple2<Integer, String>> out) { Set<String> uniqStrings = new HashSet<String>();
Integer key = null; // add all strings of the group to the set
for (Tuple2<Integer, String> t : in) {
key = t.f0;
uniqStrings.add(t.f1);
} // emit all unique strings.
for (String s : uniqStrings) {
out.collect(new Tuple2<Integer, String>(key, s));
}
}
} // [...]
DataSet<Tuple2<Integer, String>> input = // [...]
DataSet<Tuple2<Integer, String>> output = input
.groupBy(0) // group DataSet by the first tuple field
.reduceGroup(new DistinctReduce()); // apply GroupReduceFunction

2.2 将GroupReduce应用于排序分组的数据集

group-reduce函数使用Iterable访问组的元素。Iterable可以按指定的顺序分发组的元素(可选)。在许多情况下,这可以帮助降低用户定义的组减少功能的复杂性并提高其效率。

下面的代码显示了如何删除由Integer分组并按String排序的DataSet中的重复字符串的另一个示例。

// GroupReduceFunction that removes consecutive identical elements
public class DistinctReduce
implements GroupReduceFunction<Tuple2<Integer, String>, Tuple2<Integer, String>> { @Override
public void reduce(Iterable<Tuple2<Integer, String>> in, Collector<Tuple2<Integer, String>> out) {
Integer key = null;
String comp = null; for (Tuple2<Integer, String> t : in) {
key = t.f0;
String next = t.f1; // check if strings are different
if (com == null || !next.equals(comp)) {
out.collect(new Tuple2<Integer, String>(key, next));
comp = next;
}
}
}
} // [...]
DataSet<Tuple2<Integer, String>> input = // [...]
DataSet<Double> output = input
.groupBy(0) // group DataSet by first field
.sortGroup(1, Order.ASCENDING) // sort groups on second tuple field
.reduceGroup(new DistinctReduce());

3、可组合的GroupReduce功能

与reduce函数相比,group-reduce函数不是可隐式组合的。为了使group-reduce函数可组合,它必须实现GroupCombineFunction接口。

要点:GroupCombineFunction接口的通用输入和输出类型必须等于GroupReduceFunction的通用输入类型,如以下示例所示:

// Combinable GroupReduceFunction that computes a sum.
public class MyCombinableGroupReducer implements
GroupReduceFunction<Tuple2<String, Integer>, String>,
GroupCombineFunction<Tuple2<String, Integer>, Tuple2<String, Integer>>
{
@Override
public void reduce(Iterable<Tuple2<String, Integer>> in,
Collector<String> out) { String key = null;
int sum = 0; for (Tuple2<String, Integer> curr : in) {
key = curr.f0;
sum += curr.f1;
}
// concat key and sum and emit
out.collect(key + "-" + sum);
} @Override
public void combine(Iterable<Tuple2<String, Integer>> in,
Collector<Tuple2<String, Integer>> out) {
String key = null;
int sum = 0; for (Tuple2<String, Integer> curr : in) {
key = curr.f0;
sum += curr.f1;
}
// emit tuple with key and sum
out.collect(new Tuple2<>(key, sum));
}
}

4、GroupCombine 分组连接

GroupCombine转换是可组合GroupReduceFunction中组合步骤的通用形式。它在某种意义上被概括为允许将输入类型I组合到任意输出类型O.
相反,GroupReduce中的组合步骤仅允许从输入类型I到输出类型I的组合。这是因为reduce步骤中,GroupReduceFunction期望输入类型为I. 在一些应用中,期望在执行附加变换(例如,减小数据大小)之前将DataSet组合成中间格式。这可以通过CombineGroup转换能以非常低的成本实现。 注意:分组数据集上的GroupCombine在内存中使用贪婪策略执行,该策略可能不会一次处理所有数据,而是以多个步骤处理。
它也可以在各个分区上执行,而无需像GroupReduce转换那样进行数据交换。这可能会导致输出的是部分结果,
所以GroupCombine是不能替代GroupReduce操作的,尽管它们的操作内容可能看起来都一样。 以下示例演示了如何将CombineGroup转换用于备用WordCount实现。
DataSet<String> input = [..] // The words received as input

DataSet<Tuple2<String, Integer>> combinedWords = input
.groupBy(0) // group identical words
.combineGroup(new GroupCombineFunction<String, Tuple2<String, Integer>() { public void combine(Iterable<String> words, Collector<Tuple2<String, Integer>>) { // combine
String key = null;
int count = 0; for (String word : words) {
key = word;
count++;
}
// emit tuple with word and count
out.collect(new Tuple2(key, count));
}
}); DataSet<Tuple2<String, Integer>> output = combinedWords
.groupBy(0) // group by words again
.reduceGroup(new GroupReduceFunction() { // group reduce with full data exchange public void reduce(Iterable<Tuple2<String, Integer>>, Collector<Tuple2<String, Integer>>) {
String key = null;
int count = 0; for (Tuple2<String, Integer> word : words) {
key = word;
count++;
}
// emit tuple with word and count
out.collect(new Tuple2(key, count));
}
});
 

flink Reduce、GroupReduce、GroupCombine笔记的更多相关文章

  1. Hadoop :map+shuffle+reduce和YARN笔记分享

    今天做了一个hadoop分享,总结下来,包括mapreduce,及shuffle深度讲解,还有YARN框架的详细说明等. v\:* {behavior:url(#default#VML);} o\:* ...

  2. flink基础教程读书笔记

    数据架构设计领域发生了重大的变化,基于流的处理是变化的核心. 分布式文件系统用来存储不经常更新的数据,他们也是大规模批量计算所以来的数据存储方式. 批处理架构(lambda架构)实现计数的方式:持续摄 ...

  3. Flink源码学习笔记(3)了解Flink HA功能的实现

    使用Flink HA功能维护JobManager中组件的生命周期,可以有效的避免因为JobManager 进程失败导致任务无法恢复的情况. 接下来分享下 Flink HA功能的实现 大纲 基于Zook ...

  4. Flink源码学习笔记(2) 基于Yarn的自动伸缩容实现

    1.背景介绍 随着实时计算技术在之家内部的逐步推广,Flink 任务数及计算量都在持续增长,集群规模的也在逐步增大,本着降本提效的理念,我们研发了 Flink 任务伸缩容功能: 提供自动伸缩容功能,可 ...

  5. [源码解析] GroupReduce,GroupCombine 和 Flink SQL group by

    [源码解析] GroupReduce,GroupCombine和Flink SQL group by 目录 [源码解析] GroupReduce,GroupCombine和Flink SQL grou ...

  6. Flink学习笔记:Flink API 通用基本概念

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

  7. flink学习笔记-各种Time

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

  8. Flink开发中的问题

    1. 流与批处理的区别 流处理系统 流处理系统,其节点间数据传输的标准模型是:当一条数据被处理完成后,序列化到缓存中,然后立刻通过网络传输到下一个节点,由下一个节点继续处理. 批处理系统 批处理系统, ...

  9. Apache Flink - 基本API概念

    Flink程序是实现分布式集合转换的常规程序.集合最初是从源创建的.通过接收器(slink)返回结果,接收器可以将数据写到某个文件或stdout.Flink可以在各种环境(context)中运行,本地 ...

随机推荐

  1. 代码审计-数组返回NULL绕过

    <?php $flag = "flag"; if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$&q ...

  2. tuned linux 性能调优工具

    tuned 是redhat 提供的一套系统调优工具,使用简单,同时也提供了比较全的分类. 参考资料 https://github.com/redhat-performance/tuned

  3. 2.第一个Vue程序

    1.IDEA中安装Vue.js插件 2.建立项目以及html文件 1.创建一个 HTML 文件 2.引入 Vue.js <script src="https://cdn.jsdeliv ...

  4. 求数组前K个大的数

    我们举例,假若从10000万个数里选出前100个最大的数据. 首先我们先分析:既然要选出前100个最大的数据,我们就建立一个大小为100的堆(建堆时就按找最大堆的规则建立,即每一个根节点都大于它的子女 ...

  5. BBS_02day

    目录 BBS_02day: 展示个人所有文章: 点赞,点彩功能: 评论功能: BBS_02day: 展示个人所有文章: def article_detail(request,username,arti ...

  6. [LeetCode] 305. Number of Islands II 岛屿的数量之二

    A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...

  7. [LeetCode] 91. Decode Ways 解码方法

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  8. 第09组 Beta冲刺(1/5)

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 任务分配 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任 ...

  9. C#面试题(一)

    一.背景 最近学习巩固C#的基础,看到<小胖李的面试之旅>的文章,把他的面试题目拿来总结以及学习. 二.面试题 1.wcf想用http协议通信怎么做? 答:在配置文件里面配置,因为wcf默 ...

  10. Canal订阅binlog变更并结合kafka实现消息缓冲

    阿里Canal项目请先了解:canal 考虑可能binlog大批量变更,如果直接通过Canal订阅binlog变动,会造成CanalClient会瞬间爆掉.为了解决这个问题,我们可以引入kafka做一 ...