大家好,我叫王磊。是SelectDB 大数据研发。今天给大家带来的分享是《Apache Flink X Apache Doris构建极速易用的实时数仓架构》。
下面是我们的个人介绍:我是Apache Doris Contributor 和阿里云 MVP。同时著有《 图解 Spark 大数据快速分析实战》等书籍。

接下来咱们进入本次演讲的正题。本次演讲分:实时数仓需求和挑战、基于 Apache Doris 和 Apache Flink 构建实时数仓、用户案例与最佳实践分享、未来展望与计划四部分。

首先我们来看下第一部分:实时数仓需求和挑战。
首先我们站在数据流的角度分析下传统的数据架构。
从图中我们可以看到数据分为实时的数据流和离线数据流。

接下来这张图是站在技术架构的角度对传统的数据仓库架构进行分析。从图中我们可以看到不同的应用我们采用了不同的技术栈。
在湖仓部分我们基于Iceberg、Hudi、Hive等组件。
基于湖仓之上的Ad hoc查询可能会采用impala或者Kudu。
OLAP的高并发报表使用Druid或者Kylin。
同时业务还有一些半结构化的需求,这时我们可能会使用ES进行日志的检索和分析,使用HBase构建高效的点查服务。
在有的业务中为了对外提供统一的数据服务,还有在各个数据服务之上构建一个查询网关服务或者联邦查询服务,业界比较常见的是Presto和Trino。
那么这样的架构有什么问题呢?

首先是组件多、架构复杂,不易运维。
同时由于维护了实时和离线两套数据架构,因此在计算成本,存储成本和研发成本上都是比较高的。
最后也是最核心的一点是他无法保证实时流和离线流数据的一致性,只能通过离线数据定时清洗实时数据的的方式实现最终的数据一致。
基于以上的痛点,一个易用、统一和实时的架构的需求呼之欲出。这里的统一一般指数据结构的统一(结构化和半结构化数据统一),数据存储的统一,数据计算的统一。
接下来我们看下如何通过基于 Apache Doris 和 Apache Flink 构建实时数仓来满足用户实时、易用和统一的架构需求。

Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库,以极速易用的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。基于此,Apache Doris 能够较好的满足报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等使用场景,用户可以在此之上构建用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。
从图中可以看到,数据源经过各种数据集成和加工处理后,通常会入库到实时数仓 Doris 和离线湖仓(Hive, Iceberg, Hudi 中),然后基于Apache Doris 去构建一个统一的数仓。

接下来咱们来看下如何基于Doris构建极速易用的实时数仓架构。
因为Doris可以承载数据仓库服务、AD-hoc、OLAP等多种场景的应用。因此整个实时数仓架构就变的简单起来。我们只需要通过Flink CDC将RDS数实时同步到Doris、通过Routine Load将Kafka等消息队列的数据实时同步到Doris。然后在Doris内部基于Doris的不同表模型(明细模型、主键模型、统计模型)和Rollup以及物化视图的能力来构建实时数仓。

接下来咱们看在构建实时数仓中有哪些挑战?首先大家最关心的问题就是数据一致性如何保障。
数据一致性分为:最多一次、至少一次和精确一次。
最多一次:发送方仅仅发送消息而不期待得到任何确认,在这种模型中数据的生产和消费过程中都可能出现数据的丢失。
至少一次:发送方重试直到收到确认为止,在这种模型中数据的生产和消费过程中都可能出现数据的重复。
精确一次:消息只严格传递一次到接收方并能成功被接收方处理。这种数据模型能够严格保障数据的生产的准确一次性。
Doris基于两阶段提交(2PC)实现了数据的准确一致性。接下来我们看下Flink CDC ->Doris数据准确一致性。

Flink CDC ->Doris数据准确一致性是通过Flink CheckPoint 和 Doris的2PC来实现的。具体过程分为4步:

