浅谈缓存技术在OLAP场景的查询加速实践


引言

向量化和物化视图是OLAP领域的热点技术,因为最佳实践往往能降低1-2个数量级的查询时间。而缓存技术虽然也能和向量化、物化视图技术一起显著加速OLAP查询速度,降低查询的硬件成本,但关注度不高。


之前写过一篇介绍PrestoDB缓存加速的文章《如何挖掘闲置硬件资源的潜力》,也跟多个社区的小伙伴交流过如何更好的使用缓存,我产生了一个想法:

能否梳理下缓存技术在OLAP领域的实践情况,让更多人了解如何用缓存加速查询,降低成本!于是就有了本文:


本文作为科普文,首先介绍了相关概念,包括什么是OLAP数据分析,有哪些业务场景,时延的需求;开源大数据生态有哪些OLAP产品,实时数仓、数据湖、云原生要解决什么问题;接下来介绍缓存技术的原理和预计算、物化视图技术的异同;最后是缓存技术在OLAP场景的应用实践,并展望发展趋势。


多位社区伙伴在本文编写中提供了资料支持。特别感谢Alluxio社区的多位小伙伴,Doris社区的布道师家锋老师,Kylin社区的PMC霄翔老师,StarRocks社区的小伙伴(以上按开源社区的首字母排序),对本文的编写提供了帮助,帮助本文最终成稿。


OLAP数据分析

OLAP是Online Analytical Processing的缩写,是一种对大量数据进行多维度、多角度、多层次的分析,挖掘数据价值,以支持业务决策的过程。用户从不同的维度和层级来查询和分析数据,发现数据中蕴含的规律和趋势。


在线:看重交互反馈的时延性,越快越好。

分析:探查规律、趋势、变化、需求不固定。


OLAP的时延可以分为以下几档:

亚秒级:秒内看到结果。用户感觉非常连贯,完全没有等待感。由于用户看到数据至少要经过浏览器前端->看板后端->查询引擎计算,原路返回数据给前端展示,所以亚秒级要求看板后端从接收请求到获得数据在700ms内。

3秒级:3秒内看到结果。用户略有等待感,但不会觉得慢。

10秒级:10秒内看到结果。用户有明显的等待感,一般用户能接受。

分钟内:10秒到1分钟看到结果。等待时间略漫长,用户容易走神,思考还要等多久。

1分钟以上:对交互分析来说时间太长了,用户会觉得查询慢。


OLAP数据分析有三种常见的业务场景。


老板看板

老板泛指管理者,做决策的高管。同时也是管预算,买单掏钱的人。

老板看数,越快越好。应3秒内看到页面结果,最好能做到亚秒级。

老板的需求,需要第一时间响应,第一时间服务好。

老板更关注全局趋势,个性化需求是有限的,按需开发就好。


运营分析师的固定看板

分析模式相对固定,但新需求不断。

传统的开发模式,新需求一般需要开发排期,跟老板看板相比出数慢点也能接受。

一般来说,固定看板应10秒内看到结果,最好能3秒内。


数据探索自定义看板

强调自助性。用户自由选择数据源,过滤条件,计算逻辑,图表展示组件,进行数据分析探索。

由于一切皆可自定义,分析模式较难提前穷举。

一般需要产品层面支持可视化设置数据源,过滤条件,计算逻辑,图表展示。

特别是一些金融/商业化业务尝试挖掘数据价值的场景,查询不可控,容易遇到查询数据量大,计算逻辑复杂,分析耗时长的极端长尾案例。

虽然灵活,用户依然希望10秒内能看到结果,再复杂也希望不要超过1分钟。

一旦将数据探索所确定的分析过程定义成日常看板,进行统一的查询加速管理,也就覆盖了固定看板的需求。


大数据生态

大数据,数据之大,几台服务器的硬盘装不下。数据之多,几台服务器的算力算不出。

说到大数据生态,大家首先会想到谷歌的三篇论文,对应开源Hadoop的HDFS、MapReduce、HBase。现在依然较为活跃的有HDFS存数据,yarn调度,spark写离线T+1数据,flink写实时数据,以及其他的各种开源、商业产品,共同处理海量数据。


开源OLAP

OLAP领域的开源产品也有很多,较流行的有下面几个:

