转发请注明原创地址:https://www.cnblogs.com/dongxiao-yang/p/9198977.html

TopN 是统计报表和大屏非常常见的功能,主要用来实时计算排行榜。流式的TopN可以使业务方在内存中按照某个统计指标(如出现次数)计算排名并快速出发出更新后的排行榜。

我们以统计词频为例展示一下如何快速开发一个计算TopN的flink程序。

flink支持各种各样的流数据接口作为数据的数据源,本次demo我们采用内置的socketTextStream作为数据数据源。

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime); //以processtime作为时间语义

DataStream<String> text = env.socketTextStream(hostName, port); //监听指定socket端口作为输入

与离线wordcount类似,程序首先需要把输入的整句文字按照分隔符split成一个一个单词,然后按照单词为key实现累加

DataStream<Tuple2<String, Integer>> ds = text
.flatMap(new LineSplitter()); //将输入语句split成一个一个单词并初始化count值为1的Tuple2<String, Integer>类型 private static final class LineSplitter implements
FlatMapFunction<String, Tuple2<String, Integer>> { @Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
// normalize and split the line
String[] tokens = value.toLowerCase().split("\\W+"); // emit the pairs
for (String token : tokens) {
if (token.length() > 0) {
out.collect(new Tuple2<String, Integer>(token, 1));
}
}
}
}
    DataStream<Tuple2<String, Integer>> wcount = ds
.keyBy(0) //按照Tuple2<String, Integer>的第一个元素为key,也就是单词
.window(SlidingProcessingTimeWindows.of(Time.seconds(600),Time.seconds(20)))
//key之后的元素进入一个总时间长度为600s,每20s向后滑动一次的滑动窗口
.sum(1);// 将相同的key的元素第二个count值相加

全局TopN

数据流经过前面的处理后会每20s计算一次各个单词的count值并发送到下游窗口

        DataStream<Tuple2<String, Integer>> ret = wcount
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(20)))
//所有key元素进入一个20s长的窗口(选20秒是因为上游窗口每20s计算一轮数据,topN窗口一次计算只统计一个窗口时间内的变化)
.process(new TopNAllFunction(5));//计算该窗口TopN

windowAll是一个全局并发为1的特殊操作,也就是所有元素都会进入到一个窗口内进行计算。

    private static class TopNAllFunction
extends
ProcessAllWindowFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, TimeWindow> { private int topSize = 10; public TopNAllFunction(int topSize) {
// TODO Auto-generated constructor stub this.topSize = topSize;
} @Override
public void process(
ProcessAllWindowFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, TimeWindow>.Context arg0,
Iterable<Tuple2<String, Integer>> input,
Collector<Tuple2<String, Integer>> out) throws Exception {
// TODO Auto-generated method stub TreeMap<Integer, Tuple2<String, Integer>> treemap = new TreeMap<Integer, Tuple2<String, Integer>>(
new Comparator<Integer>() { @Override
public int compare(Integer y, Integer x) {
// TODO Auto-generated method stub
return (x < y) ? -1 : 1;
} }); //treemap按照key降序排列,相同count值不覆盖 for (Tuple2<String, Integer> element : input) {
treemap.put(element.f1, element);
if (treemap.size() > topSize) { //只保留前面TopN个元素
treemap.pollLastEntry();
}
} for (Entry<Integer, Tuple2<String, Integer>> entry : treemap
.entrySet()) {
out.collect(entry.getValue());
} } }

分组TopN

在部分场景下,用户希望根据不同的分组进行排序,计算出每个分组的一个排行榜。

    wcount.keyBy(new TupleKeySelectorByStart()) // 按照首字母分组
.window(TumblingProcessingTimeWindows.of(Time.seconds(20))) //20s窗口统计上游数据
.process(new TopNFunction(5)) //分组TopN统计
    private static class TupleKeySelectorByStart implements
KeySelector<Tuple2<String, Integer>, String> { @Override
public String getKey(Tuple2<String, Integer> value) throws Exception {
// TODO Auto-generated method stub
return value.f0.substring(0, 1); //取首字母做key
} }
/**
*
*针对keyby window的TopN函数,继承自ProcessWindowFunction
*
*/
private static class TopNFunction
extends
ProcessWindowFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, String, TimeWindow> { private int topSize = 10; public TopNFunction(int topSize) {
// TODO Auto-generated constructor stub
this.topSize = topSize;
} @Override
public void process(
String arg0,
ProcessWindowFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, String, TimeWindow>.Context arg1,
Iterable<Tuple2<String, Integer>> input,
Collector<Tuple2<String, Integer>> out) throws Exception {
// TODO Auto-generated method stub TreeMap<Integer, Tuple2<String, Integer>> treemap = new TreeMap<Integer, Tuple2<String, Integer>>(
new Comparator<Integer>() { @Override
public int compare(Integer y, Integer x) {
// TODO Auto-generated method stub
return (x < y) ? -1 : 1;
} }); for (Tuple2<String, Integer> element : input) {
treemap.put(element.f1, element);
if (treemap.size() > topSize) {
treemap.pollLastEntry();
}
} for (Entry<Integer, Tuple2<String, Integer>> entry : treemap
.entrySet()) {
out.collect(entry.getValue());
} } }

上面的代码实现了按照首字母分组,取每组元素count最高的TopN方法。

嵌套TopN

全局topN的缺陷是,由于windowall是一个全局并发为1的操作,所有的数据只能汇集到一个节点进行 TopN 的计算,那么计算能力就会受限于单台机器,容易产生数据热点问题。

