- 导读 -

最近几年大数据技术在各行各业得到广泛应用,为企业的运营决策和各种业务提供支持。随着数据的增长,业务对数据时效性的要求,给企业的大数据分析带来了巨大挑战。针对海量数据的实时分析需求,近年来市场上涌现出众多OLAP分析引擎。这些OLAP引擎有各自的适用场景和优缺点,如何选择一款合适的引擎来更快地分析数据、更高效地挖掘数据的潜在价值?

爱奇艺大数据服务团队评估了市面上主流的OLAP引擎,最终选择Apache Druid时序数据库来满足业务的实时分析需求。本文将介绍Druid在爱奇艺的实践情况、优化经验以及平台化建设的一些思考。

爱奇艺大数据OLAP服务

爱奇艺大数据OLAP服务在2015年前主要以离线分析为主,主要基于Hive+MySQL、HBase等。2016年起引入Kylin和Impala分别支持固定报表和Ad-hoc查询。2018年以来引入Kudu和Druid支持实时分析需求。

在引入Druid之前,业务的一些场景无法通过离线分析满足,如广告主想要实时基于投放效果调整投放策略、算法工程师调整模型推到线上A/B要隔天离线报表才能看到效果。这些场景都可以归纳为对海量事件流进行实时分析,经典的解决方案有如下几种:

  • 离线分析

使用Hive、Impala或者Kylin,它们一个共同的缺点是时效性差,即只能分析一天或者一小时前的数据,Kylin还面临维度爆炸的问题

  • 实时分析

  • 用ElasticSearch或OpenTSDB,由于数据结构本质是行存储,聚合分析速度都比较慢;可以通过查询缓存、OpenTSDB预计算进行优化,但不根本解决问题;

  • 用流任务(Spark/Flink)实时地计算最终结果,存储在MySQL提供进一步服务;问题是每当需求调整,如维度变更时,则需要写新的流任务代码;

  • 使用Kudu和Impala结合能够做到实时分析。在实践过程中发现,Kudu受限于内存和单机分区数,支撑海量数据成本很大;

  • Lambda架构:

无论选用哪种实时或离线方案的组合,都会采用Lambda架构,用离线数据校准实时数据。这意味着从摄入、处理、查询都需要维护两套架构,新增一个维度,离线和实时均需对应修改,维护困难

以上种种方案的不足,促使我们寻找新的解决方案,最终决定采用Druid。

Apache Druid介绍 

Apache Druid是针对海量事件流进行存储和实时多维分析的开源系统。它具有如下特性:

  • 实时可见:消息摄入后分钟级查询可见

  • 交互查询:查询延时在秒级,核心思想为内存计算和并行计算

  • 维度灵活:支持几十个维度任意组合,仅在索引时指定的维度查询可见

  • 易于变更:需求变更后调整索引配置立马生效;

  • 流批一体:新版本KIS模式可实现Exactly Once语义

上图为Druid架构图,大体分为几个模块:

  • MiddleManager:索引节点,负责实时处理消息,将其转成列式存储,并通过Rollup精简数据量;索引节点定期将内存中数据持久化为不可修改的文件(Segment),保存至HDFS保证数据不会丢失;

  • Historical:历史节点,将Segment加载到本地,负责大部分查询的计算;

  • Broker:查询节点,将查询分解为实时和离线部分,转发给索引节点和历史节点,并汇总最终的查询结果;

  • Overlord:负责索引任务管理;

  • Coordinator:负责负载均衡,确保Segment在历史节点之间尽量均衡;

Druid在爱奇艺的实践

Druid很好地填补了爱奇艺在实时OLAP分析领域的空白,随着业务实时分析需求的增加,Druid集群和业务规模也在稳步增长。目前集群规模在数百个结点,每天处理数千亿条消息,Rollup效果在10倍以上。平均每分钟6千条查询,P99延时一秒内,P90延时在200毫秒内。在建设Druid服务过程中,我们也不断遇到规模增长带来的性能瓶颈和稳定性问题。

1.Coordinator瓶颈

当时的挑战是实时索引任务经常被阻塞。Druid的Handoff总结如下,索引节点将Segment持久化到HDFS,然后Coordinator制定调度策略,将计划发布到ZooKeeper。历史节点从ZooKeeper获取计划后异步地加载Segment。当历史节点加载完Segment索引节点的Handoff过程才结束。这个过程中,由于Coordinator制定计划是单线程串行的,如果一次触发了大量Segment加载,执行计划制定就会很慢,从而会阻塞Handoff过程,进而索引节点所有的Slot均会被用满。

而以下过程均会触发大量Segment加载,在解决Coordinator调度性能瓶颈前, 很容易引发故障:

• 历史节点因硬件故障、GC、主动运维退出

• 调整Segment副本数、保留规则

通过火焰图对Coordinator进行Profiling最终定位了问题,如下图所示,将最耗时部分放大出来,是负载均衡策略对每个Segment要选择一个最佳的服务器。阅读源码可知其过程为,加载Segment X,需要计算它和服务器的每个Segment Y的代价Cost(X, Y),其和为服务器和Segment X的代价。假设集群有N个Segment,M个Historical节点,则一个节点宕机,有N/M个Segment需要加载,每个Segment都和剩余的N个节点计算一次代价,调度耗时和N成平方关系。

一个节点宕机调度耗时 = (N/M)个Segment * 每个Segment调度耗时 = (N/M) * N = O(N^2)

分析清楚原因后,很容易了解到Druid新很容易了解到Druid新版本提供了新的负载均衡策略(druid.coordinator.balancer.strategy = CachingCostBalancerStrategy),应用后调度性能提升了10000倍,原先一个历史节点宕机会阻塞Coordinator1小时到2小时,现在30秒内即可完成。

2.Overlord瓶颈

Overlord性能慢,我们发现升级到0.14后Overlord API性能较差,导致的后果是索引任务概率性因调用API超时而失败。通过Jstack分析,看到大部分的HTTP线程均为阻塞态,结合代码分析,定位到API慢的原因,如左图所示,Tranquility会定期调用Overlord API,获取所有RunningTasks,Overlord内部维护了和MySQL的连接池,该连接池默认值为8,该默认值值过小,阻塞了API处理。解决方法是增大dbcp连接池大小。druid.metadata.storage.connector.dbcp.maxTotal = 64

调整后,Overlord性能得到了大幅提升,Overlord页面打开从几十秒降低到了几秒。但意料之外的事情发生了,API处理能力增加带来了CPU的飙升,如右图所示,并且随着Tranquility任务增加CPU逐渐打满,Overlord页面性能又逐步降低。通过火焰图Profile可知,CPU主要花费在getRunningTasks的处理过程,进一步分析Tranquility源码后得知,Tranquility有一个配置项(druidBeam.overlordPollPeriod)可以控制Tranquility轮询该API的间隔,增大该间隔后问题得到了暂时缓解,但根本的解决方案还是将任务切换为KIS模式。

3.索引成本

Druid索引成本过高。基于Druid官方文档,一个Druid索引任务需要3个核,一个核用于索引消息,一个核用于处理查询,一个核用于Handoff过程。我们采用该建议配置索引任务,压测结果是3核配置下能够支撑百万/分钟的摄入。

在最初,集群所有的索引任务都是统一配置,但实际使用过程中,大部分的索引任务根本达不到百万/分钟的消息量,造成了资源大量浪费。如下图所示,我们按照索引任务的内存使用量从高到低排序,9 GB为默认配置,80%的任务利用率低于1/3,即3 GB。我们以3 GB绘制一条横线,以内存使用最接近的任务绘制一条竖线,定义A为实际使用的内存,B为第二象限空白部分,C为第四象限空白部分,D为第一象限空白部分,则浪费的资源 = (B+C+D)的面积。

我们思考能否采取索引任务分级的策略,定义一种新的类型索引节点 – Tiny节点。Tiny节点配置改为1 core\3GB,能够满足80%小任务的资源需求,而default节点继续使用 3 core9 GB的配置,满足20%大任务的需求,在这种新的配置下,浪费的资源 = (B + C)的面积,D这一大块被省下来。简单地计算可知,在不增加机器的情况下,总Slots能够增加1倍。

默认slot资源需求为1,Tiny为1/3,调整后单位任务需要的资源 = 0.2 * 1 + 0.8 * 1/3 = 0.5

在实际操作层面,还需解决一个问题,即如何把Datasource指定给合适的Worker节点。在Druid低版本中,需要通过配置文件将每一个Datasource和Worker节点进行关联,假设有N个Datasource,M个Worker节点,这种配置的复杂度为 N * M,且无法较好地处理Worker节点负载均衡,Worker宕机等场景。在Druid 0.17中,引入了节点Category概念,只需将Datasource关联特定的Category,再将Category和Worker绑定,新的配置方法有2个Category,复杂度 =  2 * N + 2 * M。

4.Tranquility vs KIS

刚使用Druid时,当时主力模式是Tranquility。Tranquility本质上仍然是经典的Lambda架构,实时数据通过Tranquility摄入,离线数据通过HDFS索引覆盖。通过离线覆盖的方式解决消息延迟的问题,缺点是维护两套框架。对于节点失败的问题,Tranquility的解决方案是链路冗余,即同时在两个索引节点各起一份索引任务,任一节点失败仍有一份能够成功,缺点是浪费了一倍的索引资源。自0.14版本起,Druid官方建议使用KIS模式索引数据,它提供了Exactly Once语义,能够很好地实现流批一体。

和Tranquility的Push模式不同,KIS采取Pull模式,索引任务从Kafka拉取消息,构建Segment。关键点在于最后持久化Segment的时候,KIS任务有一个数据结构记录了上一次持久化的Offset位置,如图例左下角所示,记录了每个Kafka Partition消费的Offset。在持久化时会先检查Segment的开始Offset和元信息是否一致。如果不一致,则会放弃本次持久化,如果一致,则触发提交逻辑。提交中,会同时记录Segment元信息和Kafka Offset,该提交过程为原子化操作,要么都成功,要么都失败。

KIS如何处理各个节点失败的情况呢?假设Kafka集群失败,由于是Pull模式,Druid在Kafka恢复后继续从上一个Offset开始消费;假设Druid索引节点失败,Overlord后台的Supervisor会监控到相应任务状态,在新的索引节点启动KIS任务,由于内存中的状态丢失,新的KIS任务会读取元信息,从上一次的Offset开始消费。假设是MySQL或者更新元数据过程失败,则取决于提交的原子操作是否成功,若成功则KIS从新的Offset开始消费,失败则从上一次Offset开始消费。

进一步看一下KIS是如何保证Exactly Once语义。其核心是保证Kafka消费的Offset连续,且每个消息都有唯一ID。Exactly Once可以分为两个部分,一是At Least Once,由KIS检查Offset的机制保证,一旦发现缺失了部分Offset,KIS会重新消费历史数据,该过程相当于传统的离线补数据,只是现在由Druid自动完成了。另一个是At Most Once,只要保证Offset没有重叠部分,则每条消息只被处理了一次。

以下是KIS在爱奇艺的一个实例,左下图为业务消息量和昨天的对比图,其中一个小时任务持久化到HDFS失败了,看到监控曲线有一个缺口。之后Druid后台启动了一个新的KIS任务,一段时间后,随着KIS补录数据完成,曲线图恢复到右下图所示。那么,如果业务不是一直盯着曲线看,而是定期查看的话,完全感受不到当中发生了异常。

基于Druid的实时分析平台建设

Druid性能很好,但在初期推广中却遇到很大的阻力,主要原因是Druid的易用性差,体现在如下几个方面:

  1. 数据摄入需要撰写一个索引配置,除了对数据自身的描述(时间戳、维度和度量),还需要配置Kafka信息、Druid集群信息、任务优化信息等

  2. 查询的时候需要撰写一个JSON格式的查询,语法为Druid自定义,学习成本高

  3. 返回结果为一个JSON格式的数据,用户需自行将其处理成最终图表、告警

  4. 报错信息不友好,上述所有配置均通过JSON撰写,一个简单的逗号、格式错误都会引起报错,需花费大量时间排查

为解决Druid易用性差的问题,爱奇艺自研了实时分析平台RAP(Realtime  Analysis Platform),屏蔽了Kafka、Druid、查询的细节,业务只需描述数据格式即可摄入数据,只需描述报表样式、告警规则,即可配置实时报表和实时告警。

RAP实时分析平台,主要有六大特性:

  • 全向导配置:业务无需手写ETL任务

  • 计算存储透明:业务无需关心底层OLAP选型

  • 丰富报表类型:支持常见的线图、柱状图、饼图等

  • 数据延时低:从APP数据采集到生成可视化报表的端到端延时在5分钟内,支持数据分析师、运营等业务实时统计分析UV、VV、在线用户数等

  • 秒级查询:大部分查询都是秒以内

  • 灵活变更:更改维度后重新上线即可生效

RAP实时分析平台目前已经在爱奇艺会员、推荐、BI等多个业务落地,配置了上千张报表,帮助业务在实时监控报警、实时运营分析、实时AB测试对比等场景提升排障响应速度、运营决策效率。

关于RAP的更多技术细节和业务应用场景,可以阅读之前分享的技术文章:爱奇艺大数据实时分析平台的建设与实践

未来展望

进一步迭代完善Druid及RAP,提升稳定性、服务能力,简化业务接入成本:

• 接入爱奇艺自研的Pilot智能SQL引擎,支持异常查询拦截、限流等功能

• 运维平台:包括元信息管理、任务管理、服务健康监测等,提升运维效率

• 离线索引:支持直接索引Parquet文件,通过Rollup进一步提升查询效率

• 支持JOIN:支持更丰富的语义

参考资料

[1] https://druid.apache.org/

[2] 直播回放:Druid在爱奇艺的实践和技术演进

[3] 爱奇艺大数据实时分析平台的建设与实践

[4] 爱奇艺在日志实时数据监控的探索与实践

猜你喜欢

1、恭喜,Apache Hudi 即将成为顶级项目!

2、NVIDIA 与数砖合作,将 GPU 加速带入 Apache Spark 3.0

3、你必须掌握的 21 个 Java 核心技术!

4、Apache Kafka 不需要管理员:删除 Apache ZooKeeper 的依赖

过往记忆大数据微信群,请添加微信:fangzhen0219,备注【进群】

基于 Apache Druid 的实时分析平台在爱奇艺的实践相关推荐

  1. 如何支持亿级用户分流实验?AB实验平台在爱奇艺的实践

    01 背景 随着互联网公司的产品和业务越来越多样,利用数据来驱动业务决策成为必然,而AB实验正是以数据指标来判断产品功能和运营策略迭代效果的方法和工具,其可以在保证样本同时性和同质性基础上,对比两个或 ...

  2. i 技术会笔记 | Druid在爱奇艺的实践和技术演进

    - 导读 - 最近几年大数据技术在各行各业得到广泛应用,为企业的运营决策和各种业务提供支持.随着数据的增长,业务对数据时效性的要求,给企业的大数据分析带来了巨大挑战.针对海量数据的实时分析需求,近年来 ...

  3. 益聚星荣:B站成“今年最亏视频平台”?爱奇艺都甘拜下风

    划重点: 1.在疫情中"起飞"的B站,今年疯狂投资了43家公司,最终勇夺"今年最亏视频流媒体平台"的"殊荣",就连时运不济的爱奇艺,在亏钱额 ...

  4. Mesos 在爱奇艺的实践

    [编者的话]Mesos 在爱奇艺目前管理着大约 2000 台物理机,分布在多个数据中心,单个集群最大节点数接近 600. 本文讲的是Mesos 在爱奇艺的实践Mesos 平台每周启动的容器超过 500 ...

  5. 爱奇艺容器实践(内附云原生落地沙龙干货下载)

    4月10日下午,爱奇艺技术产品团队举办了"i技术会"线下技术沙龙,本次技术会的主题是"云原生落地探索与实践",邀请快手.百度和字节跳动的技术专家,与爱奇艺技术产 ...

  6. 互联网晚报 | 微软将把所有暴雪游戏引入英伟达平台;爱奇艺首次实现全年运营盈利;​客服回应沪上阿姨外包装旗袍图被质疑不雅...

    微软将把所有暴雪游戏引入英伟达平台 北京时间2月22日,微软总裁史密斯在新闻发布会上表示,继任天堂后,微软宣布与英伟达签订了一项为期10年的协议,在微软收购动视暴雪成功后,Xbox PC游戏和动视暴雪 ...

  7. 干货|爱奇艺数据库实践:不同场景如何快速选择数据库

    郭磊涛 爱奇艺数据库和中间件负责人 本文主要分享数据库选型方面的一些思路,在数据库选型的时候要考虑哪些问题?比如,有哪些需求?待选用的数据库是否和需求对应的上?是不是直接就可以拿来用?需不需要一些额外 ...

  8. 爱奇艺本地实时Cache方案

    高并发系统离不开Cache,通过采用更多的本地Cache来提升系统吞吐量和稳定性是必然的,这其中的最大难点就是解决分布式本地Cache数据的实时性和一致性问题,否则本地Cache就无法更普遍应用于频繁 ...

  9. 从 Spark Streaming 到 Apache Flink : 实时数据流在爱奇艺的演进

    作者:陈越晨 整理:刘河 本文将为大家介绍Apache Flink在爱奇艺的生产与实践过程.你可以借此了解到爱奇艺引入Apache Flink的背景与挑战,以及平台构建化流程.主要内容如下: 爱奇艺在 ...

最新文章

  1. The HipHop Virtual Machine
  2. 深入理解Ribbon之源码解析
  3. String字符串编码解码格式
  4. 几个SQL命令的使用
  5. BNUOJ 4215 最长公共连续子序列
  6. 数据光端机设备性能指标介绍
  7. TCL 中upvar 用法 (摘自http://www.cnblogs.com/kane1990/archive/2011/12/19/2293981.html)
  8. CodeSmith NetTier模板生成的代码框架用法 (转)
  9. mysql 密码重置 linux_怎么在linux系统重置mysql的root密码
  10. 进程部分(IPC机制及生产者消费者模型)和线程部分
  11. VirtualBox中安装Ubuntu、LAMP、SVN、JRE和Tomcat
  12. 分布式存储系统学习笔记(三)—分布式键值系统(1)—Amazon Dynamo
  13. php做APP接口开发,接口的安全性
  14. linux快捷键列表,全面总结Linux快捷键的使用
  15. java文件上传下载接口_java 文件上传下载
  16. android 手机壁纸制作教程,教程:让你的手机桌面瞬间高逼格!
  17. java如何用雪花算法批量生成唯一编码(保证位数不过长)?
  18. Error 1924.Could not update environment variable FNL_LICENSE_NUMBER.  Verify that you have sufficien
  19. 【AI绘画打卡】| 用漫画生成器绘制宅男最爱的二次元美女
  20. CLIP学习笔记:Learning Transferable Visual Models From Natural Language Supervision

热门文章

  1. word里画的流程图怎么全选_Word中绘制流程图的正确姿势,这招大多数人不知道!...
  2. Linux之SUSE系统SAP-HANA经常系统内存不足使得SAP应用不能使用解决方案
  3. Flink窗口+触发器 ,实现定时、定量批量写入Hbase不同的表
  4. python将数据导出为csv文件时,出现PermissionError: [Errno 13] Permission denied:问题
  5. 参考文献在Latex编译后的文章中无法显示
  6. C++批量修改文件名字
  7. Android Adb命令(5) - find 查找设备文件
  8. idea无法识别java文件、Maven下载依赖报错:Cannot resolve...或者Could not find artifact...实测有效
  9. Struts2的OGNL表达式语言
  10. SEO 行业怎么了?