基于flink快速开发实时TopN程序
转发请注明原创地址: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程序的更多相关文章
- Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架
Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的. 历史 Bootstrap 是由 Twitter 的 ...
- 基于NSIS脚本开发的安装程序制作软件:易量安装
原文 基于NSIS脚本开发的安装程序制作软件:易量安装 前几天“萝卜”给我推荐了一款安装程序制作工具——易量安装. 易量安装是一款安装程序制作软件,基于著名的NSIS(Nullsoft Scripta ...
- 基于django快速开发一个网站(一)
基于django快速开发一个网站(一) * 创建虚拟环境.基于虚拟环境创建django==2.0.0和图片加载库和mysql数据库驱动 1. 创建目录并创建虚拟环境 ╰$ mkdir Cornuco ...
- 快速开发微信小程序
image.png 最近婷主在做微信小程序.自己的微信公众号也需要添加点料,乘着这次放假,把微信小程序研究了下.虽然没有做什么很强大的功能,不过好歹自己的公众号也有了微信小程序.够用即可. 1.需要先 ...
- Sublime插件库新成员基于APICloud快速开发跨平台App
互联网时代强调用户体验,那什么是HTML5跨平台App开发者的编程体验?“不剥夺.不替换开发者喜欢的开发工具,就是人性化的用户体验”,APICloud给出了这样的答案! 重磅发布“多开发工具支持策略” ...
- 使用Node.js的socket.io模块开发实时web程序
首发:个人博客,更新&纠错&回复 今天的思维漫游如下:从.net的windows程序开发,摸到nodejs的桌面程序开发,又熟悉了一下nodejs,对“异步”的理解有了上上周对操作系统 ...
- AAuto 快速开发win32小程序
AAuto编程语言 AAuto是专用于桌面软件快速开发的新一代混合型编程语言 - 具有动态语言轻便.灵活.快速开发的特性,而且又可以同时支持静态类型开发,象静态语言那样使用.AAuto可以直接支持原 ...
- Weshop基于Spring Cloud开发的小程序商城系统
WESHOP | 基于微服务的小程序商城系统 Weshop是基于Spring Cloud(Greenwich)开发的小程序商城系统,提供整套公共微服务服务模块,包含用户中心.商品中心.订单中心.营销中 ...
- 如何基于 PHP-X 快速开发一个 PHP 扩展
0x01 起步 PHP-X本身基于C++11开发,使用cmake进行编译配置.首先,你需要确定所有依赖项已安装好.包括: gcc-4.8 或更高版本 PHP7.0 或更高版本,需要php7-dev 开 ...
随机推荐
- Mac OS X 11年9个版本的历经变化
本月苹果将发布OS X 10.8 Mountain Lion,是Mac OS X系统在其11年生命长河中的第9个版本.2001年,刚从鬼门关爬回来的苹果决定在OS X上做一个赌注,因为他们已经浪费了1 ...
- 解决kylin报错:Failed to create dictionary on <db>.<table>, Caused by: java.lang.IllegalArgumentException: Too high cardinality is not suitable for dictionary
报错信息: 2017-05-13 15:14:30,035 DEBUG [pool-9-thread-10] dict.DictionaryGenerator:94 : Dictionary clas ...
- Traefik的TLS配置
生产环境的部署大多采用F5+ Traefik这种方式,因为Traefik的SSL方式相对来说比较慢,因此SSL更多的在F5上开放,而F5到Traefik之间以及后端都是http方式. 但客户需要在开发 ...
- jquery中remove()与detach()的区别
说到删除节点,马上就会想到remove,不过原来还有一个detach,而且它们还是有区别的,就是detach保留了jquery的数据,而remove就会完全删除干净.所以如果在删除一个dom节点后还想 ...
- Shadow Map 原理和改进 【转】
http://blog.csdn.net/ronintao/article/details/51649664 参考 1.Common Techniques to Improve Shadow Dept ...
- "com.android.ide.s.ProcessException:Process 'cand 'C:\Program Files\Java\jdk1.8.0_60\bin\java.exe'' finished with non-zero exit value 2"
使用Android Studio 出现该问题: "com.android.ide.common.process.ProcessException: org.gradle.process.in ...
- jquery 获取标签名(tagName)
如果是为了取到tagName后再进行判断,那直接用下面的代码会更方便: $(element).is('input') 如果是要取到标签用作到别的地方,可以使用一下代码: $(element)[0].t ...
- IntelliJ IDEA java开发 WebService
测试的功能是通过访问solr服务器,获取相关信息,然后以webservice的形式供客户端访问来获取数据.通过查询资料,现在把过程记录如下: 1.环境 IntelliJ IDEA 2017.2.6 J ...
- 怎样在Ubuntu手机应用中得到全部的环境变量值
我们在先前的例程中已经通过一些方法得到我们应用的一些环境变量值.这些值有的很实用.比方我们能够得到我们应用所仅仅能訪问的文件夹.在今天的例程中,我们来展示一种方法能够得到应用全部的环境变量.在我们的实 ...
- Android之旅七 Service简介
1. Service是什么:它是一个应用程序组件.没有图形化界面.通常用来处理一些耗时比较长的操作(例如下载.播放MP3等等).可以使用Service更新ContentProvide ...