Druid:一个分布式的列式存储引擎,支持实时和历史数据的快速查询和分析,适合用于事件驱动的应用场景。按时间粒度预计算,不存明细。主要用于实时分析,但不支持数据修改合并,精准去重。

Kylin:一个基于Hadoop的OLAP引擎,支持多维分析和SQL查询,利用预计算技术提高查询性能,适合用于海量数据的分析场景。核心是Cube立方体预计算,主要用于离线场景,支持精准去重。

PrestoDB/Trino:一个分布式的SQL查询引擎,支持对多种数据源进行OLAP查询和分析,如Hive、HBase、Cassandra、MySQL等。适合用于多种数据源的各种分析场景。因为存算一体的本地存储方案Raptor项目被社区(FaceBook技术团队)放弃了,所以较难提供亚秒级查询响应,需要其他技术配合。

ClickHouse:一个面向列的分布式数据库管理系统,支持实时OLAP查询和分析,存算一体。具有极强的单表查询性能,适合用于单表分析。较早实践向量化技术,大力出奇迹的俄罗斯风格。

Doris/StarRocks:一个基于MPP架构的分布式数据库管理系统,支持OLAP查询和分析,具有低延迟、高并发、高可用性和易扩展性,适合用于各种分析场景。是一种比较热门的引擎技术,发展方向是实时数仓和湖仓一体。此外,Doris还在半结构化日志分析方向发力,目标是提供比ES更高性价比的日志分析解决方案。


实时数仓

实时数仓是一个热门的数仓概念。核心点就是,最近的数据能低延时的按需展示出来。

具体来说,要能低延时地采集、清洗、加工、存储海量实时数据,分析数据。目的是及时看到变化趋势,发现潜在问题,实时调整运营策略。 

难点是海量数据的低延时写入/可见性、同key数据合并,高基复杂过滤条件的精准去重uv统计等。

像Druid,不支持数据合并,精准去重。HBase写数据吞吐高,天然支持按key合并数据,查询明细时延低,但没有OLAP分析的能力。


数据湖

数据湖从定义上,指一个存储海量结构化和非结构化数据的系统,以原始数据为中心,提供了统一的数据访问接口,支持多种数据处理和分析。


理论上,无论什么数据源的原始数据,数据湖都能处理。现实是,大家不会直接在原始数据上进行所有操作,会对数据分层处理。


数据湖在实践中,主要解决hive数仓无法快速对历史数据进行修改或删除,没有ACID保证,实时写入场景小文件多的问题,最终提供了可修改数据的实时/离线数据分析的能力。


目前主流开源湖仓存储方案有三个:

Apache Hudi:由Uber发起的实时数据湖方案,主要特点是支持快速的upsert/delete操作、增量查询和流式消费等功能。

Apache Iceberg:由Netflix发起的通用数据湖方案,主要特点是支持高效的元数据管理、快速查询计划、快照隔离和增量消费等功能。

Delta:由Databricks推出的基于Spark的数据湖方案,主要特点是支持ACID事务、Schema演化、时间旅行和流批一体化等功能。

国内互联网公司用Hudi和Iceberg的比较多。此外,也有一些国产开源湖仓产品,比如数元灵科技开源的LakeSoul,服务于一些国企。

由于最近数元灵科技加入Linux Foundation AI & Data基金会,并捐赠了开源湖仓项目 LakeSoul,所以再额外介绍一下。

LakeSoul 主要特性有:

1

ACID 事务高并发更新;

2

高效灵活的 upsert 操作;

3

高性能的 IO 层;

4

BI&AI一体化地支持。

社区做的Benchmarks性能对比测试,写入和读取性能都很好。详见《数元灵科技加入Linux Foundation AI & Data基金会,并捐赠开源湖仓项目 LakeSoul》。


云原生

云原生是比较火的概念。

大数据服务可以在物理机上自建(包括自建云),也可以运行在公有云上。那么到底什么是云原生,云原生的好处是什么?

我认为云原生的核心是能否用好云的特性,提供高性价比。公有云和自建云的特性略有不同,下面分开介绍:


【公有云的云原生】

什么是云原生现在众说纷纭,但最早的时候,云原生是高性价比的代名词,是一种云上的最佳实践。对大数据分析业务来说,公有云上的存储选择很影响性价比。


跟物理机自建相比,云盘,特别是SSD云盘,价格占比较高。因为云盘并不是普通的硬盘,一般会有副本技术确保不丢数据,还要有网络设备,软件的支持。再加上云厂商自己的商业策略,相对cpu,内存资源来说,云盘的价格较高。