介绍完了数据的一致性原理,接下来咱们看下如何基于Flink CDC实现全量和增量数据的同步。这个原理很简单,因为Flink CDC实现了基于Snapshot的全量数据同步和基于BINlog的增量数据同步,同时全量数据同步和增量数据同步可以自动切换。
因此在数据迁移的过程中用户只需要配置要同步的表即可,Flink 任务启动的时候会首先进行表历史数据的全量同步,当全量数据同步完成后会自动切换为增量数据同步。

当我们完成实时数据同步后,用户又产生了RDS Schema变更同步的需求。因为随着业务的发展RDS的表结构会发生变化,用户希望CDC不但能将数据的变化实时同步到Doris,也希望能将RDS上的表结构变更也同步到Doris。这样的话用户就不用担心RDS表结构和Doris表结构不一致问题了。
要能满足DDL同步的前提是Doris能够支持快速的Schema Change,这样即使瞬间有很多Schema Change需求能够快速响应。之前Doris的Schema Change支持Hard Link Schema Change、Hard Sort Schema Change和Hard Sort Schema Change三中模式。这三种Schema Change的耗时都比较高。因此在最新的版本中我们引入了Light Schema Change,
相较于 Hard Linked Schema Change 的作业流程, Light Schema Change 的实现原理就要简单的多,只需要在加减 Value 列的时候,对 FE 中表的元数据进行修改并持久化。这样Schema Change的过程只需要更新FE 中的源数据,因此其效率很高,并且该响应是一个同步的过程。
由于 Light Schema Change 只修改了 FE 的元数据,没有同步给 BE,而 BE 对读写操作依赖于自身的 Schema,这时候就会出现 Schema 不一致的问题。为了解决此问题,我们对 BE 读写流程进行了修改。主要包含以下方面:

有了Light Schema Change的保障,我们的Flink CDC就同时支持DML的同步和DDL的同步,DML同步包括Insert、Update和Delete等语句,DDL语句包括ALTER TABLE ADD COLUMN 和ALTER TABLE DROP COLUMN。
有了DDL同步后,在Flink CDC中如何使用呢?

当我们解决了基于Flink和Doris数据同步过程中的数据一致性、全增量数据同步和DDL变更同步后。一个完整的数据同步方案就完成了。接下来我们站在数据模型的角度,看出如何基于Flink在Doris中构建不同的数据模型。


介绍完数据模型后,我们来看下如何基于Doris实现高并发的写入和更新。
对于大数据架构来说。高并发的写入并不难,难点在于高并发的更新。如何在上亿数据中快速找到要更新的数据并对数据进行更新一直是大数据领域比较难处理的问题。在这个问题上Doris通过MVCC多版本并发控制的机制来实现。
特别的在unique模型中,当我们写入一个数据时,如果数据在库中不存在则会写入一个版本数据,当我们再次对该数据进行更新时会直接再写入一个版本,此时数据的变更(新增、修改、删除)在Doris中以多版本的形式存在。用户查询的时Doris会将最新的版本对应的数据返回给用户,并在Compaction时对历史变更数据进行清理。这种设计很好的解决了海量数据更新难问题。
同时Doris支持Merge On Write和Merge On Read两种模式。接下来我们分别进行介绍。

首先我们来看Merge On Read。他的特点是
写入快:由于其无论是insert还是update,对于Doris来说都会以Append多版本的方式写入,因此其写入性能很高。
查询慢:因为查询过程中,需要对Key进行聚合、去重,然后查询,因此其查询性能慢。
接下来我们通过一个例子看下:

Merge On Write兼顾查询性能和写入性能。Merge On Write写入过程中引入了Delete Bitmap,用来标记Rowset中某一行是否被删除,使用了兼顾性能和存储空间的Roaring Bitmap,将Bitmap和tablet meta一起存储在RocksDB中,每个segment对应一个bitmap。为了保持Unique Key原有的version语义,Delete Bitmap也支持多版本。每次导入产生该版本的增量bitmap,查询时需要合并所有此前版本的delete bitmap。
接下来咱们看下基于Delete Bitmap的Merge On Write写入流程:


Doris针对不同的应用场景提供了不同的数据模型,分别为:明细模型,主键模型和聚合模型。
明细模型:明细数据存储(日志分析、行为分析)
主键模型:相同key的数据覆盖更新(订单状态、用户状态)
聚合模型:相同key列value列合并(报表统计、指标计算)

接下来我们看下如何通过物化视图来加速查询。
物化视图的概念是: 根据预定义的SQL分析语句执行预计算并将计算结果物化(持久化)起来用以加速查询的一种手段。
他主要的应用场景是:数据预聚合、聚合数据和明细数据同时查询、匹配不同前缀索引三大场景。
我们这里创建一个名叫 advertiser_view_record的Base表和名为advertiser_uv的物化视图。
数据的更新过程首先会更新Base表,然后更新物化视图。

Doris通过物化视图来加速查询。并且在查询的过程中Doris会自动进行路由选择,当我们的查询在物化视图中能查询到数据时会直接走物化视图的数据。当数据在物化视图中不存在时会查询Base表,同时借助Doris的列式存储和向量化计算快速完成查询。
物化视图的智能路由选择遵循最小匹配原则,也就是说只有查询的数据的集合比物化事务小的时候才有可能走物化视图。其智能路由过程包括:最优选择和查询改写两个过程。
Doris 支持两级分区存储, 第一层为分区(partition), 第二层为 HASH 分桶(bucket)。例如我们可以按照时间首先对数据进行分区,在分区内部使用site进行分桶。当我们查询某个site上的数据的时候借助分区分桶裁剪能够快速命中数据。
除此之外为了加速查询,我们还可以使用索取来加速查询,Doris内部也提供智能的查询优化。




Apache Doris 构建的离线+实时数仓一体化,采用 SQL 开发,并用 Dolphinscheduler 一键部署调度,极大的降低开发难度和开发工作量,可进行快速迭代以满足目前行业日益增长的数据需求。
新架构采用 Flink+Doris 的架构体系,FlinkCDC+StreamLoad 可以做到流批一体化数据接入,减少了组件的使用,解决了数据的冗余存储,服务器资源节省了 30%,数据存储磁盘占用减少 40%,同时组件的运维成本大大减少。
Doris的易用性极高,支持 MySQL 协议和标准 SQL,各业务线均可通过查询 MySQL 的方式进行数据查询,极大的减少了学习成本。
从 2021 年 Apache Doris上线云积互动的第一个业务至今,Apache Doris 在云积互动内部已成为大数据服务的基础,承担了包括人群分析、报表查询、指标计算等场景下的在线/离线需求,在较小的集群规模下支持了每天近2万次的用户在线分析查询。

当前我们的集群配置为 5 台阿里云 ESC,16 核 64G。在相同集群配置下,1000 个表的每日增量数据合并任务,用 Hive 需要 3-5 小时,用 Spark需要 2-3 小时,然而同样的需求 Drois 运用 Unique Key 模型完成只需要 10 分钟,大大提前了后续计算任务的开始时间。
另外,因 Hive 跑得慢,我们后续的几百个 Hive 计算任务,排队情况很严重,不得不把一些优先级低的任务排到下午甚至晚上,日任务全部跑完需要十几个小时。而我们把全部批任务迁移到 Doris 上计算后,全部任务跑完只需要 2 小时不到,后续增加新的需求任务完全无压力。
总而言之,使用 Doris 后,报表数据的更新时间大大提前,临时的数据查询需求响应时长大大缩短,至少节约了每年几万的大数据集群扩容成本,同时获得了各部门的认可。
提升开发效率
随着公司业务快速的发展,会不断的有新的数据分析需求,就需要我们接入新库新表,给老表加字段等,这对于 Hive 数仓是非常痛苦的,表要重建、全量数据要抽,这就需要每周有半天时间都在处理这些事情。
在使用 Doris 作为数仓后,通过我们的数据易平台配置 Flink CDC 任务快速接入 MySQL 库表的全量+增量数据,同时利用 Doris 的 Online Schema Change 特性,实时同步 Binlog 里的 DDL 表结构变更到 Doris,数据接入数仓零开发成本。
另外因为 Doris 支持 MySQL 协议直接对接数据可视化应用,我们不需要再把结果数据从 Hive 推到 MySQL 里提供数据服务,节约了数据库资源,减少了开发步骤。
体现数据价值
Doris 有审计日志,我们可以通过日志,分析出每个表每天的查询使用情况,以便我们评估跟进数据价值、下线废弃报表及任务。另外还可以预警资源消耗多、查询慢的查询语句,帮助用户进行语法优化等。