解决思路就是使用嵌套 TopN,或者说两层 TopN。在原先的 TopN 前面,再加一层 TopN,用于分散热点。例如可以先加一层分组 TopN,第一层会计算出每一组的 TopN,而后在第二层中进行合并汇总,得到最终的全网TopN。第二层虽然仍是单点,但是大量的计算量由第一层分担了,而第一层是可以水平扩展的。


基于flink快速开发实时TopN程序的更多相关文章

  1. Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架

    Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的. 历史 Bootstrap 是由 Twitter 的 ...

  2. 基于NSIS脚本开发的安装程序制作软件:易量安装

    原文 基于NSIS脚本开发的安装程序制作软件:易量安装 前几天“萝卜”给我推荐了一款安装程序制作工具——易量安装. 易量安装是一款安装程序制作软件,基于著名的NSIS(Nullsoft Scripta ...

  3. 基于django快速开发一个网站(一)

    基于django快速开发一个网站(一) *  创建虚拟环境.基于虚拟环境创建django==2.0.0和图片加载库和mysql数据库驱动 1. 创建目录并创建虚拟环境 ╰$ mkdir Cornuco ...

  4. 快速开发微信小程序

    image.png 最近婷主在做微信小程序.自己的微信公众号也需要添加点料,乘着这次放假,把微信小程序研究了下.虽然没有做什么很强大的功能,不过好歹自己的公众号也有了微信小程序.够用即可. 1.需要先 ...

  5. Sublime插件库新成员基于APICloud快速开发跨平台App

    互联网时代强调用户体验,那什么是HTML5跨平台App开发者的编程体验?“不剥夺.不替换开发者喜欢的开发工具,就是人性化的用户体验”,APICloud给出了这样的答案! 重磅发布“多开发工具支持策略” ...

  6. 使用Node.js的socket.io模块开发实时web程序

    首发:个人博客,更新&纠错&回复 今天的思维漫游如下:从.net的windows程序开发,摸到nodejs的桌面程序开发,又熟悉了一下nodejs,对“异步”的理解有了上上周对操作系统 ...

  7. AAuto 快速开发win32小程序

    AAuto编程语言 AAuto是专用于桌面软件快速开发的新一代混合型编程语言 -  具有动态语言轻便.灵活.快速开发的特性,而且又可以同时支持静态类型开发,象静态语言那样使用.AAuto可以直接支持原 ...

  8. Weshop基于Spring Cloud开发的小程序商城系统

    WESHOP | 基于微服务的小程序商城系统 Weshop是基于Spring Cloud(Greenwich)开发的小程序商城系统,提供整套公共微服务服务模块,包含用户中心.商品中心.订单中心.营销中 ...

  9. 如何基于 PHP-X 快速开发一个 PHP 扩展

    0x01 起步 PHP-X本身基于C++11开发,使用cmake进行编译配置.首先,你需要确定所有依赖项已安装好.包括: gcc-4.8 或更高版本 PHP7.0 或更高版本,需要php7-dev 开 ...

随机推荐

  1. Toad 常用快捷键

    F9             执行全部sql                Ctrl_Enter     执行当前sql                Ctrl+T     补全table_name  ...

  2. VMware8安装MacOS 10.8

    前一篇博客,介绍了如何利用VMware安装MacOS系统,虽然可以安装成功,但也有不友好的地方,如: 1)MacOS系统文件需要是ISO格式,不是原生的dmg格式: 2)每次开机都需要借助HJMac工 ...

  3. ylbtech-LanguageSamples-Indexers(索引器)

    ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Indexers(索引器) 1.A,示例(Sample) 返回顶部 “索引器”示例 本示 ...

  4. zabbix3.x安装出现“configure: error: Not found mysqlclient library”的解决办法

    一.zabbix3.x安装出现“configure: error: Not found mysqlclient library”的解决办法 1.编译安装zabbix-server出现 编译时加参数:- ...

  5. 使用rsync进行多服务器同步

    使用rsync进行多服务器同步 @(Others) 当集群数量很大时,修改配置文件和节点之间的文件同步是一件很麻烦且浪费时间的事情. rsync是linux上实现不同机器之间文件同步.备份的工具,ce ...

  6. select()/poll() 的内核实现

    mark 引用:http://janfan.cn/chinese/2015/01/05/select-poll-impl-inside-the-kernel.html 文章 select()/poll ...

  7. M.U.G.E.N Error怎么办

    当运行乱舞格斗2008的时候出现以下错误. 在任务管理器中找到M.U.G.E.N.exe这个进程,右击设置相关性,然后取消勾选其中一个,点击确定. 不要关闭这个窗口,否则M.U.G.E.N这个进程也将 ...

  8. SOA服务总线设计

    背景 基于总线的设计,借鉴了计算机内部硬件组成的设计思想(通过总线传输数据).在分布式系统中,不同子系统之间需要实现相互通信和远程调用,比较直接的方式就是“点对点”的通信方式,但是这样会暴露出一些很明 ...

  9. css颜色大全

    本文来自:http://www.cnblogs.com/axing/archive/2011/04/09/CSS.html CSS颜色代码大全: FFFFFF #DDDDDD #AAAAAA #888 ...

  10. OpenCV中的矩阵和图像类型

    任务刚刚做完,就迫不及待的来写写在OpenCV中常见的几类数据类型: 在使用OpenCV时我们时常会碰到IplImage这个数据类型,IplImage就是我们通常说的“图像”进行编码的基本结构,这些图 ...