Hadoop生态的hdfs存储,基于单机硬盘无法保证稳定的假设,默认三副本,或使用EC纠偏码技术1.5倍副本,保证数据不丢。


公有云上,用虚拟机,挂云盘,在云盘上搭建hdfs集群,技术上没有任何问题,但存储成本会比物理机贵很多,IO吞吐也不如物理机的本地硬盘。自己基于SSD云盘搭建存算一体的数据库,存储成本也极高。


所以用云盘作为长期存储,有成本的问题。


如果是独享机型(实际是独享物理机)用本地盘搭建集群的方案,性能等同于物理机自建,但一般用户拿不到较低折扣的话,费用依然会很高。

如果是非独享机型挂载本地盘的方案,可挂载的本地盘容量有限,不适合作为长期存储方案。


以单位存储的价格来选择长期存储方案,那么云上性价比之王就是S3类对象存储。作为先驱,AWS的S3是事实上的云存储标准,每个公有云都会有类S3协议的对象存储服务。跟可挂载的云盘相比,S3最大的优势是单位存储便宜。

但由于S3本质上是一种分布式kv存储,所以跟hdfs文件系统相比,有两个比较慢的操作:move大文件和list目录操作。move操作换key要做数据的拷贝,list目录要根据前缀过滤遍历所有key,操作代价高。


KV存储包装成文件系统接口的关键,是用额外的元数据文件将文件路径和数据块路径信息解耦,hudi等云原生技术也是这么处理的。


所以,有大量move操作的HBase从性价比考虑不太适合公有云,需要对S3做适配,特别是move文件。hive这种批任务要做move,以及有list大目录操作的也不太适合,也需要做S3的适配。新生的hudi等数据湖存储格式,由于提供了元数据文件,没有move操作,适配s3,在公有云上天然性价比高,所以能够说自己是云原生。


如果使用S3做数据存储,大数据量现查现算是无法满足亚秒级需求的,需要配合其他技术,比如缓存和预计算。


【自建云】

除了公有云,国内还流行自建云(私有云/自有云/内部云)。

一般是有能力的大公司在自己的机房,自建IT基础设施,供内部使用。因为也使用虚拟化、容器化、微服务等云上流行的技术管理资源,提供弹性伸缩,灵活部署的能力,所以也是一种云。


自建云可以提供跟公有云类似的资源申请接口,计算、存储服务接口,具备弹性伸缩能力。此外,自建云还有一个优势,因为是内部使用,虚拟机/容器可以允许穿透资源隔离,直接使用宿主机的底层硬件。这样硬件的IO和物理机更相近,费用模型也等同于物理机,即相对于公有云来说存储更便宜。使用底层的硬盘,mover和list目录操作也不再有性能问题。


比如,节约存储成本考虑,可以使用单台40块10TB机械盘,25G网络的存储型物理机,hdfs冷数据策略存储1.5倍副本,6-3EC策略,访问频率低的历史冷数据。存储单价便宜,允许同时挂掉3台不丢数据,跟磁带存储相比提供了查询更友好的读能力。


加速查询考虑,可以让计算服务的容器直接挂载宿主机nvme ssd硬盘,适配真实宿主机分布的一致性hash调度策略,提供高性能、跨容器生命周期可用的本地缓存,加速查询。


所以自建云的存储选择面更广,能够成本更低。


广义缓存技术

缓存(Cache)最初是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,特点就是访问速度快。

广义来说,在OLAP领域,为了提高数据展示给终端用户的速度,额外保存、没有持久化需求的数据,都可以算作缓存。


硬件性能瓶颈

从物理架构来说,突破存储的硬件性能瓶颈,将数据临时保存在计算层能够更快速读取,更低响应延时的存储介质里,都可以算做缓存。


比如下面的例子,本地内存,每块内存读写20GB/s以上。一般DDR4内存理论读带宽上限90GB/s,即使服务器是numa总线架构,cpu访问remote memory比访问local memory按慢30%计算,单块盘吞吐也能超过50GB/s。

本地NVMe SSD,理论上每块盘的顺序读写性能大概2GB/s,并且一个计算型服务器可以挂多块盘。现在高配计算型服务器可以配NVMe SSD硬盘作为系统盘。

