本文为 presto & Alluxio & 缓存白名单策略的技术综述,摘录自各处最佳实践。
基于Alluxio与HDFS支撑Presto和TPC-DS查询场景的性能测试
基于Presto+Alluxio的adhoc查询方案在网易游戏的实践
唯品会实践案例:基于Alluxio优化电商平台热点数据访问性能
网易严选:基于Alluxio+Impala深度融合架构的BI系统性能优化实践
别的文章:
教育大数据智能分析平台研究与实践 架构图有趣,文字价值一般
贝壳找房
为什么使用 Alluxio
QueryEngine 底层目前使用三种查询引擎:MR、Tez 和 Spark SQL,根据用户的选择及查询的代价来智能的选择执行引擎。为了降低对 Spark SQL 的影响,Spark SQL 引擎使用的是独有的 Yarn 集群。原始架构有如下问题:
1)数据量大,而且请求量变大,查询性能变差;
2)Spark SQL 计算与存储分离,每次查询都需要远程加载数据,数据本地行查,性能差;
3)目前的分析基本都是 T+1 的数据,数据基本不变,每次查询都要远程拉取数据,对大数据存储集群和网络 IO 压力很大;
4)对相同的数据会有多次的访问查询。
基于上面 Alluxio 的特性分析,alluxio 非常适合我们的业务场景,可以用于加速 QueryEngine 的查询分析。
缓存白名单做法
考虑到成本问题,SSD 的存储有限,而 adhoc 查询的数据量却非常庞大,高达数百 TB。因此我们基于过去 30 天内的 adhoc 查询记录,分析出表的访问频率和分区范围以及表的大小等三个维度的信息,只对中小表、高频访问的热表以及每个表的高频分区进行 Alluxio 缓存加速,针对进入 Spark SQL 的非白名单查询,则访问 HDFS 中的数据。
针对 Spark SQL 的查询,我们使用的是 Spark ThriftServer。为了使进入白名单的数据查询 Alluxio 中的数据,而不是 HDFS 中的数据,我们修改了 HiveMetaStore 的相关源码,使数据地址指向 alluxio 中的数据地址,而非 HDFS 中数据的地址。这样进入白名单表的查询,使用修改源码的 HiveMetaStore,而非白名单表的查询使用原始的 HiveMetaStore,从 HDFS 读取数据。
考虑到 Alluxio 冷读较直接访问 HDFS 有性能损失,因此我们每天都会定期提前加载新白名单中的数据,缓存到 Alluxio 中,并且淘汰旧的不需要的分区中的数据。
基于Alluxio与HDFS支撑Presto和TPC-DS查询场景的性能测试
为什么要引入 Alluxio
- 通过监控发现计算节点的物理内存有富余,不需要增加额外机器成本
- 机器网卡较为空闲,瓶颈主要存在于磁盘IO
- HDFS所在磁盘存在多种不同类型负载,数据读取速度不稳定
- 热数据读取加速
- 存储计算分离,在计算节点提高数据本地性
- 统一命名空间,虚拟数据湖
场景依赖
Alluxio 的落地非常依赖场景,否则优化效果并不明显(无法发挥内存读取的优势)。
- 存储计算分离
- 有明显热表/热数据
- 多数据中心访问加速
- 相同数据被单应用多次访问
- 数据并发访问
基于Presto+Alluxio的adhoc查询方案在网易游戏的实践
数据分析人员通常会经两种途径来访问这些海量的原始或表格数据:
常规的业务指标会经由成熟的报表系统落到到数仓存储系统;
除此外还存在着另外一种类型的adhoc(即席)报表查询需求,其业务特点为:
- 查询条件灵活,无法事先确定查询的表名和SQL语法
- 查询的数据量相比于离线ETL一般比较少
- 能够提供查询过程的进度百分比(经过与业务同学的沟通,发现对这个的需求出奇的高)
- 查询实效性要求高,以满足业务人员数据探索的需求。根据数据量的不同,查询平均时延要求在2-15s左右
SparkSQL的 adhoc 缺点
SparkSQL在进行查询的时候,一般都需要先向YARN申请一定量的资源,在集群比较繁忙的时候,申请资源的时间往往都是秒到分钟级别,会极大程度影响查询速度;
SparkSQL存在大量的HDFS IO: 源数据在HDFS上;另外,SparkSQL的默认的shuffle配置会导致超过executor内存大小的中间数据落到HDFS IO。但是从我们线上环境来看,datanode的磁盘IO延迟和吞吐极不稳定—特别是在离线作业高峰期的时候更加明显—导致查询的性能存在比较严重的波动。
唯品会实践案例:基于Alluxio优化电商平台热点数据访问性能
背景
在互联网电商平台上,广告是提升成交总额(GrossMerchandise Volume)和拉取新客的常见途经。在广告系统或广告运营中都需要基于人群数据分析进行定向的用户广告投放。在第三方平台进行广告投放,同样需要使用人群数据分析计算。根据计算分析方的不同,可以分为两类,第一类是基础数据全部发送给第三方广告平台,如抖音,腾讯等,由第三方在投放人群时候进行人群计算并作选择;第二类是人群计算工作在电商平台内部完成,推送给第三方的只是单个的人群包数据(设备数据)。在唯品会,我们目前采用第二类方式进行人群计算投放。我们每天需要完成数万的人群包计算,这些计算都是基于几张位于HDFS的之上的Hive表完成,这些表每天通常都行需要被访问上万次。
引申:人群包一般是怎么计算的?
人群包就是将用户进行分类。一般根据用户的设备号、手机号等,将用户分为几个类别,当然类别之间可以重复。例如常用的人群包种类包括:电商人群包、学生人群包、美容人群包等等。广告主可以选某种人群进行定向投放。
一般就是聚类算法,他们通过聚类算法等分析这批样本客户在自己媒体中的行为数据及注册数据,比如爱看什么视频啦、什么时间上网啦等等之类的。不断优化算法并对样本客户进行训练,看看自己的算法和购买来的特征数据差异有多大,如此一直优化到准确率可接受为止。当算法准确率到达可接受程度了,就可以让算法发挥作用了,在广告投放过程中使用这套算法猜测访问者的特征,然后对符合特征的访问者投放指定的广告。
问题描述
在集群相对稳定的情况下,一个人群计算任务的执行时间约3分钟。在集群不稳定的情况下,执行时间的变化会比较大,具体部分运行时间如下图2所示。在这种情况下,计算任务的资源消耗比正常情况大很多,大约能达到30/3=10倍左右,同时人群计算也难以达到业务时间要求(20:00前运行完成)。我们将运行不稳定的原因总结为以下几个方面:
- 人群计算任务的数据本地性不好。
- 在单个节点计算热点数据,交换机80G上下行带宽也常常打满(DN节点双万兆网络)。
- HDFS读写本身存在长尾现象。
新的目标
为了更好地满足热点数据的计算需求,我们需要取得较好的数据本地性。因此,我们希望能够达到以下目标:
计算与存储同置,这样数据就不需通过网络反复读取,造成网络流量浪费。
减少HDFS读写长尾对人群计算造成的额外影响,同时减少人群计算对于HDFS稳定性的影响。
广告人群计算介于线上生产任务跟离线任务之间的任务类型。这里我们希望能保证这类应用的可靠性和稳定性,从而更好地为公司业务赋能。
结果评价
基于Alluxio的新架构解决了HDFS热点数据的读取问题,从而使得广告人群计算这类准生产应用也能得以保障,实现了技术赋能业务。另外,计算效率的提升也对带来了可观的资源的节约,额外支撑的硬件只是少量SSD盘。
网易严选:基于Alluxio+Impala深度融合架构的BI系统性能优化实践
Alluxio在网易严选BI场景的挑战分析
Alluxio的部署和使用方式非常简单,然而在大规模数据的BI场景中不经调优地直接使用Alluxio,性能结果与预想的存在一定差距。具体原因分析如下:
- Alluxio并不像我们最初设想的那样,只是一个单纯的缓存服务。Alluxio首先是一个分布式的虚拟文件系统,有完整的元数据管理、块数据管理、UFS管理(底层文件系统的简称)以及健康检查机制,尤其是它的元数据管理实现比很多底层文件系统更加强大。这些功能是Alluxio的优点和特色,但也意味着如果每次都完整地使用Alluxio的全部功能,完成整个读操作的链路额外开销要比从一个单纯的代理服务、或支持自动Load的缓存服务要高。
- 对于大数据场景,内存缓存容量相对于计算引擎需要读取的数据量之间的比例常常是很低的。以严选为例,计算引擎每天需要读取的数据量在30TB左右,对比之下我们提供的1TB内存盘就显得捉襟见肘。低缓存量会导致低命中率和频繁逐出(Cache Eviction)开销,此时无论使用LRU、LRFU还是其他缓存策略,都无法带来明显改善。
在使用Alluxio之前,网易有数系统已经使用Redis开发了内部的图表缓存功能(即下图中的一级缓存),用于主动缓存相对稳定或相对重要的图表数据。
解决方案
- 由于我们的场景下缓存空间/数据量比例很小且数据的热度普遍不高,因此直接使用LRU等缓存策略的效果和性能不理想。我们的解决思路是将需要缓存的数据量减少,高效利用缓存,具体方式是只缓存最有“缓存价值”的数据。
- 数据块的缓存价值=节省的IO时间
=(数据块大小 / 平均IO速度+读取数据块的额外时间开销)*数据块的读取次数 - 分区/表的缓存价值 = 该分区/表中所有数据块的缓存价值之和
- 数据块的缓存价值=节省的IO时间
- 设计实现了缓存价值分析程序,根据每天的数据请求记录计算出被访问到的表或分区的缓存价值,然后按照缓存价值大小取其中排名靠前的表或分区加入缓存白名单,不在白名单中的数据将不使用Alluxio进行缓存。我们会将缓存空间/数据量比例控制在30%-70%的区间,然后结合使用LRFU策略就可以得到较好的缓存命中率和性能提升。
- 对于不在缓存白名单中的数据(较低缓存价值的数据),我们会使用Impala的数据路由功能,跳过Alluxio直连HDFS,从而避免从Alluxio读带来的开销。
探秘Presto+Alluxio高效云端SQL查询
当Alluxio的数据编排层和Presto一起部署时,可以优化整体的数据栈,使得数据栈在每个工作节点上具有更紧密的数据本地性。首先,用户可以使用Alluxio来对Presto缓存数据。这意味着计算驱动着数据需要从底层数据竖井和存储系统中取出。数据根据查询行为存储到缓冲区中,而查询行为又意味着最终用户行为,而最终用户行为又意味着最热的数据。I/O的操作从底层的慢速存储系统交给了Alluxio中一个非常快的数据访问层来进行。
百度案例:使用Alluxio提速数据查询30倍
使用Alluxio将原先的批处理查询将转换为交互式查询,这使百度能够以交互方式分析数据,从而提升了生产力,并改善了用户体验。
场景描述
由于PB级别的数据分布在多个数据中心,因此数据查询很可能需要将数据从远程数据中心传输到计算所在数据中心,这就是导致用户运行查询时出现很大延迟的原因。由于数据存储中心节点和数据计算中心节点具有不同的最优硬件规格,因此解决方案并不是将计算过程移动到存储数据中心那么简单。我们需要一个内存级的存储系统来存储常用的“热”数据,并且该系统能够位于计算节点上。
组件
我们的系统包含以下组件:
- 操作管理器:包装Spark SQL的持久化Spark应用程序。它接受来自查询UI的查询,并提供查询解析和查询优化功能。
- 视图管理器:管理缓存元数据并处理来自操作管理器的查询请求。
- Alluxio:用作存储常用数据内存级存储系统,提供计算本地性。
- 数据仓库:基于HDFS系统的远程数据中心,用于存储数据。
Presto在滴滴的探索与实践
presto 在滴滴的业务场景:
业务场景
- Hive SQL查询加速
- 数据平台Ad-Hoc查询
- 报表(BI报表、自定义报表)
- 活动营销
- 数据质量检测
- 资产管理
- 固定数据产品
使用 Presto + HDFS 有一些痛点:
- latency高,QPS较低
- 不能查实时数据,如果有实时数据需求,需要再构建一条实时数据链路,增加了系统的复杂性
- 要想获得极限性能,必须与HDFS DataNode 混部,且DataNode使用高级硬件,有自建HDFS的需求,增加了运维的负担
特性增强
insert数据时,将插入数据的总行数写入HMS,为业务方提供毫秒级的元数据感知能力
支持查询进度滚动更新,提升了用户体验
支持查询可以指定优先级,为用户不同等级的业务提供了优先级控制的能力
修改通信协议,支持业务方可以传达自定义信息,满足了用户的日志审计需要等
支持DeprecatedLzoTextInputFormat格式
支持读HDFS Parquet文件路径
稳定性建设:Presto在使用过程中会遇到很多稳定性问题,比如Coordinator OOM,Worker Full GC等,为了解决和方便定位这些问题,首先我们做了监控体系建设,主要包括:
- 通过Presto Plugin实现日志审计功能
- 通过JMX获取引擎指标将监控信息写入Ganglia
- 将日志审计采集到HDFS和ES;统一接入运维监控体系,将所有指标发到 Kafka;
- Presto UI改进:可以查看Worker信息,可以查看Worker死活信息
引擎优化及调研:作为一个Ad-Hoc引擎,Presto查询性能越快,用户体验越好,为了提高Presto的查询性能,在Presto on Hive场景,我们做了很多引擎优化工作,主要工作:
- 某业务集群进行了JVM调优,将Ref Proc由单线程改为并行执行,普通查询由30S~1分钟降低为3-4S,性能提升10倍+
- ORC数据优化,将指定string字段添加了布隆过滤器,查询性能提升20-30%,针对一些业务做了调优
- 数据治理和小文件合并,某业务方查询性能由20S降低为10S,性能提升一倍,且查询性能稳定
- ORC格式性能优化,查询耗时减少5%
- 分区裁剪优化,解决指定分区但获取所有分区元信息问题,减少了HMS的压力
- 下推优化,实现了Limit、Filter、Project、Agg下推到存储层
18年我们为了提高Presto查询性能,也调研了一些技术方案,包括Presto on Alluxio和Presto on Carbondata,但是这2种方案最后都被舍弃了,原因是:
- Presto on Alluxio查询性能提升35%,但是内存占用和性能提升不成正比,所以我们放弃了Presto on Alluxio,后续可能会对一些性能要求敏感的业务使用。
- Presto on Carbondata是在18年8月份测试的,当时的版本,Carbondata稳定性较差,性能没有明显优势,一些场景ORC更快,所以我们没有再继续跟踪调研Presto on Carbondata。因为滴滴有专门维护Druid的团队,所以我们对接了Presto on Druid,一些场景性能提升4~5倍,后续我们会更多关注Presto on Clickhouse及Presto on Elasticsearch。
Presto在车好多的实践
优化:
客户端和服务端之间加一层代理
- 代理层的作用不仅隐藏了 Coordinator 真实地址,而且可以根据需求设置一些客户端接入规范,以便能区分接入方式/类型等。我们还在代理层附加了下面两个主要功能:在每一个 Query 结束时,会记录其所有信息并发送到 Kafka,最终落入到 Hive,即日志审计,方便管理员后续分析/治理;监控一些 Query 指标,在超出阈值时主动 kill Query,提高集群稳定性。
服务经常 OOM,很不稳定。经过调研,我们采取以下措施来优化 OOM 问题:
- 设置堆外内存最大使用量 MaxDirectMemorySize
- 设置 glibc 的参数 export MALLOC_ARENA_MAX=1
2.3 棘手的排队问题出现
背景
经过了一年多的迭代,Presto 在车好多集团内部成为了提供 Adhoc 查询的核心组件,数十个业务线的数百名用户都重度依赖 Presto 来实现他们的分析需求或者报表结果,基本上集群每天有 600+用户(数据分析师、运营、市场、产品等),高峰期每秒提交数目最大能达到百级别。在这样的一个情况下,高峰期任务排队的情况就会出现并且越来越严重,严重影响了用户的使用体验。
解决方案&效果
首先的想到的是任务治理
• 大查询限制:导致集群排队的主要原因是大查询(耗费计算资源多的 Query)长时间占用集群资源不释放,集群最大运行 Query 数目被打满,后续提交的 Query 只能排队。为了限制大查询,我们下调单个 Query 的最大运行时间、最大扫描分区数目、内存使用最大值、stage 数目等,让集群资源快速流转起来;
• 单个用户 Query 数目限制:我们下调单个用户的最大运行数目以及最大排队数目,防止单个用户提交过多查询占满集群资源,其他用户没有机会提交;
• 优化 SQL:我们根据一些规则,给出 SQL 优化的建议,比如:避免笛卡尔积、distinct 滥用、非等值 join 等情况,并推动用户优化 SQL;
• 推动上层 BI 工具缓存结果:为了方便用户使用,有一些 BI 工具来对接 Presto,有多个用户会查看同一张报表,基于这样的情况,没有必要每次查看都要发起一次查询,工具层缓存这个结果,对底层 Presto 的压力会大大缓解;
• 推动中间表的建设,优化查源表的情况,减少计算资源的浪费;
• 每周统计出各个部门的资源使用账单&资源消耗排名 Top N 的用户,并通知,这是推动用户优化任务重要的数据来源;
其次,增加资源,这也是必然要尝试的一个方法。然而由于一些客观原因,比如:成本、机房初始容量规划等,无法给集群进行提供充足的资源,只能小规模有限扩容。
通过以上两个方面的优化,尤其是任务治理,排队情况得到缓解,然而总会有一些新用户会提交一些不合理的任务,因此任务治理是一项长期持续的工作。资源方面,没有条件新增,那么就只能在存量资源上想办法。
即席查询(Ad Hoc)如何做到又快又稳?
以下的这四种问题虽然都是在即席查询场景中相对常见的问题,但解决起来却并不容易。
- 只查询单个总 PV 和总 UV,但是却读取了上百 G 数据;
- 虽然 CPU 还没跑满,但是内存一直不够,各种 OOM;
- CPU、内存、磁盘 IO 都空闲,但是查询性能就是慢;
- 晚上跑 ETL 集群资源足够,白天分析师互相杀 SQL。
“减 IO、控内存、降带宽、优调度“这四个手段
- 减 IO 是一个统称,是指在查询的每个环节中,都需尽量去减少向上一步传输的数据量。
- 场景1、只读取相关数据
- 场景 2、建立稀疏索引
- 场景 3、使用转换漏斗模型(用户分群、商品价格稀疏索引、事件名称分桶)
- 经常会需要在有限的资源下满足客户多种的数据分析需求的挑战,所以需要控内存。
- 场景 1、分桶执行策略。Bucket Execution:优化后的内存占用=原内存占用/数据分桶个数
- 场景2、流量洪峰时的策略执行(Dynamic Bucekt Execution,即动态分桶执行策略:优化后的内存占用=原内存占用/数据分桶个数/用户 ID 分片数。)在动态分桶的基础上,优先保证每个桶的主键全局有序,再按照主键进一步进行范围切割。
- 但是在大数据场景中,影响效率的并非只有上文所提到的这两个因素,集群之间的网络带宽情况经常也会成为导致查询性能降低的诱因之一。
- 因此这部分的重点是降低带宽。通过把用户数据进行 hash 并分成多片,使每台机器只处理特定数据,这样就不会涉及到计算中间结果的再次 shuffle。
- 即便通过上述『减 IO、控内存、降带宽』这3个环节的性能优化后,在实际数据处理的过程中往往还是会遇到集群压力负载大、多用户同时查询等场景下的不可用情况。
- 此时就需要进一步梳理客户场景对 ad-hoc 查询的需求是什么,一般来说,有以下三点:
- 查询结果确定可以出结果,而不是直接报错和多次人工重试;
- 在多人使用的场景下,分析师希望自己先提交的查询一定能先出结果,而不是被后面的查询抢占资源;
- 日常数据分析过程中,有一些紧急查询需要提前,不能等待其它任务完成。
- 通过以上一些场景需求,从而可以针对性定义了3个优化目标,分别为:查询结果可保证、查询速度可预期以及查询队列可控制。
- 此时就需要进一步梳理客户场景对 ad-hoc 查询的需求是什么,一般来说,有以下三点:
网易云音乐数仓建模案例—声波APP
3.1现有设计
快速便捷获取高质量数据是业务侧的希冀,同时为减少ad-hoc式的查询也是我们的希冀。因此构建声波olap模型,目标是帮助业务人员快速使用数据,获取结果并用于业务生产。
取数模型设计:
目前模型建设流程:
- 业务侧/已有报表中归纳常用指标
- 模型设计(常分析的业务过程(交易、互动)的明细、用户、房间、用户+房间的汇总表)
- 模型评审
- 配置模型(使用场景的说明、字段业务口径、技术口径、添加自定义维度、自定义度量)
- 测试使用
流量自动化的解决方案:
- 策划梳理坑位信息-〉与策划勾兑坑位信息-〉设计埋点scm信息-〉上传埋点到埋点平台-〉与开发勾兑埋点内容–〉下载最终版坑位信息制作坑位码表。
- 设计流量自动化的聚合表模型:uid+os+appver+mspm+source(+房间id+房间模版类型id)的粒度统计对应的(曝光、点击、进房)次数、人数和时长等信息。构建流量自动化模型,最终可由取数展示,该模型可以查看日常曝光点击的坑位PV、UV,同时可以查看核心(曝光-点击-进房)漏斗数据。
3.2思考
目前存在的难点,这些都是后期会优化的内容。
- 数据侧:a.模型设计(聚合、解耦) b.模型迭代回跑
- 平台侧:a.平台开发进度无法满足模型使用 b.问题响应速度依赖其他部门
- 业务侧:a.对数据的维度、度量、聚合、日期分区的理解困难 b.自主分析数据的习惯尚未建立
大数据展现——即席查询
产品定位
即席查询(BONC Intelligent Query)是北京东方国信科技股份有限公司针对商业智能应用领域、面向公司内部开发人员和行业最终用户使用的快速查询、取数的应用工具。即席查询能有效地减少取数环节、实现快速取数响应,并能够有效缓解支撑人员的工作压力、能够防止各级人员理解差异或偏差,低成本、高效地保证统计口径一致。通过即席查询以“IT系统”替代“IT部门”实现取数支撑,能够促进IT支撑的转型,把更多的精力投入到数据保障和数据分析领域。
1. 统一的语义管理体系
由元数据平台提供统一的指标与维度语义管理体系,避免重复定义维度和指标,独立、业务语义管理与物理数据层的管理各自独立且通过映射关联,具备更强的灵活性和可扩展性,关注业务、查询。业务人员不需要了解数据物理上是如何存放、如何理解、如何获取,只需要知道自已在业务上想要什么数据。
2. 智能化查询取数
后台可以根据立方体配置信息,自动选择表及表关联进行查询。保证找到数据量最小,运算量最小的数据进行取数。系统可进行自动优化,对于汇总级较快的查询,直接展示,对于明细级较慢的查询,自动生成后台任务;并且可以根据系统的使用情况进行自组织管理,自动优化数据存储、优化数据查询语句、优化数据索引、自动重复利用数据缓存等。
3. 多样化取数方式
包括规则定义取数、模版取数、预约任务取数、文件上传取数、SQL模版取数等取数方式。
- 规则定义取数:用户可以根据实际需求通过页面自定义取数规则。通过设定描述性的维度约束、设定查询特定的指标数值范围来实现。
- 模板取数:针对在一定时期内存在需要重复多次但约束条件变更不大的需求。在规则定义取数基础之上,将按一定规则配置的取数查询,保存为共享的模版,通过定制好的模版提供查询,为快速查询提供了良好的解决方式。
- 预约任务取数:在规则定义取数时,如果是明细查询,查询数据时会自动转为任务执行,任务在一定的时间段内才会被执行,出于系统的性能考虑,需要对系统的任务执行情况作相应的调度和控制。
- 文件上传取数:主要用于小规模小范围,而且需求比较明确的快速查询,可以省去通过自己构建维度来查询,大大的方便了操作人员的使用。
- SQL模板取数:(也就是自助 SQL)通常情况下,专业IT人员如果想要操作数据库,必须使用数据库客户端工具连接到数据库服务器上进行操作,SQL模板取数提供了一个WEB版的SQL客户端工具,用户通过使用浏览器即可对数据库进行数据操作、查询。