​爱奇艺|海量数据实时分析服务技术架构演进

2023-11-02 02:20

本文主要是介绍​爱奇艺|海量数据实时分析服务技术架构演进,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.现状与挑战

爱奇艺目前使用到的大数据相关技术有Druid、Impala、Kudu、Kylin、Presto、ElasticSearch等,并且随着各技术框架的版本升级而升级。 比如:
  • Druid是一个分布式的支持实时分析的数据存储系统,数据与时间强相关,已由0.10.0版本升级到0.14.2版本;

  • Impala是Cloudera受谷歌Dremel启发开发的实时交互SQL大数据查询工具;

  • Kudu是Cloudera开源的存储引擎,可以同时提供低延迟的随机读写和高效的数据分析能力;

  • Kylin是Apache开源的一个分布式引擎, 提供了在Hadoop之上的SQL查询接口及OLAP能力,支持超大规模数据;

  • Presto是一个分布式的SQL查询引擎,其设计专门用于进行高速、实时的数据分析;

  • ElasticSearch是一个高可靠、可扩展、分布式的全文搜索引擎。

不同的业务场景需要不同的大数据技术架构,对于爱奇艺号而言,因单日数据量达到亿级且分固定时间选择和自由时间选择(至少查询近2年数据)查询数据的业务特点,因此采用的是Druid和ElasticSearch的组合技术架构,其中自由时间选择查询Druid,而固定时间选择查询ElasticSearch。同时,为了保证数据的高可用,Druid和ElasticSearch都有主备2份数据。

然而,在使用Druid和ElasticSearch的过程中也遇到了一些 挑战 ,比如:

Druid本身对数据写入和查询只提供了基于JSON的API接口,学习接口的使用方法,了解各种字段含义,学习成本很高;另外,数据的安全性,在早期的Druid版本中支持较弱;再有,高qps长时间跨度的聚合查询也是一个很大的挑战。

对于ElasticSearch,因不适用于大数据量的聚合计算,要尽量避免此种应用场景,且ElasticSearch提供的RESTful API的查询接口学习成本也相对较高。另外,因为Druid集群是服务于公司全部业务的,如何做业务隔离也是一个严峻的挑战。

2.技术架构演进

在最初的爱奇艺号数据服务中,主要采用的是Kylin,架构如下图所示:

640?wx_fmt=png

服务分集群部署,每个集群部署多台机器,固定时间选择和自由时间选择查询的都是Kylin,并对数据进行缓存。 因爱奇艺号作品数据查询的是视频明细数据的特点,随着业务的发展,爱奇艺号用户以及上传视频量快速增长,导致Kylin Cube的构建时长和查询时长明显增加,甚至会出现查询超时的情况。 另外,Kylin构建Cube过程很是不稳定,经常会出现构建失败或超时的情况,需要耗费大量的人力成本去处理上述异常情况。

基于此,我们进行了新的技术选型,对Impala+Kudu、ElasticSearch、Druid等技术架构进行了对比。最后,因Druid具有超大数据规模、毫秒级查询时延、高并发查询、高稳定性等的特点,故爱奇艺号选择Druid平台作为底层架构。而对于固定时间选择,因其时间固定且视频量级为亿级,故采用ElasticSearch存储和查询,重新选型后的架构如下图所示。

640?wx_fmt=png

爱奇艺号的作品数据查询分为两个部分: 固定时间范围查询和自由时间范围查询,我们对固定时间范围查询结果进行预计算且结果存入ElasticSearch,这样免去了大数据集上的实时聚合和排序,查询性能得到了很大提升; 自由时间范围选择查询Druid,因为是分天查询视频数据,所以Druid的Segment粒度是天,但若用户选择的数据查询时间跨度比较大,那么Druid扫描的Segment数量就会增加,加载进内存的数据会增加,聚合数据速度会变慢,针对此种场景,爱奇艺号导入了按月分Segment数据的DataSource,即把每个视频1个自然月的数据汇总到一个Segment,这样减少了扫描的Segment数量,加载进内存的数据减少,数据聚合速度会变快。 经过测试,当用户选择的时间范围跨度大于6个月时,将查询时间范围拆分成自然月与自然日的两个时间范围并行查询,查询时间会明显缩短。

经过上述优化,一个普通的爱奇艺号用户查询数据时长由2s+缩减至150ms+,性能提升十分明显,用户反馈良好,固定时间选择具体性能对比如下图所示:

640?wx_fmt=png

由上图可以看出,优化后昨日/近7天/近90天的数据查询时间明显缩短,且数据查询时长并不随着时间范围的扩大而明显增加,固定时间维度查询优化明显。 自由时间选择的查询性能对比如下图:

640?wx_fmt=png

由上图可以看出,优化后自由时间选择的查询时长明显优于优化前,查询时长是数量级级别的差异。但当用户的视频量比较大时,Druid的查询性能明显下降,于是我们通过扩容集群机器等方式进一步解决用户视频量大而导致查询变慢的问题。

另外,为了预防Druid集群故障,我们采用主备Druid集群的方式存储了2份同样的数据,当主Druid集群出现故障不可用时,采用Hystrix的服务降级,改成查询备份的Druid集群数据,从而保证服务高可用。 因为固定时间维度查询预计算好的ElasticSearch结果,缓解了Druid查询压力,且对查询过的数据进行Redis缓存,进一步降低ElasticSearch和Druid的查询压力,从而保证服务的稳定性,接口成功率提升至99.9%。

3.选择Druid的原因

Druid是一个用于大数据实时查询和分析的高容错、高性能开源分布式系统,旨在快速处理和查询,Druid的架构如下图所示:

640?wx_fmt=png

Druid主要包含以下5类 节点

  • MiddleManager节点:摄入数据以及生成Segment数据文件

  • Historical节点:加载已生成好的数据文件,以供数据查询

  • Coordinator节点:负责历史节点的数据负载均衡,以及通过规则管理数据的生命周期

  • Overload节点:负责数据摄入的负载均衡

  • Broker节点:对外提供数据查询服务,并同时从MiddleManager节点和Historical节点查询数据,合并后返回给调用方 

同时,集群还包括以下三类外部依赖

  • Metadata:存储Druid集群的元数据信息,比如:Segment的相关信息,一般是MySQL。

  • Zookeeper:为Druid集群提供一致性协调服务。

  • Deep Storage:存放生成的Segment数据文件,并共Historical节点下载,一般是HDFS。

Druid为何能支持如何快速的查询呢?下面为你详细介绍。

在介绍Druid快速查询原理之前,首先介绍一下Druid的数据查询过程。

查询节点接收外部Client的查询请求,并根据查询中指定的interval找出相关的Segment,然后找出包含这些Segment的实时节点和历史节点,再将请求分发给相应的实时节点和历史节点,最后将来自实时节点和历史节点的查询结果合并后返回给调用方。其中,查询节点通过Zookeeper来发现历史节点和实时节点的存活状态。

下图展示了在系统架构中查询请求数据如何流动,以及哪些节点涉入其中。

640?wx_fmt=png

查询具体过程 如下:

  1. 查询请求首先进入查询节点,查询节点将与已知存在的Segment进行匹配查询;

  2. 查询节点选择一组可以提供所需要的Segment的历史节点和实时节点,将查询请求分发到这些机器上;

  3. 历史节点和实时节点都会进行查询处理,然后返回结果;

  4. 查询节点将历史节点和实时节点返回的结果合并,返回给查询请求方。

Druid快速查询 主要有以下3个原因:

  • 内存式查询

  • 缓存的使用

  • Segment特殊存储格式:列式存储、Bitmap索引、RoaringBitmap Compression

首先,Druid是一个内存式的数据库,设计初衷就是数据的查询落到内存中,如果内存足够大,可以保证所有的数据都加载到内存中;其次,如果Broker节点上已经缓存本次查询的结果(即之前查询过与本次查询完全相同的查询),那么Broker节点直接返回数据给客户端,而无需再查询各历史节点,进一步提高了查询速度;再次,基于Druid基本存储单位Segment的特殊存储格式,列式存储保证了,每次查询只查询其需要的列,而不必查询出一行中的所有数据列,Bitmap索引的使用,保证了其快速查询。

下面重点介绍一下其中Bitmap索引: 

我们考虑如下场景,一场举世瞩目的篮球名人慈善赛在洛杉矶举行,所得善款全部用于公益事业,参加篮球赛的有现勇士球星Curry和Durant,著名歌手Beyonce、Biber,还有另外一名Curry女士参加等等。 其中每人得分及相应捐款如下:

640?wx_fmt=png

如果想查询出篮球运动员Curry的得分情况和捐款情况,如何快速查询出来呢?

首先,为每个字段中的每个值建立一个Bitmap索引,上述中共有name/gender/profession/score/donation 5个非时间字段,其中name/gender/profession属于维度列,score/donation属于度量列。对于name这个字段,因为其有4个值,Curry、Durant、Beyonce、Biber4个值,因此有4个Bitmap,每个Bitmap 0表示无,1表示有,Bitmap大小由数据条数决定,即有多少条数据,这个Bitmap的size就是多大。

Curry对应的Bitmap如下:

1

0

0

0

1

Profession中basketball player的Bitmap如下:

1

1

0

0

0

要查询勇士球星Curry的记录的话,就直接用上述两个Bitmap做"与"运算即可,得出:

1

0

0

0

0

这样的话,即可得出第一行即为其查询结果。
另外,对于同一个字段的各个值,其中只有与记录条数相等的1的个数,其余全是0(比如: 对于name字段,其有4个值,5条记录,那么对于这4个值得4个Bitmap中,仅有5个值为1),可以使用压缩算法对其进行压缩,Druid使用的是Roaring Bitmap Compression,详情请见: https://roaringbitmap.org/ 。

4.展望

Druid在0.10版本之后开始支持SQL,且随着版本的升级支持的SQL函数也越来越多,但因为Druid SQL本质上是一个语言翻译层,受限于Druid本身的查询处理能力,支持的SQL功能有限。 Druid目前并没有支持JOIN查询,所有的聚合查询都被限制在单个DataSource进行,但在实际的使用过程中,往往需要不同DataSource进行关联查询才能得到想要结果,这也是目前Druid开发团队的难题。

现在爱奇艺大部分DataSource的Segment的粒度是天或小时级的,当需要查询的时间跨度比较大时,会导致查询变慢,占用大量Historical节点资源,可以创建一个Batch任务,把几天前(或几周前)的数据按照天或月粒度Roll up重新构建Index,当查询时间跨度较大时,性能会有明显提升。

此外,因为目前爱奇艺号不同功能使用的是同一个Druid集群,只是在DataSource间做数据隔离,但是数据查询Broker之间并未做隔离,各功能之间数据查询会互相影响,也是希望解决的难题。

这篇关于​爱奇艺|海量数据实时分析服务技术架构演进的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327433

相关文章

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Java异常架构Exception(异常)详解

《Java异常架构Exception(异常)详解》:本文主要介绍Java异常架构Exception(异常),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. Exception 类的概述Exception的分类2. 受检异常(Checked Exception)

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

Redis 中的热点键和数据倾斜示例详解

《Redis中的热点键和数据倾斜示例详解》热点键是指在Redis中被频繁访问的特定键,这些键由于其高访问频率,可能导致Redis服务器的性能问题,尤其是在高并发场景下,本文给大家介绍Redis中的热... 目录Redis 中的热点键和数据倾斜热点键(Hot Key)定义特点应对策略示例数据倾斜(Data S