网络内存,一般延时比本地高,吞吐取决于网络带宽,同交换机25Gb网络可以提供大概3GB/s的读写吞吐性能。

本地SATA SSD,顺序读写大概550MB/s。

本地SATA盘,顺序读写大概150MB/s。

同地域云盘、S3,性能一般跟实例的规格有关,具体请参考各云厂商的官方数据。


同机房跨房间,同地域跨机房,跨地域,计算和存储的距离越远,访问延时越高,IO吞吐取决于两点之间的带宽上限。特别是跨地域的带宽比较贵,提高上限要搭建专线。比如杭州机房的电商交易数据走专线写到北方离线机房,两地之间搭建个几十G的专线,成本非常贵。一般来说计算层不要直接读取跨地域的数据,先拉到同地域再读。


举例来说,1台计算型服务器,有96核,16块32GB内存条即512GB内存,2块1TB的nvme硬盘,放在25Gb网络上,可以提供极快的内存和nvme硬盘缓存加速性能,也能提供网络内存为同交换机的其他服务节点提供缓存加速能力。


数据加工

从数据加工角度,把经过计算,更偏用户侧的数据,临时存下来也可以显著提高查询性能。所以缓存和预计算、物化视图技术也很相近,下面简单介绍下预计算和物化视图技术的异同:


预计算

OLAP的预计算是指在OLAP系统中,对可能的查询结果进行提前计算并存储,以提高查询性能的一种技术。预计算和缓存技术上没有明显的区别,预计算一般指在用户查询前主动计算和存储计算结果,而缓存一般指用户查询时再被动存储计算结果,加速接下来的查询。有3种常用的预计算策略:

全部预计算:这种策略是对数据立方体的所有可能的查询结果进行预计算,并存储在一个或多个新的数据立方体中。这种策略可以提供最高的查询性能,但是也会占用最多的存储空间,并且需要最长的更新时间。

部分预计算:这种策略是根据用户的查询需求,只对一部分常见或重要的查询结果进行预计算,并存储在一个或多个新的数据立方体中。这种策略可以平衡查询性能和存储空间的需求,但是也需要维护用户的查询模式,并适时调整预计算范围。

按需预计算:这种策略是根据用户的实时查询,动态地对查询结果进行预计算,并缓存在内存或磁盘中。这种策略可以节省存储空间,并且可以适应用户的查询变化,但是会增加第一次查询的延迟,并且需要管理缓存的有效期和淘汰机制。

Druid和Kylin都有预计算能力,方式有所不同:

Druid的预计算是基于用户设定的时间颗粒度,进行所有维度的预计算。查询跨时间粒度需要将多个时间粒度的数据做聚合。

Kylin的核心是Cube,预先对数据作多维索引,基本思路是预先对数据作多维索引,查询时只扫描索引而不访问原始数据。根据用户需求可以对特定维度组合进行预计算,存储在一个或多个数据立方体中。这种策略可以平衡查询性能和存储空间的需求,但也需要维护用户的查询模式,并适时调整预计算范围。

所以Druid适合实时分析和时序数据,Kylin适合离线分析和自定义维度。


物化视图

物化视图是一种特殊的数据库存储,包含了特定查询结果的数据,并存储在一个物理表中。物化视图可以用来提高查询性能,特别是对于复杂的聚合查询。


物化视图和缓存的区别,主要是物化视图是持久化存储的,一般自带可用性保障。而缓存是临时存储的,不需要保证可用性。


另外,提供物化视图功能的数据库服务可以根据基表的变化自动更新物化视图,由写基表触发。而缓存一般需要有数据库存储之外的同步策略,由读触发写缓存。


不同的数据库对物化视图的实现和使用方式有所不同,比如ClickHouse的物化视图更像是插入触发器,当向基表插入数据时,插入数据的一部分被物化视图SELECT查询转换,结果插入到视图中。如果视图中有一些聚合计算,则它仅应用于新插入的数据。源表现有数据的任何更改(如更新、删除、删除分区等)不会更改物化视图。查询物化视图必须要指定查询物化视图表。并且,ClickHouse的物化视图是应用于单机数据块的,分布式聚合结果可能不准确,依赖于写数据的切分数据策略。


Doris/StarRocks的物化视图可以自动根据原始表更新数据,不需要异步和原表做数据同步。物化视图应用于数据集整体,可以在查询基表时,使用CBO优化器自动优化为查询物化视图。StarRocks支持多表物化视图的查询改写,支持多表物化视图的分区刷新。Doris也计划在即将发布的2.0版本里完善多表物化视图的支持,所以Doris/StarRocks的物化视图比Clickhouse的可用性高。


缓存技术实践

查询结果缓存

OLAP查询的特点是海量明细数据产生少量分析结果数据,所以可以将少量查询结果缓存下来,一旦命中缓存就能提供稳定的用户侧亚秒级响应。


查询结果缓存一般由看板系统提供,独立于计算引擎/数据库之外。查询结果可以缓存在Redis,即网络内存中,供看板后端调用。


查询结果缓存有两个挑战:

  1. 第一次查询的预热问题,即如何预测用户的查询提前准备好结果缓存。所以查询结果缓存能极大的加速固定看板,但对数据探索帮助有限。

  2. 经常变化的数据如何缓存,即近实时场景如何用缓存。

实践中,用户视角的离线看板缓存命中率可以达到70%,即7成查询秒内出结果。实时看板缓存主要用于大促高峰大量运维用户盯相同看板的场景,目的是降查询并发,减少引擎计算资源的需求从而降成本,避免底层引擎过载从而提高系统稳定性。


离线看板

t+1更新的离线数据,可以缓存较长时间。当底层数据表发生数据更新/数据回溯,看板系统感知表的变化,无效该表的查询缓存,重新查询底层引擎,为避免某些数据变化场景缓存未如预期失效,使用查询结果缓存的看板系统应提供用户主动清除缓存的功能做兜底。


对离线看板,可以根据日常查询日志,统计出日常高频率的查询,做查询预测。数据加工产出后,在数据查询的低峰期、分析师上班前,先预查询一遍生成查询结果缓存,从而提高用户查询时的缓存命中率。


【Doris的SQL Cache】

Doris 自0.15 版本开始,支持了SQL Cache,缓存SQL结果集。SQLCache按SQL的签名、查询的表的分区ID、分区最新版本来存储和获取缓存。三者组合确定一个缓存数据集,任何一个发生变化,如SQL变化,查询字段或条件不一样,或数据更新后版本变化了,都不会命中缓存,避免返回旧数据结果。


SQL Cache存在be的内存中,跟Doris的分区缓存共享缓存容量。开启SQL Cache后,执行计划会计算SQL的hash,在fe的内存中通过hash索引找到SQL Cache信息,再去对应的be获取SQL Cache。


SQL Cache可以配置最大结果集行数,以及热分区的冷却间隔时间,以此来选择是按SQL Cache缓存还是按分区缓存。详见Doris官方文档。


【全量预计算】

重要的老板看板/高管看板,一种做法是用离线任务把可能会展示的分析结果全部加工出来,写到mysql里,看板后端直接查询mysql,这样所有看板都能亚秒级响应。


实时看板

实时数据或日内数据看板,虽然数据变化很快,依然可以使用查询结果缓存。主要目的是降查询并发,减少计算资源需求降成本,避免底层引擎过载提高系统稳定性,适用于有大量运营同时看数,反复刷新的场景。


要先跟业务方沟通能接受的查询延时,一般会按1分钟或5分钟的缓存有效期来缓存查询结果,以此来降低查询并发。这种大量运营同时刷新的看板,页面前端也应支持按看板区域局部刷新,因为大看板频繁刷新全量报表代价很高,而用户往往只关心部分数据表格的变化。


元数据缓存

一般是查询引擎内嵌的功能,用于缓存离线hive metastore的元数据,将元数据缓存到本地内存里。目的是不受离线hms查询时间波动的影响,因为离线hms的性能会受到离线集群负载的影响,有时会特别慢,甚至超过10秒才响应,元数据加载都超过10秒,查询就必然比10秒慢了。所以缓存到内存中可以不受公共hms响应时间的影响。


如前文介绍的,PrestoDB用过期时间,后台刷新时间,和LRU策略来控制元数据缓存的有效性。难点在于如果有其他系统更新了元数据,如何感知元数据变化。比如当天的小时分区,新写分区后元数据缓存还是旧的,查询就查不到新分区数据。本来新分区过一会就可见了,但如果上层系统也做了查询结果缓存,在数据更新后会重新查询计算引擎来刷新上层系统的查询结果缓存,但计算引擎返回了无新分区的旧数据,就容易造成旧缓存长时间没更新,新数据长时间不可见的问题。


PrestoDB社区解决数据有效性的方案是支持只缓存分区的元数据,并且使用分区缓存前先调用批量获取分区版本的接口来比较版本差异,有差异了再批量更新有差异的分区信息。但hms未开源获取分区版本的接口,并且公共hms负载高时查询其他的获取表,获取分区名列表的接口,依然可能很慢。


Doris 和StarRocks对hive外表,设计了一种增量同步元数据的方案。fe定时查询hms 当前eventId,如果有新增就获取全部增量event,过滤需要的并和当前元数据缓存做比较,有变化的主动刷新。但是,当我们有超大规模的离线集群,可能一套集群会对应多套hms,虽然hms的查询接口对外封装为一个,但请求event依然需要感知多套hms,分别去请求event,而StarRocks并不支持配置多套hms获取event。此外,大集群hms的event会特别频繁特别多,大部分对当前计算引擎缓存来说是无用的。最后,依然没解决极端情况下查询结果缓存更新了旧数据,新数据长时间无法更新的问题。


所以实践中采用的方案是,计算引擎提供清理,刷新指定元数据的管理接口,由上游看板系统来通知缓存清理和刷新。对变化敏感并且做了查询结果缓存的看板系统,能够感知spark数据加工任务运行完成,调用管理接口来清理缓存。

此外,对数据变化敏感的查询客户端,比如DQC,可以设置查询参数来让查询引擎不使用元数据缓存,从远端hms更新。


中间结果缓存

查询结果缓存在数据探索和实时数据分析场景的缓存命中率不高,而数据探索和实时数据分析场景用中间结果缓存依然可以有较高命中率,从而显著提高查询速度。


中间结果缓存是由计算引擎提供的功能。本质是,按数据块维度,缓存数据块在某些计算算子链的计算结果。下次有相同数据块的相同计算,可以直接使用缓存的计算结果。中间结果缓存命中可以极大提升查询时间,提高计算引擎查询吞吐。一次查询的大半数据处理命中中间结果缓存能够提供三秒内,甚至亚秒的查询响应。


对数据探索来说,虽然查询模式未知,依然可能在多次查询之间使用相同的数据块进行相同的计算,比如第一次比较前两天的数据进行分析,第二次比较前三天,前两天数据的计算结果就可以直接使用,只计算第三天的计算即可。


对实时数据分析来说,即使业务方不接受分钟级查询结果缓存,旧数据的中间结果缓存依然可以复用,只有新数据需要重新扫描计算。所以中间结果缓存对实时数据分析的效果非常好。对比下Druid的实时数据分析,Druid按时间片粒度统计了需要的统计数据,查询时再将各时间片数据组合起来,其实跟中间结果缓存就特别像。


广义上来说,Druid的时间片粒度预计算,Kylin的多维立方体上的预计算,Clickhouse/Doris/StarRocks的物化视图,都是用中间结果加速数据分析,只是把中间结果提前持久化了。预计算和物化视图不是本文的重点,下面介绍计算引擎支持的未提前预计算的中间结果缓存。


PrestoDB支持fragement缓存,按split数据块和计算链计算key,结果缓存在本地ssd里,LRU加过期时间控制容量。该功能依赖PrestoDB自身的软亲和调度策略,提高命中率,避免缓存副本数膨胀。


StarRocks3.0对存算一体表和湖表提供query cache支持,基于数据块和计算链,支持缓存各种join聚合结果,LRU缓存在内存里。详见StarRocks官方文档。


Doris自0.15 版本开始,存算一体表支持Partition Cache,按分区缓存计算结果,并在后续查询时复用。PartitionCache的缓存第一级Key是去掉了分区条件后的SQL的128位MD5签名,缓存的第二级Key是查询结果集的分区字段的内容,以及分区的版本号和版本更新时间。分区缓存目前只支持按分区字段分组聚合方式,并且只支持聚合结果集的前半部分或后半部分以及全部命中缓存,不支持结果集被分区缓存分割成几个部分。分区缓存存在BE的内存中,LRU控制容量,分区缓存在哪个be存储由分区数据的分布来决定,详见Doris官方文档。


通用缓存模型角度考虑,中间结果缓存的数据块分析任务调度、命中缓存,写缓存的逻辑跟本地数据缓存一致,在本地数据缓存章节再详细讨论,额外需要的是判断计算链命中和如何缓存的逻辑。比如根据数据处理后的数据压缩率、数据分析的计算复杂度阈值,将高于阈值的在内存中缓存,其他的缓存在本地SSD硬盘中。已存在本地且计算不复杂的数据不再缓存到硬盘。哪些计算链适合把结果缓存在一起,哪些计算链适合拆分为多个结果缓存等等。


数据文件缓存

数据文件缓存有两大类:一类是存算一体的本地数据块缓存,让存算分离架构也能提供3秒的查询响应速度。另一类是缓存集群,可以跨应用、跨异构存储的提供共享缓存支持,对跨机房,跨地域的加速尤其明显。


本地数据块缓存

将远程数据文件按数据块粒度存储在和计算同节点的SSD硬盘,内存中,就是本地数据块缓存。


如前一篇文章介绍的,本地数据块缓存对看板业务提速明显,缓存命中率也能达到80%以上,查询p80降低到3秒左右。结合前面介绍的查询结果缓存,中间结果缓存一起用,用户侧查询p90可以达到2秒以内。


【PrestoDB】

PrestoDB的本地数据块缓存是和Alluxio社区共建的,Alluxio的jar由PrestoDB worker进程加载使用。简单来说,本地数据块缓存主要包含以下技术:

一致性哈希算法调度策略并兼顾worker的负载,在worker负载不高时按一致性hash算法将相同数据块的读取任务调度到相同的worker上,避免缓存副本过多,提高缓存命中率。如果前两个worker负载都高,则随机选一个worker,并且指定不写缓存,避免缓存写的太多。

按1MB的粒度管理缓存数据块,存在SSD硬盘上。写缓存的同时LRU清理超过容量限制的缓存块。

支持异步和同步两种方式写缓存。即使是同步,也只是写缓存的前置操作是同步的,数据块写硬盘的操作依然是异步的。

提供缓存的监控指标,基于指标建立监控体系来衡量缓存的效果。

基于布隆过滤器链的shadow cache,评估缓存容量和缓存命中率的关系。这个功能是假设有无限的本地存储时,指定时间内的数据全部缓存,缓存命中率能达到多少。如果shadow cache的命中率很低,则说明业务很少重复访问数据,不太适合使用本地数据块缓存。如果shadow cache的命中率高而本地数据块缓存的命中率低,说明业务场景适合使用缓存,但当前本地缓存的空间太小了。这是因为在数据文件在被重复访问时,之前写入的本地数据块缓存,已经因为缓存满了而被淘汰掉了,所以重复访问无法得到加速。那么增加缓存空间配置,比如换个大一点的硬盘,就能取得更好的加速收益。 

判断数据文件版本,以避免查询hudi表报错。

在内存中缓存orc和parquet文件的索引块。

【Kylin】

Kylin 4.0也支持本地数据缓存。4.0将预计算数据由存在HBase改为存在Parquet文件里,用spark查询。云上会将预计算数据持久化在S3类对象存储里以降低存储成本。为了提高 Kylin 4.0 在使用云上对象存储时的查询性能,提供了spark查询任务的软亲和调度和本地缓存的能力,可以设置将数据缓存到spark计算节点的内存或是磁盘中。详见Kylin官方文档。


【StarRocks】

StarRocks3.0也有本地缓存功能,一致性哈希算法调度策略,支持过期时间,内存和本地硬盘的双层LRU。但未看到有介绍开启本地缓存后调度如何兼顾be负载,如何主动判断数据版本的功能。


【Doris】

Doris 计划在即将推出的2.0 版本提供本地数据块缓存策略。一致性哈希算法调度,支持动态控制缓存块的大小,通过LRU算法、过期时间以及文件版本管理缓存生命周期。此外,会将数据文件的meta信息(如Parquet Footer)缓存在内存中,来降低存算分离表的的数据访问开销。


实时数据分析和数据湖

对于实时数据分析,一般是查询日内数据趋势,以及做同比和环比,不变的历史数据依然可以缓存数据块,只需要从远程数据源拉取较新的数据。

对于数据湖,可能涉及小文件合并和数据修改合并,需要判断数据文件的版本,版本不变的数据文件依然按数据块缓存即可,有版本变化的重新从远端拉取数据,淘汰旧版本缓存。