在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
我是一名决定学习Ruby和RubyonRails的ASP.NETMVC开发人员。我已经有所了解并在RoR上创建了一个网站。在ASP.NETMVC上开发,我一直使用三层架构:数据层、业务层和UI(或表示)层。尝试在RubyonRails应用程序中使用这种方法,我发现没有关于它的信息(或者也许我只是找不到它?)。也许有人可以建议我如何在RubyonRails上创建或使用三层架构?附言我使用ruby1.9.3和RubyonRails3.2.3。 最佳答案 我建议在制作RoR应用程序时遵循RubyonRails(RoR)风格。Rails
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭8年前。Improvethisquestion我们有以下(以及更多)系统,我们将数据从一个应用推送/拉取到另一个:托管CRM(InsideSales.com)Asterisk电话系统(内部)横幅广告系统(openx,我们托管)潜在客户生成系统(自行开发)电子商务商店(spree,我们托管)工作板(本土)一些工作网站抓取+入站工作提要电子邮件传送系统(如Mailchimp,自主开发)事件管理系统(如eventbrite,自主开发)仪表板系统(大量图表和
我需要在rail3中使用标准注册/登录/忘记密码功能进行身份验证。是否有大多数人为此使用的插件或其他东西? 最佳答案 我不确定最常用的方法是什么-但可以肯定的是,Plataformatec的“Devise”是一个非常流行的方法:http://github.com/plataformatec/devise我已经尝试了一些authgem,对我来说,它是最简单的设置和修改以满足我的需要。它内置了密码恢复、帐户确认(如果需要)和其他一些非常方便的功能。 关于ruby-on-rails-在Rail
我在ruby表单中有一个提交按钮f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id"我想在不使用任何javascript的情况下通过ruby禁用此按钮 最佳答案 添加disabled:true选项。f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id",disabled:true 关于ruby-on-rails-如何在Rails中添加禁用的提交按钮,我们在St
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?
在我的mac上安装几个东西时遇到这个问题,我认为这个问题来自将我的豹子升级到雪豹。我认为这个问题也与macports有关。/usr/local/lib/libz.1.dylib,filewasbuiltfori386whichisnotthearchitecturebeinglinked(x86_64)有什么想法吗?更新更具体地说,这发生在安装nokogirigem时日志看起来像:xslt_stylesheet.c:127:warning:passingargument1of‘Nokogiri_wrap_xml_document’withdifferentwidthduetoproto
Ruby语言是否可以用于创建全新的移动操作系统或桌面操作系统,即是否可以用于系统编程? 最佳答案 嗯,现在有一些操作系统使用比C更高级的语言。基本上,ruby解释器本身需要用一些低级的东西来编写,并且需要一些引导加载代码将功能齐全的ruby解释器作为独立内核加载到内存中。一旦ruby解释器被引导并以内核模式(或innerrings之一)运行,就没有什么可以阻止您在其上构建整个操作系统。不幸的是,它可能会很慢。每个操作系统功能的垃圾收集可能会相当引人注目。ruby解释器将负责任务调度和网络堆栈等基本事情,使用垃圾收集框架会大大
这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi