直播有赞短视频频这个哪真的很赞呢

1、今天主管提了个需求需要查詢上海市公布一批高新技术企业的基本

2、下载打开一看,pdf格式是这样子的112页,这也不能直接用啊

成功合并Excel表,整理丢到数据库考虑實现方式。

4、理论上实现的方式:

登录网页版本实现的方式: 只要不停的检索公司名称即可得到公司信息

但是只有会员才能拿到全部信息恏的 ,去某宝花一块钱买一天的会员

近3000多条信息手工查询肯定不行,想想上代码吧

5、代码实现,理论上人通过浏览器也可以实现

模擬浏览器登录---脚本自动填充搜索---下载信息---退出,一顿操作猛如虎开始上代码:

 # 设置延时,用企查查app扫码登陆
 #定位登录后页面搜索框输叺要查询的公司,按回车键
 k = "上海欧朔智能包装科技有限公司"
 #下载单前页面,进行页面解析提取数据
 
 #页面发生了变化再次定位到新的页面
 #连接数据库,调取数据
 #定位第二页输入框传入
 # 下载单前页面,进行页面解析提取数据
 

}

整理 | 祝尚(Flink 社区志愿者)

校对 | 邹誌业(Flink 社区志愿者)

1. 整体思路与学习路径

2. 应用场景与编程模型

3. 工作流程与实现机制

Tips:点击「阅读原文」可查看更多数仓系列直播视频~

当峩们碰到一项新的技术时我们应该怎样去学习并应用它呢?在我个人看来有这样一个学习的路径,应该把它拆成应用和实现两块首先应该从它的应用入手,然后再深入它的实现

应用主要分为三个部分,首先应该了解它的应用场景比如窗口的一些使用场景。然后進一步地我们去了解它的编程接口,最后再深入了解它的一些抽象概念因为一个框架或一项技术,肯定有它的编程接口和抽象概念来组荿它的编程模型我们可以通过查看文档的方式来熟悉它的应用。在对应用这三个部分有了初步的了解后我们就可以通过阅读代码的方式去了解它的一些实现了。

实现部分也分三个阶段首先从工作流程开始,可以通过 API 层面不断的下钻来了解它的工作流程接下来是它整體的设计模式,通常对一些框架来说如果能构建一个比较成熟的生态,一定是在设计模式上有一些独特的地方使其有一个比较好的扩展性。最后是它的数据结构和算法因为为了能够处理海量数据并达到高性能,它的数据结构和算法一定有独到之处我们可以做些深入叻解。

以上大概是我们学习的一个路径从实现的角度可以反哺到应用上来,通常在应用当中刚接触某个概念的时候会有一些疑惑。当峩们对实现有一些了解之后应用中的这些疑惑就会迎刃而解。

看了这个例子我们可能会有些疑惑:

  • 当 key 基数很大时如何有效地触发每个 key 窗口计算?

  • 窗口计算的中间结果如何存储何时被清理?

当你了解了实现部分再回来看应用这部分可能就有种醍醐灌顶的感觉。

缺点:甴于 MySQL 存储数据有限所以聚合的时间粒度不能太细,维度组合不能太多

■ 第二种架构相对于第一种引入了 OLAP 引擎,同时也不用 Flink 来做聚合通过 Druid 的 Rollup 来做聚合。

缺点:因为 Druid 是一个存储和查询引擎不是计算引擎。当数据量巨大时比如每天上百亿、千亿的数据量,会加剧 Druid 的导入壓力

■ 第三种架构在第二种基础上,采用 Flink 来做聚合计算写入 Kafka最终写入 Druid。

缺点:当窗口粒度比较长时结果输出会有延迟。

■ 聚合统计:从 Kafka 读取数据根据不同的维度做1分钟或5分钟的聚合计算,然后结果写入 MySQL 或 Druid 中

■ 记录合并:对多个 Kafka 数据源在一定的窗口范围内做合并,結果写入 ES例如:用户的一些行为数据,针对每个用户可以对其行为做一定的合并,减少写入下游的数据量降低 ES 的写入压力。

■ 双流 join:针对双流 join 的场景如果全量 join 的话,成本开销会非常大所以就要考虑基于窗口来做 join。

■ WindowAssigner:窗口分配器用来确定哪些数据被分配到哪些窗口。

■ State:状态用来存储窗口内的元素,如果有 AggregateFunction则存储的是增量聚合的中间结果。

■ AggregateFunction(可选):增量聚合函数主要用来做窗口的增量计算,减轻窗口内 State 的存储压力

■ Trigger:触发器,用来确定何时触发窗口的计算

■ Evictor(可选):驱逐器,用于在窗口函数计算之前(后)对滿足驱逐条件的数据做过滤

■ Collector:收集器,用来将窗口的计算结果发送到下游

上图中红色部分都是可以自定义的模块,通过自定义这些模块的组合我们可以实现高级的窗口应用。同时 Flink 也提供了一些内置的实现可以用来做一些简单应用。



  

首先我们先指定时间戳和 Watermark 如何生荿;然后选择需要聚合的维度的 Key;再选择一个窗口和选择用什么样的触发器来触发窗口计算以及选择驱逐器做什么样的过滤;最后确定窗口应该做什么样计算。

接下来我们详细看下每个模块

总结一下主要有3类窗口:

Trigger 是一个比较重要的概念,用来确定窗口什么时候触发计算

假如我们定义一个5分钟的基于 EventTime 的滚动窗口,定义一个每2分触发计算的 Trigger有4条数据事件时间分别是20:01、20:02、20:03、20:04,对应的值分别是1、2、3、2我們要对值做 Sum 操作。

当第一条数据在20:01进入窗口时State 的值为1,此时还没有到达 Trigger 的触发时间

第二条数据在20:02进入窗口,State 中的值为1+2=3此时达到2分钟滿足 Trigger 的触发条件,所以 Result 输出结果为3

第三条数据在20:03进入窗口,State 中的值为3+3 = 6此时未达到 Trigger 触发条件,没有结果输出

第四条数据在20:04进入窗口,StateΦ的值更新为6+2=8此时又到了2分钟达到了 Trigger 触发时间,所以输出结果为8如果我们把结果输出到支持 update 的存储,比如 MySQL那么结果值就由之前的3更噺成了8。

如果 Result 不支持 update 操作只能 append 的话,则会输出2条记录在此基础上再做计算处理就会引起错误。

前两条数据先后于20:01和20:02进入窗口此时 State 中嘚值更新为3,同时到了Trigger的触发时间输出结果为3。

当后两条数据进入窗口之后State 重新从0开始累计并更新为5,输出结果为5

由于结果输出是 append 模式,会输出3和5两条数据然后再做 Sum 也能得到正确的结果。

上面就是 PurgingTrigger 的一个简单的示例它还支持很多有趣的玩法。

有这样一个车辆区间測试的需求车辆每分钟上报当前位置与车速,每行进10公里计算区间内最高车速。

首先需要考虑的是如何来划分窗口它不是一个时间嘚窗口,也不是一个基于数量的窗口用传统的窗口实现比较困难,这种情况下我们考虑使用 DeltaTrigger 来实现

下面是简单的代码实现:

如何提取時间戳和生成水印,以及选择聚合维度就不赘述了这个场景不是传统意义上的时间窗口或数量窗口,可以创建一个 GlobalWindow所有数据都在一个窗口中,我们通过定义一个 DeltaTrigger并设定一个阈值,这里是10000(米)每个元素和上次触发计算的元素比较是否达到设定的阈值,这里比较的是烸个元素上报的位置如果达到了10000(米),那么当前元素和上一个触发计算的元素之间的所有元素落在同一个窗口里计算然后可以通过 Max 聚合计算出最大的车速。

基于上面的区间测速的场景每行进10公里,计算区间内最近15分钟最高车速

实现上只是在前面基础上增加了 Evictor 的使鼡,过滤掉窗口最后15分钟之前的数据

Flink 内置的 WindowFunction 有两种类型,第一种是 AggregateFunction它是高级别的抽象,主要用来做增量聚合每来一条元素都做一次聚合,这样状态里只需要存最新的聚合值

  • 优点:增量聚合,实现简单

  • 缺点:输出只有一个聚合值,使用场景比较局限

第二种是 ProcessWindowFunction,它昰低级别的抽象用来做全量聚合每来一条元素都存在状态里面,只有当窗口触发计算时才会调用这个函数

  • 优点:可以获取到窗口内所囿数据的迭代器,实现起来比较灵活;可以获取到聚合的  Key 以及可以从上下文 Context 中获取窗口的相关信息

  • 缺点:需要存储窗口内的全量数据,State 嘚压力较大

同时我们可以把这两种方式结合起来使用,通过 AggregateFunction 做增量聚合减少中间状态的压力。通过 ProcessWindowFunction 来输出我们想要的信息比如聚合嘚 Key 以及窗口的信息。

上一节我们介绍了窗口的一些抽象的概念包括它的编程接口,通过一些简单的示例介绍了每个抽象概念的的用法

這一节我们深入的研究以下窗口底层是怎么实现的。

首先看下 WindowOperator 的工作流程代码做了一些简化,只保留了核心步骤

主要包括以下8个步骤:

前面提到的增量聚合计算和全量聚合计算,这两个场景所应用的 State 是不一样的

如果是全量聚合,元素会添加到 ListState 当中当触发窗口计算时,再把 ListState 中所有元素传递给窗口函数

在触发窗口计算时会将窗口中的状态传递给 emitWindowContents 方法。这里会调用我们定义的窗口函数中的 process 方法将当前嘚 Key、Window、上下文 Context、窗口的内容作为参数传给它。在此之前和之后会分别调用 evictBefore 和evictAfter 方法把一些元素过滤掉最终会调用 windowState 的 clear 方法,再把过滤之后的記录存到 windowState 中去从而达到 evictor 过滤元素的效果。

最后看下 Trigger 的实现原理当我们有大量的 Key,同时每个 Key 又属于多个窗口时我们如何有效的触发窗ロ的计算呢?

Flink 利用定时器来保证窗口的触发通过优先级队列来存储定时器。队列头的定时器表示离当前时间最近的一个如果当前定时器比队列头的定时器时间还要早,则取消掉队列头的定时器把当前的时间注册进去。

当这次定时器触发之后再从优先级队列中取下一個 Timer,去调用 trigger 处理的函数再把下一个 Timer 的时间注册为定时器。这样就可以循环迭代下去

本文主要分享了 Flink 窗口的应用与实现。首先介绍了学習一项新技术的整体思路与学习路径从应用入手慢慢深入它的实现。然后介绍了实时数仓的典型架构发展历程之后从窗口的应用场景、抽象概念、编程结构详细说明了窗口的各个组成部分。并通过一些示例详细展示了各个概念之间配合使用可以满足什么样的使用场景朂后深入窗口的实现,从源码层面说明了窗口各模块的工作流程

Tips:点击「阅读原文」可回顾作者分享视频及了解更多数仓系列直播


关紸 Flink 中文社区,获取更多技术干货

你也「在看」吗????

}

我要回帖

更多关于 有赞短视频 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信