本地硬盘的选择

如果有条件,使用本地硬件做缓存介质尽量使用nvme ssd。

如果是公有云环境,可以给计算节点挂载一块ssd本地盘。

如果是自建云,计算引擎容器化了,要能在容器重启后从宿主机硬盘重新加载本地缓存,并且调度策略能够按宿主机的真实分布给worker容器分配合适的数据块任务。


Alluxio社区规划

Alluxio社区在本地缓存上的发展规模,包括:

和集群模式一致,支持同时使用内存和硬盘,双层LRU缓存。

提升数据版本判断和旧版本数据清理的性能。

精细化统计指标,支持细粒度统计缓存命中情况,并能在具体查询的上下文里记录缓存命中情况。

支持设置指定哪些路径缓存。

跟Doris社区共建Doris的本地数据缓存实现。


一些畅想

本地缓存的发展趋势是智能化,即自动采集分析历史数据,判断不同数据的缓存性价比,选择合适的缓存存储介质。


可以统计哪些表、哪些分区访问频率高,在哪个时间段访问频率高,按访问评率分优先级进行缓存。比如历史数据和近期数据缓存的性价比是不同的,查询最近3天,相对数据量小且查询频率高,即缓存性价比高,高优缓存尽量不被淘汰。查询三个月前的全量数据,频率低数据量大,缓存性价比低,不进行缓存。


智能在内存和ssd硬盘中做选择。频繁被访问、数据量较小的数据可以优先缓存在内存中。访问率低的的缓存在硬盘,甚至在负载高时暂不缓存。数据已经存储在本地硬盘的,不再缓存到本地硬盘。


对于实时数据分析,频繁改变现有数据的分区,即使查询频率很高,也能智能的降低缓存优先级。


native读

对于Orc和Parquet文件格式,很多计算引擎都有各自的native读优化,可以更细粒度的读文件元数据和精简数据块。为适配读,数据块可以按读数据需进行更细粒度的缓存管理。


分布式缓存集群

本地数据块缓存是计算引擎进程内的缓存,只服务自身一个应用,且容量有限,无法提前拉取数据。


而分布式缓存集群,可以跨应用、跨异构存储的提供共享缓存支持,提前拉取数据,对跨机房,跨地域的查询加速尤其明显。


Alluxio分布式缓存集群是业内比较知名的开源缓存产品。Alluxio缓存集群主要提供了统一多数据源的管理能力:

为跨地域、跨云,跨异构存储提供统一存储抽象,统一命名空间,统一数据访问接口。引入新的或者改变旧的存储系统,计算层可以无感知。

提供策略化数据管理能力。支持将数据按冷热策略写到异地、异构存储中,自动将由热变冷的数据归档到低成本存储介质中。

分布式缓存服务。将频繁访问的数据(特别是和计算层距离较远IO较低的数据)缓存到和计算层同网络甚至是同节点的内存或高速硬盘中,提供跨应用服务、节点级数据本地性。

分布式缓存对AI训练的数据读加速效果很好,也能加速OLAP查询分析。Alluxio缓存集群可以提供兼容现有文件系统/对象存储接口的统一数据访问层,兼顾海量数据的低存储成本和热数据缓存高IO性能,提高性价比。


Alluxio缓存集群在腾讯的实践可参考:《腾讯 Alluxio:加速新一代大数据与 AI 变革》


Alluxio缓存集群的技术细节可以参考:

《2min速览:从设计、实现和优化角度浅谈Alluxio元数据同步》—本文非常详细的讲解了Alluxio集群同步数据和数据的元数据的技术细节,期待有人能在2分钟内看完。


立即下载


软件下载


精选智库

本文分享自微信公众号 - Alluxio(Alluxio_China)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

工信部:不得为未备案 App 提供网络接入服务 Go 1.21 正式发布 Linus 亲自 review 代码,希望平息关于 Bcachefs 文件系统驱动的“内斗” 字节跳动推出公共 DNS 服务 7-Zip 官网被百度认定为恶意网站 谷歌发布 AI 代码编辑器:Project IDX 清华报告:文心一言稳坐国内第一,超越 ChatGPT Vim 项目的未来 凝思软件将上市,由“中国 Linux 第一人”创办 ChatGPT 每日成本约 70 万美元,OpenAI 或已在破产边缘
{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/5904778/blog/9723244
今日推荐