乐趣区

关于flink:专治数仓疑难杂症美团点评-Flink-实时数仓应用经验分享

实时数仓建设目标

解决传统数仓的问题

实时数仓是一个很容易让人产生混同的概念。实时数仓自身仿佛和把 PPT 彩色的背景变得更白一样,从传统的教训来讲,咱们认为数仓有一个很重要的性能,即可能记录历史。通常,数仓都是心愿从业务上线的第一天开始有数据,而后始终记录到当初。

但实时处理技术,又是强调以后解决状态的一门技术,所以咱们认为这两个绝对对抗的计划重叠在一起的时候,它注定不是用来解决一个比拟宽泛问题的一种计划。于是,咱们把实时数仓建设的目标定位为解决因为传统数据仓库数据时效性低解决不了的问题。

因为这个特点,咱们给定了两个准则:

  • 传统数仓能解决的问题,实时数仓就不解决了。比方上个月的一些历史的统计,这些数据是不会用实时数仓来建设的。
  • 问题自身就不太适宜用数仓来解决,也不必实时数仓解决。比方业务性很强的需要,或者是对时效性要求特地高的需要。这些需要咱们也不倡议通过实时数仓这种形式来进行解决。

当然为了让咱们整个零碎看起来像是一个数仓,咱们还是给本人提了一些要求的。这个要求其实跟咱们建设离线数仓的要求是一样的,首先实时的数仓是须要面向主题的,而后具备集成性,并且保障绝对稳固。

离线数仓和实时数仓的区别在于离线数据仓库是一个保留历史累积的数据,而咱们在建设实时数仓的时候,咱们只保留上一次批处理到以后的数据。这个说法十分的拗口,然而实际上操作起来还是蛮轻松的。

通常来讲解决方案是保留大略三天的数据,因为保留三天的数据的话,能够稳固地保障两天残缺的数据,这样就能保障,在批处理流程还没有解决完昨天的数据的这段间隙,仍然可能提供一个残缺的数据服务。

实时数仓的利用场景

  • 实时 OLAP 剖析

OLAP 剖析自身就非常适合用数仓去解决的一类问题,咱们通过实时数仓的扩大,把数仓的时效性能力进行晋升。甚至可能在剖析层面上都不必再做太多革新,就能够使原有的 OLAP 剖析工具具备剖析实时数据的能力。

  • 实时数据看板

这种场景比拟容易接受,比方天猫双 11 的实时大屏滚动展现外围数据的变动。实际上对于美团来讲,不光有促销上的业务,还有一些次要的门店业务。对于门店的老板而言,他们可能在日常的每一天中也会很关怀本人当天各个业务线上的销售额。

  • 实时特色

实时特色指通过汇总指标的运算来对商户或者用户标记上一些特色。比方屡次购买商品的用户后盾会断定为优质用户。另外,商户销售额稿,后盾会认为该商户商的热度更高。而后,在做实时精准经营动作时可能会优先思考相似的门店或者商户。

  • 实时业务监控

美团点评也会对一些外围业务指标进行监控,比如说当线上呈现一些问题的时候,可能会导致某些业务指标降落,咱们能够通过监控尽早发现这些问题,进而来缩小损失。

如何建设实时数仓

实时数仓概念映射

咱们通过离线数仓开发和实时数仓开发的对应关系表,帮忙大家疾速清晰的了解实时数仓的一些概念。

  • 编程形式

离线开发最常见的计划就是采纳 Hive SQL 进行开发,而后加上一些扩大的 udf。映射到实时数仓里来,咱们会应用 Flink SQL,同样也是配合 udf 来进行开发。

  • 作业执行层面

离线解决的执行层面个别是 MapReduce 或者 Spark Job,对应到实时数仓就是一个继续一直运行的 Flink Streaming 的程序。

  • 数仓对象层面

离线数仓实际上就是在应用 Hive 表。对于实时数仓来讲,咱们对表的形象是应用 Stream Table 来进行形象。

  • 物理存储

离线数仓,咱们少数状况下会应用 HDFS 进行存储。实时数仓,咱们更多的时候会采纳像 Kafka 这样的音讯队列来进行数据的存储。

实时数仓的整体架构

在此之前咱们做过一次分享,是对于为什么抉择 Flink 来做实时数仓,其中重点介绍了技术组件选型的起因和思路,具体内容参考《美团点评基于 Flink 的实时数仓建设实际》。本文分享的次要内容是围绕数据自身来进行的,上面是咱们目前的实时数仓的数据架构图。

《美团点评基于 Flink 的实时数仓建设实际》
https://tech.meituan.com/2018/10/18/meishi-data-flink.html

从数据架构图来看,实时数仓的数据架构会跟离线数仓有很多相似的中央。比方分层构造;比如说 ODS 层,明细层、汇总层,乃至应用层,它们命名的模式可能都是一样的。尽管如此,实时数仓和离线数仓还是有很多的区别的。

跟离线数仓次要不一样的中央,就是实时数仓的档次更少一些。

以咱们目前建设离线数仓的教训来看,数仓的第二层远远不止这么简略,个别都会有一些轻度汇总层这样的概念,其实第二层会蕴含很多层。另外一个就是应用层,以往建设数仓的时候,应用层其实是在仓库外部的。在应用层建设好后,会建同步工作,把数据同步到利用零碎的数据库里。

在实时数仓外面,所谓 APP 层的利用表,实际上就曾经在利用零碎的数据库里了。上图,尽管画了 APP 层,但它其实并不算是数仓里的表,这些数据实质上曾经存过来了。

为什么主题档次要少一些?是因为在实时处理数据的时候,每建一个档次,数据必然会产生肯定的提早。

为什么汇总层也会尽量少建?是因为在汇总统计的时候,往往为了容忍一部分数据的提早,可能会人为的制作一些提早来保证数据的精确。

举例,统计事件中的数据时,可能会等到 10:00:05 或者 10:00:10 再统计,确保 10:00 前的数据曾经全副承受到位了,再进行统计。所以,汇总层的档次太多的话,就会更大的减轻人为造成的数据提早。

倡议尽量减少档次,特地是汇总层肯定要缩小,最好不要超过两层。明细层可能多一点档次还好,会有这种零碎明细的设计概念。

第二个比拟大的不同点就是在于数据源的存储。

在建设离线数仓的时候,可能整个数仓都全副是建设在 Hive 表上,都是跑在 Hadoop 上。然而,在建设实时数仓的时候,同一份表,咱们甚至可能会应用不同的形式进行存储。

比方常见的状况下,可能绝大多数的明细数据或者汇总数据都会存在 Kafka 外面,然而像维度数据,可能会存在像 Tair 或者 HBase 这样的 kv 存储的零碎中,实际上可能汇总数据也会存进去,具体起因前面详细分析。除了整体构造,咱们也分享一下每一层建设的要点。

■ ODS 层的建设

数据起源尽可能对立,利用分区保证数据部分有序

首先第一个建设要点就是 ODS 层,其实 ODS 层建设可能跟仓库不肯定有必然的关系,只有应用 Flink 开发程序,就必然都要有实时的数据源。目前次要的实时数据源是音讯队列,如 Kafka。而咱们目前接触到的数据源,次要还是以 binlog、流量日志和系统日志为主。

这外面我次要想讲两点:

首先第一个建设要点就是 ODS 层,其实 ODS 层建设可能跟这个仓库不肯定有必然的关系,只有你应用这个 flink 开发程序,你必然都要有这种实时的数据源。目前的次要的实时数据源就是音讯队列,如 kafka。咱们目前接触到的数据源,次要还是以 binlog、流量日志和系统日志为主。

这外面我次要想讲两点,一个这么多数据源我怎么选?咱们认为以数仓的教训来看:

首先就是数据源的起源尽可能要对立。 这个对立有两层含意:

  • 第一个对立就是实时的数据源自身要跟本人对立,比方你抉择从某个零碎接入某一种数据,要么都从 binlog 来接,要么都从系统日志来接,最好不要混着接。在不晓得数据生产的流程的状况下,一部分通过 binlog 接入一部分通过系统日志接入,容易呈现数据乱序的问题。
  • 第二个对立是指实时和离线的对立,这个对立可能更重要一点。尽管咱们是建设实时数仓,然而实质上还是数仓,作为一个团队来讲,仓库里的指标的计算逻辑和数据起源应该完全一致,不能让应用数据的人产生误解。如果一个数据两个团队都能为你提供,咱们倡议抉择跟离线同学统一的数据起源。包含咱们公司自身也在做一些保障离线和实时采纳的数据源统一的工作。

第二个要点就是数据乱序的问题,咱们在采集数据的时候会有一个比拟大的问题,可能同一条数据,因为分区的存在,这条数据先产生的状态后生产到,后产生的状态先生产到。咱们在解决这一问题的时候采纳的是美团外部的一个数据组件。

其实,保证数据有序的次要思路就是利用 kafka 的分区来保证数据在分区内的部分有序。至于具体如何操作,能够参考《美团点评基于 Flink 的实时数仓建设实际》。这是咱们美团数据同步部门做的一套计划,能够提供十分丰盛的策略来保障同一条数据是依照生产程序进行保序生产的,实现在源头解决数据乱序的问题。

■ DW 层的建设

解决原始数据中数据存在噪声、不残缺和数据模式不对立的状况。造成标准,对立的数据源。如果可能的话尽可能和离线保持一致。

明细层的建设思路其实跟离线数仓的基本一致,次要在于如何解决 ODS 层的数据可能存在的数据噪声、不残缺和模式不对立的问题,让它在仓库内是一套满足标准的对立的数据源。咱们的倡议是如果有可能的话,最好入什么仓怎么入仓,这个过程和离线保持一致。

尤其是一些数据起源比拟对立,然而开发的逻辑常常变动的零碎,这种状况下,咱们可能采纳的其实是一套基于配置的入仓规定。可能离线的同学有一套入仓的零碎,他们配置好规定就晓得哪些数据表上数据要进入实时数仓,以及要录入哪些字段,而后实时和离线是采纳同一套配置进行入仓,这样就能够保障咱们的离线数仓和实时数仓在 DW 层长期保持一个统一的状态。

实际上建设 DW 层其实次要的工作次要是以下 4 局部。

惟一标红的就是模型的规范化,其实模型的规范化,是一个陈词滥调的问题,可能每个团队在建设数仓之前,都会先把本人的规范化写进去。但理论的后果是咱们会看到其实并不是每一个团队最终都能把标准落地。

在实时的数仓建设当中,咱们要特别强调模型的规范化,是因为施行数仓有一个特点,就是自身实时作业是一个 7×24 小时调度的状态,所以当批改一个字段的时候,可能要付出的运维代价会很高。在离线数仓中,可能改了某一个表,只有一天之内把上游的作业也改了,就不会出什么问题。然而实时数仓就不一样了,只有改了上游的表构造,上游作业必须是可能正确解析上游数据的状况下才能够。

另外应用像 kafka 这样的零碎,它自身并不是结构化的存储,没有元数据的概念,也不可能像改表一样,间接把之前不标准的表名、表类型改标准。要在预先进行标准代价会很大。所以倡议肯定要在建设之初就尽快把这些模型的规范化落地,防止后续要投入十分大的代价进行治理。

  • 反复数据处理

除了数据自身咱们会在每条数据上额定补充一些信息,应答实时数据生产环节的一些常见问题

  • 惟一键和主键

咱们会给每一条数据都补充一个惟一键和一个主键,这两个是一对的,惟一键就是标识是惟一一条数据的,主键是标记为一行数据。一行数据可能变动很屡次,然而主键是一样的,每一次变动都是其一次惟一的变动,所以会有一个惟一键。惟一键次要解决的是数据反复问题,从分层来讲,数据是从咱们仓库以外进行生产的,所以很难保障咱们仓库以外的数据是不会反复的。

可能有些人交付数据给也会告知数据可能会有反复。生成惟一键的意思是指咱们须要保障 DW 层的数据可能有一个标识,来解决可能因为上游产生的反复数据导致的计算反复问题。生成主键,其实最次要在于主键在 kafka 进行分区操作,跟之前接 ODS 保障分区有序的原理是一样的,通过主键,在 kafka 里进行分区之后,生产数据的时候就能够保障单条数据的生产是有序的。

  • 版本和批次

版本和批次这两个其实又是一组。当然这个内容名字能够轻易起,最重要的是它的逻辑。

首先,版本。版本的概念就是对应的表构造,也就是 schema 一个版本的数据。因为在解决实时数据的时候,上游的脚本依赖表上一次的 schema 进行开发的。当数据表构造发生变化的时候,就可能呈现两种状况:第一种状况,可能新加或者删减的字段并没有用到,其实齐全不必感知,不必做任何操作就能够了。另外一种状况,须要用到变动的字段。此时会产生一个问题,在 Kafka 的表中,就相当于有两种不同的表构造的数据。这时候其实须要一个标记版本的内容来通知咱们,生产的这条数据到底应该用什么样的表构造来进行解决,所以要加一个像版本这样的概念。

第二,批次。批次实际上是一个更不常见的场景,有些时候可能会产生数据重导,它跟重启不太一样,重启作业可能就是改一改,而后接着上一次生产的地位启动。而重导的话,数据生产的地位会发生变化。

比方,明天的数据算错了,领导很着急让我改,而后我须要把明天的数据重算,可能把数据程序修改好之后,还要设定程序,比方从明天的凌晨开始从新跑。这个时候因为整个数据程序是一个 7×24 小时的在线状态,其实原先的数据程序不能停,等重导的程序追上新的数据之后,能力把原来的程序停掉,最初应用重导的数据来更新后果层的数据。

在这种状况下,必然会短暂的存在两套数据。这两套数据想要进行辨别的时候,就要通过批次来辨别。其实就是所有的作业只生产指定批次的数据,当重导作业产生的时候,只有生产重导批次的作业才会生产这些重导的数据,而后数据追上之后,只有把原来批次的作业都停掉就能够了,这样就能够解决一个数据重导的问题。

■ 维度数据建设

其次就是维度数据,咱们的明细层外面包含了维度数据。对于维度的数据的解决,实际上是先把维度数据分成了两大类采纳不同的计划来进行解决。

  • 变动频率低的维度

第一类数据就是一些变动频率比拟低的数据,这些数据其实可能是一些基本上是不会变的数据。比如说,一些天文的维度信息、节假日信息和一些固定代码的转换。

这些数据实际上咱们采纳的办法就是间接能够通过离线仓库外面会有对应的维表,而后通过一个同步作业把它加载到缓存中来进行拜访。还有一些维度数据创立得会很快,可能会一直有新的数据创立进去,然而一旦创立进去,其实也就不再会变了。

比如说,美团上开了一家新的门店,门店所在的城市名字等这些固定的属性,其实可能很长时间都不会变,取最新的那一条数据就能够了。这种状况下,咱们会通过公司外部的一些公共服务,间接去拜访以后最新的数据。最终,咱们会包一个维度服务的这样一个概念来对用户进行屏蔽,具体是从哪里查问相干细节,通过维度服务即可关联具体的维度信息。

  • 变动频率高的维度

第二类是一些变动频率较高的数据。比方常见的病人心脑科的状态变动,或者某一个商品的价格等。这些货色往往是会随着工夫变动比拟频繁,比拟快。而对于这类数据,咱们的解决计划就略微简单一点。首先对于像价格这样变动比拟频繁的这种维度数据,会监听它的变动。比如说,把价格设想成维度,咱们会监听维度价格变动的音讯,而后构建一张价格变换的拉链表。

一旦建设了维度拉链表,当一条数据来的时候,就能够晓得,在这个数据某一时刻对应的精确的维度是多少,防止了因为维度疾速的变动导致关联错维度的问题。

另一类如新老客这维度,于咱们而言其实是一种衍生维度,因为它自身并不是维度的计算形式,是用该用户是否下过单来计算出来的,所以它其实是用订单数据来算进去的一个维度。

所以相似订单数的维度,咱们会在 DW 层建设一些衍生维度的计算模型,而后这些计算模型输入的其实也是拉链表,记录下一个用户每天这种新老客的变动水平,或者可能是一个优质用户的变动的过程。因为建设拉链表自身也要关联维度,所以能够通过之前分组 key 的形式来保障不乱序,这样还是将其当做一个不变的维度来进行关联。

通过这种形式来建设拉链表绝对麻烦,所以实际上倡议利用一些内部组件的性能。实际操作的时候,咱们应用的是 Hbase。HBase 自身反对数据多版本的,而且它能记录数据更新的工夫戳,取数据的时候,甚至能够用这个工夫戳来做索引。

所以实际上只有把数据存到 HBase 里,再配合上 mini-versions,就能够保证数据不会超时死掉。下面也提到过,整个实时数仓有一个大准则,不解决离线数仓能解决的过程。相当于解决的过程,只须要解决三天以内的数据,所以还能够通过配置 TTL 来保障 HBase 里的这些维度能够尽早的被淘汰掉。因为很多天以前的维度,实际上也不会再关联了,这样就保障维度数据不会无限度的增长,导致存储爆炸。

■ 维度数据应用

解决维度数据之后,这个维度数据怎么用?

第一种计划,也是最简略的计划,就是应用 UDTF 关联。其实就是写一个 UDTF 去查问下面提到的维度服务,具体来讲就是用 LATERAL TABLE 关键词来进行关联,内外关联都是反对的。

另外一种计划就是通过解析 SQL,辨认出关联的维表以及维表中的字段,把它本来的查问进行一次转化为原表.flatmap (维表),最初把整个操作的后果转换成一张新的表来实现关联操作。

然而这个操作要求使用者有很多周边的零碎来进行配合,首先须要能解析 SQL,同时还能辨认文本,记住所有维表的信息,最初还要能够执行 SQL 转化,所以这套计划适宜一些曾经有成熟的基于 Flink SQL 的 SQL 开发框架的零碎来应用。如果只是单纯的写封装的代码,倡议还是应用 UDTF 的形式来进行关联会十分的简略,而且成果也是一样的。

■ 汇总层的建设

在建设实时数仓的汇总层的时候,跟离线的计划其实会有很多一样的中央。

第一点是对于一些共性指标的加工,比如说 pv、uv、交易额这些运算,咱们会在汇总层进行对立的运算。另外,在各个脚本中屡次运算,不仅节约算力,同时也有可能会算错,须要确保对于指标的口径是对立在一个固定的模型外面的。自身 Flink SQL 曾经其实反对了十分多的计算方法,包含这些 count distinct 等都反对。

值得注意的一点是,它在应用 count distinct 的时候,他会默认把所有的要去重的数据存在一个 state 外面,所以当去重的基数比拟大的时候,可能会吃掉十分多的内存,导致程序解体。这个时候其实是能够思考应用一些非准确零碎的算法,比如说 BloomFilter 非准确去重、HyperLogLog 超低内存去重计划,这些计划能够极大的缩小内存的应用。

第二点就是 Flink 比拟有特色的一个点,就是 Flink 内置十分多的这种工夫窗口。Flink SQL 外面有翻滚窗口、滑动窗口以及会话窗口,这些窗口在写离线 SQL 的时候是很难写进去的,所以能够开发出一些更加专一的模型,甚至能够应用一些在离线开发当中比拟少应用的一些比拟小的工夫窗口。

比如说,计算最近 10 分钟的数据,这样的窗口能够帮忙咱们建设一些基于工夫趋势图的利用。然而这外面要留神一点,就是一旦应用了这个工夫窗口,要配置对应的 TTL 参数,这样能够缩小内存的应用,进步程序的运行效率。另外,如果 TTL 不够满足窗口的话,也有可能会导致数据计算的谬误。

第三点,在汇总层进行多维的主题汇总,因为实时仓库自身是面向主题的,可能每一个主题会关怀的维度都不一样,所以咱们会在不同的主题下,依照这个主题关怀的维度对数据进行一些汇总,最初来算之前说过的那些汇总指标。然而这里有一个问题,如果不应用工夫窗口的话,间接应用 group by,它会导致生产进去的数据是一个 retract 流,默认的 kafka 的 sink 它是只反对 append 模式,所以在这里要进行一个转化。

如果想把这个数据写入 kafka 的话,须要做一次转化,个别的转化计划实际上是把撤回流里的 false 的过程去掉,把 true 的过程保存起来,转化成一个 append stream,而后就能够写入到 kafka 里了。

第四点,在汇总层会做一个比拟重要的工作,就是衍生维度的加工。如果衍生维度加工的时候能够利用 HBase 存储,HBase 的版本机制能够帮忙你更加轻松地来构建一个这种衍生维度的拉链表,能够帮忙你精确的 get 到一个实时数据过后的精确的维度。

仓库质量保证

通过下面的环节,如果你曾经建设好了一个仓库,你会发现想保障仓库的失常的运行或者是保障它高质量的运行,其实是一个十分麻烦的过程,它要比一线的操作简单得多,所以咱们在建设完仓库之后,须要建设很多的周边零碎来进步咱们的生产效率。

上面介绍一下咱们目前应用的一些工具链零碎,工具链零碎的性能结构图如下图。

首先,工具链零碎包含一个实时计算平台,次要的性能是对立提交作业和一些资源分配以及监控告警,然而实际上无论是否开发数仓,大略都须要这样的一个工具,这是开发 Flink 的根本工具。

对于咱们来讲,跟数仓相干的次要工具有两块:

  • 系统管理模块,这个模块实际上是咱们的实时和离线是一起应用的。其中知识库治理模块,次要是用来记录模型中表和字段的一些信息,另外就是一些工单的解决办法也会保护进去。Flink 治理次要是用来治理一些咱们公司本人开发的一些 Flink 相干的零碎组件。
  • 重点其实还是咱们整个用来开发实时数仓 ETL 的一个开发工具。次要是如下几点:
  • SQL 及 UDF 治理,治理 SQL 脚本和 UDF,以及对 UDF 进行配置。
  • 工作日志查看和工作监控。
  • 调度治理,次要是治理工作的重导和重传。
  • 数据资产治理,治理实时和离线的元数据,以及工作依赖信息。

其实整个这条工具链,每个工具都有它本人特定的用场场景,上面重点解说其中两个。

元数据与血统治理

■ 元数据管理

咱们在 Flink SQL 的开发过程中,每一个工作都要从新把元数据从新写一遍。因为 kafka 以及很多的缓存组件,如 Tair、Redis 都不反对元数据的治理,所以咱们肯定要尽早建设元数据管理系统。

■ 血统治理

血统其实对于实时数仓来讲比拟重要,在上文中也提到过,在实时的作业的运维过程当中,一旦对本人的作业进行了批改,必须保障上游都是可能精确的解析新数据的这样一个状况。如果是依赖于这种人脑去记忆,比如说谁用我的销售表或者口头告诉这种形式来讲的话,效率会十分的低,所以肯定要建设一套就是血统的管理机制。要晓得到底是谁用了生产的表,而后上游用了谁的,不便大家再进行批改的时候进行周知,保障咱们整个实时数仓的稳固。

元数据和血统管理系统,最简略的实现形式大略分为以下三点:

  • 通过元数据服务生成 Catalog

首先通过元数据系统,把元数据系统里的元数据信息加载到程序中来,而后生成 Flink Catalog。这样就能够晓得以后作业能够生产哪些表,应用哪些表。

  • 解析 DDL 语句创立更新表

当作业进行一系列操作,最终要输入某张表的时候,解析作业外面对于输入局部的 DDL 代码,创立出新的元数据信息写入到元数据系统。

  • 作业信息和运行状态写入元数据

作业自身的元数据信息以及它的运行状态也会同步到元数据系统外面来,让这些信息来帮忙咱们建设血缘关系。

最终的零碎能够通过数据库来存储这些信息,如果你设计的零碎没那么简单,也能够应用文件来进行存储。重点是须要尽快建设一套这样的零碎,不然在后续的开发和运维过程当中都会十分的苦楚。

数据品质验证

将实时数据写入 Hive,应用离线数据继续验证实时数据的准确性。

当建设完一个数仓之后,尤其是第一次建设之后,肯定会十分狐疑本人数据到底准不准。在此之前的验证形式就是通过写程序去仓库里去查,而后来看数据对不对。在后续的建设过程中咱们发现每天这样人为去比照太累了。

咱们就采取了一个计划,把中间层的表写到 Hive 外面去,而后利用离线数据丰盛的品质验证工具去比照离线和实时同一模型的数据差别,最初依据设定的阈值进行监控报警。这个计划尽管并不能及时的发现实时数据的问题,然而能够帮忙你在上线前理解实时模型的精确水平。而后进行工作的革新,一直进步数据的准确率。另外这个计划还能够测验离线数据的准确性。

以上是美团点评基于 Flink 构建的实时数仓利用教训的分享,心愿对大家有所帮忙!

退出移动版