Alluxio导读
近期,腾讯 Alluxio 团队与 CDG 金融数据团队、TEG supersql 团队、konajdk 团队进行通力协作,处理了金融场景落地腾讯 Alluxio(DOP=Data Orchestration Platform 数据编排渠道) 进程中遇到的各种问题,终究抵达了功用和稳定性都大幅提高的作用。
布景
在腾讯金融场景中,咱们的数据剖析首要有两大入口,一个是依据sql的剖析渠道产品idex,另一个是图形化的剖析渠道产品”全民BI”。全民BI是一款相似tableau相同的能够经过拖拉拽进行数据探究剖析的东西,由于不需求编写sql,所以面向人群更广,不只包括了数据剖析人员,还有产品和运营,对耗时的敏感度也更高,而这里首要介绍的是针对全民BI运用场景的落地优化。
为支撑日益添加的各类剖析场景,今年腾讯金融事务数据团队进行了较大的架构晋级,引入了 Presto + 腾讯 Alluxio(DOP),以满意用户海量金融数据的自由探究需求。
大数据olap剖析面临的应战
| 应战一:从可用到更快,在快速增加的数据中交互式探究数据的需求。
虽然这些年SSD不管是功用仍是本钱都获得了长足的进步,可是在可见的未来5年,HDD仍是会以其本钱的优势,成为企业中心存储层的首选硬件,以应对未来还会继续快速增加的数据。
可是关于olap剖析的特色,磁盘的IO是近乎随机碎片化的,SSD明显才是更合适的挑选。
下图展现的是olap剖析中presto对一个ORC文件读取的视图,其间灰色竖条表明具体的剖析需求读取的三列数数据在整个文件中或许的位置分布:
| 应战二:在多种核算使命负载,olap剖析的功用如安在IO瓶颈中包围
企业大数据核算常见的两种负载:
✓ **ETL:**数据的抽取(extract)、转化(transform)、加载(load),首要是在数据仓库、用户画像、引荐特征构建上,特色是触及大部分的数据列。
✓ **OLAP:**在线联机剖析处理,首要用在对数据的多维度剖析上,特色是仅触及少数的数据列,但或许触及较大的数据规模。
虽然ETL的峰值会在凌晨,但其实整个白日都会有各种使命在不断的履行,两种类型使命的IO负载的影响看起来不可防止,再加上中心存储层HDD硬盘的IO功用约束,IO很容易会成为数据探究的瓶颈。
| 一种盛行的处理计划
面临这些应战,目前许多企业会挑选下面的这种架构:
将olap剖析需求的热数据(比方近一年)仿制到一个olap专用的存储中,这样不只能够处理IO竞赛的问题,还能够选用SSD硬盘,进一步加快olap。
可是这样的架构却又引入了新的问题:
✓ **数据的鸿沟:**由于数据需求提前仿制,假如需求临时剖析超出约好规模的数据(比方同比上一年),就会导致只能降级到中心存储上的引擎去履行,这里不只触及到存储的切换,也触及到核算引擎的切换。
✓ **数据的共同性和安全:**数据仿制需求面临数据共同性的拷问,别的便是这部分数据的权限和安全问题能否跟中心存储进行关联,不然就要独立管控数据的权限和数据安全,这无疑又是不小的本钱,这一点在重视监管的金融行业特别如此。
Alluxio:一种或许更优的计划
重新思考咱们的olap引擎的存储需求其实是:
1)有一份独享的数据副本,最好选用SSD的存储,满意更高的功用要求
2)不需求额外的数据办理本钱:数据生命周期、权限和安全
所以咱们首先想到的其实是在HDFS层面处理,Hadoop在2.6.0版别的时分引入了异构存储,支撑对指定的目录采纳某种存储战略,可是这个特性并不能处理咱们的几个问题:
✓ 不同核算负载的IO阻隔:由于这部分关于olap引擎(比方presto)和etl引擎(比方spark)是透明的,无法完成让olap引擎拜访某一个指定的副本(比方ONE_SSD战略的SSD副本)
✓ 数据生命周期的办理本钱高:假如要依据冷热做动态战略办理还有很多的作业要做
数据副本其实能够分红物理和逻辑层面来考虑:
1)物理两套,逻辑两套:需求面临两份数据办理的问题
2)物理一套,逻辑一套:难以处理IO阻隔的问题
在上面两种不可行的状况下,咱们自然地想到了另一个思路:
✓ 物理两套,逻辑一套?
而Alluxio恰好在这个思路上给了咱们一种或许性:
Alluxio的元数据能够完成跟HDFS的同步,有比较完善的共同性保证,所以能够理解为在Alluxio中的数据跟HDFS是一份逻辑数据。而依据数据冷热驱逐的自动化机制给更灵活的数据生命周期的办理供给了一条通路。
这样,结合数据的预加载,结合Alluxio的缓存特性,不只做到了无鸿沟的拜访中心存储的数据,同时也完成了热数据的IO阻隔和SSD加快。
但区别于更盛行的缓存加快的用法,咱们运用Alluxio的方式更倾向于IO阻隔
| Alluxio的缓存战略挑选
Alluxio的两种首要缓存战略
✓ CACHE : 经过Alluxio拜访后,假如不在Alluxio中,则会进行缓存,单位为block
✓ **NO_CACHE:**经过Alluxio拜访后,假如不在Alluxio中,不进行缓存
两种战略对应两种不同的存储办理计划:
【名词解释】
预加载查询:是经过olap运用体系挂号注册的剖析主题(对应库表),然后结构的简略聚合查询:select count(*) ,来触发Alluxio的数据加载。
终究考虑到长时刻的办理和运维杂乱度,咱们挑选了路径单一容错性更高的CACHE计划
新的应战
思路清晰了,可是仍是有三个应战:
1)怎样让Alluxio只运用于olap引擎,而防止修正公共hive元数据中的数据location
2)怎样防止一个随意的大规模查询导致其他数据被大面积驱逐?
3)异构存储机型下,咱们的缓存恳求分配战略怎样挑选?
| 应战一:怎样让Alluxio只运用olap引擎,而无需修正hive元数据?
由于alluixo的拜访schema是:Alluxio:// ,所以正常状况下运用Alluxio需求在hive中将对应表格的地址修正为Alluxio://,但假如那样做的话,其他引擎(比方spark)也会相同拜访到Alluxio,这是咱们不期望的。
得益于TEG 天穹presto团队的前期作业,咱们采纳的做法是经过在presto中添加一个Alluxio库表白名单模块处理。也便是依据用户拜访的库表,咱们将拿到元数据的地址前缀hdfs://hdfs_domain/user-path替换成了alluxio://allluxio_domain:port/hdfs_domain/user-path, 这样后续的list目录和获取文件操作都会走alluxio client,以此处理alluxio的独享问题。
别的关于商业版别的alluxio,还有一个Transparent URI 的特功用够处理相同的问题。
| 应战二:怎样防止随意的大规模查询导致其他数据被大面积驱逐
运用库表白名单,咱们完成了对Alluxio存储的数据的横向约束,可是仍然存在一个很大的危险便是用户或许忽然提交一个很大规模的查询,然后导致许多其他库表的数据被evict。
由于只要选用的是CACHE战略,只要数据不在Alluxio,就会触发Alluxio的数据加载,这时分就会导致其他数据依据evict战略(比方LRU) 被清理掉。
为了处理这个问题咱们采纳了下面的两个关键的战略:
✓ 依据时刻规模的库表白名单战略:
在库表白名单的横向约束基础上,添加纵向的依据分区时刻的约束机制,所以就有了咱们后面迭代的依据时刻规模的库表白名单战略,咱们不只约束了库表,还约束了必定的数据规模(一般用最近N天表明)的分区数据,然后再结合用户高频运用数据的规模,就能够确定一个库表比较合理规模。
下面是一个样例片段参考:
"dal_base.*",
"dal_base.*.${yyyyMMddHH:(-720h,0)}",
"dal_base.*.${yyyyMMdd:(-217d,0)}",
"dal_base.*.${yyyyMM:(-36m,0)}"
✓ 下降Alluxio worker异步缓存加载的最大线程数:
Alluxio.worker.network.async.cache.manager.threads.max 默许是2倍cpu核数,咱们基本上是调整成了1/2甚至是1/4 cpu核数,这样由于查询忽然添加的load cache恳求就会被reject掉,下降了对存量数据的影响。
这样咱们实际上便是构建了一个Alluxio的保护墙,让Alluxio在一个更合理的数据规模内(而不是全局)进行数据办理,提高了数据的有用性。
并且选用这样的战略,部分直接走HDFS的流量不管是耗时,仍是对Alluxio的内存压力都会有所下降。
| 应战三: 异构存储机型下,咱们的缓存恳求分配战略怎样挑选?
这个也是将Alluxio当作一个存储层,能够独立扩展必需求面临的,新的机型不必定跟本来的共同。面临异构 Worker 存储的需求,Alluxio已有的块位置选取战略,都会造成热门或许不均衡的问题,不能有用运用不同worker上的存储资源。比方:
✓ **RoundRobinPolicy、DeterministicHashPolicy:**平均战略,将恳求平均分配给一切Worker,会导致小容量的worker上的数据淘汰率更高;
✓ **MostAvailableFirstPolicy:**或许会导致大容量worker容易成为数据加载热门;并且由于一切worker存储终究都会抵达100%,所以满了之后这个战略也便是失掉含义了。
因此 咱们积极参与腾讯 Alluxio 开源社区,设计并贡献了“依据容量的随机块位置选取战略 CapacityBaseRandomPolicy”。
该战略的基本思想是:在随机战略的基础上,依据不同worker的容量给予不同节点不同的分发概率。这样容量更大的worker就会接收更多的恳求,配合不同worker上的参数调整,完成了均衡的数据负载。
如下图所示,是上线初期的容量状况,第一列是存储容量,第二列是运用容量,能够看到基本是按份额在增加。
除了上面的三个应战,咱们还对计划中的一个问题”presto触发查询会导致多副本问题”做了优化。由于presto的查询会将一个文件拆成以split为单位(默许64MB)进行并行处理,会在不同Worker上触发缓存,实际上会对数据产生多个副本。本来咱们运用DeterministicHashPolicy来约束副本数量,可是由于切换到了CapacityBaseRandomPolicy,咱们再一次对副本数失掉了操控。因此咱们做了如下两个优化:
✓ 预加载查询设置大split(max_initial_split_size,max_split_size):运用跟alluxio block size共同的split,比方256MB,这样防止一个文件被拆成多个split
✓ 对CapacityBaseRandomPolicy添加了缓存机制:防止了同一个worker屡次恳求发送到多个worker上,触发多个副本加载问题
终究架构
在落地进程中,为了满意实际存储需求,额外申请了SSD存储机型扩容了Alluxio worker,终究选用了 Presto + 腾讯 Alluxio(DOP) 混合布置以及独立布置 Alluxio Worker 的架构,即有的服务器同时布置了Presto worker和Alluxio worker,有的服务器仅布置Alluxio worker,该架构具有核算和存储各自独立扩展的才能。
线上运转作用
咱们依据某一作业日随机抽取了一批历史查询,5个并发,由于完全是随机的,所以查询触及的规模或许包含了部分必定不走Alluxio的数据(不在预设的白名单时刻规模,或许没有射中),可是能更实在反映咱们实际运用的作用。
测验咱们选取了两个时刻段:
1) 周末下午:500个查询,大部分ETL使命现已完成,HDFS大集群负载低,这时分首要看SSD加快作用。
2)作业日早上:300个查询,这个时刻点还会有许多ETL,画像标签、引荐特征等使命运转,HDFS集群繁忙程度较高,这个首要看IO阻隔性。
测验成果如下:
闲时:
图中的横坐标是按耗时从低到高排序后的500个查询(剔除了最大值213秒),纵坐标是耗时(单位秒),其间90分位的耗时有Alluxio和无Alluxio分别是16s和27s,90分位的查询功用提高为68.75%,这里首要是SSD带来功用提高。
忙时:
图中的横纵坐标如上一个图共同,横坐标是300个按耗时排序后的查询,注意:由于查询掩盖的数据规模或许超过Alluxio的数据规模,所以会呈现极端值。
作用总结:
从测验成果能够看到:
✓ SSD提速:即便在闲时对50%以上的查询都有必定幅度的提高作用,在90分位抵达了68%的功用提高。
✓ IO阻隔优势:能够看到HDFS忙时,无Alluxio的90分位查询会明显上升,可是有Alluxio的查询非常平稳,在90分位抵达了+294%的功用提高。
优化调优实践
| 选用腾讯 Konajdk + G1GC
腾讯 Alluxio(DOP) 选用 KonaJDK 和 G1GC 作为底层 JVM 和 垃圾收回器。KonaJDK 关于 G1GC 进行了继续的优化,相较于社区版别,针对腾讯内部运用特色进行了深度的优化,削减了GC暂停时刻和内存运用。
| 运用腾讯 Kona-profiler 定位高并发拜访 Alluxio Master FGC 问题
当呈现事务海量并发查询恳求场景,Alluxio Master 呈现了频繁 FGC 的状况,并且内存无法大幅收回,导致 Alluxio Master 无法正常供给服务,影响事务运用。
咱们获取了 JVM heap dump 文件,运用 kona-profiler 进行剖析。
运用 kona-profiler 快速发现问题的瓶颈在于:短时刻内呈现了很多未被开释的 Rocksdb 的 ReadOptions 目标,这些目标被Finalizer引用,说明ReadOptions目标能够被收回了,可是在排队做 finalizer 的函数调用,进一步定位发现,ReadOptions 目标的祖先类 AbstractNativeReference 完成了 finalizer 函数,其间的逻辑又过于杂乱,因此收回较慢,这在7.x 版别的 rocksdb 现已修复。
但由于版别晋级跨度过大,咱们选用另一种办法处理该问题。配置腾讯 Alluxio 的alluxio.master.metastore.block=ROCKS_BLOCK_META_ONLY,支撑把 blockLocation 独立放置于内存办理,而 block 信息运用 rocksdb 办理,这样从根本上防止了原本海量获取 block 位置操作,结构海量 rocksdb 的 ReadOptions 目标的问题。
晋级改造后。
Alluxio 侧,在压测的状况下,999分位从本来的 10ms 削减到了 0.5ms,qps 从 2.5w 提高到了6.5w;
正常负载下晋级前rpc排队状况:
正常负载下晋级后 rpc 排队状况:
Presto 侧:关于触及分区许多的查询场景,比方大规模的点击流漏斗剖析,在一个基准测验里,从 120 秒削减到了 28 秒,提高了4 倍。
| 周期性呈现50秒慢查询问题参数优化
一个查询屡次履行耗时差许多。大部分在7秒左右,可是会偶尔忽然添加到50秒,便是某个数据读取很慢,测验的时分集群的负载仍是比较低的。
下图是慢查询时 Presto 的调用栈
结合源码,能够看出此刻 Alluxio 客户端认为拿到的 BlockWorker 客户端是不健康的。
判别健康的断定规范为:不是 shutdown 状态,且两个通讯 channel 都是健康的。
依据上下文,能够判别,目前不是 shutdown 的,那么只能是两个通讯 channel 不健康了。
进一步结合源码,定位在 closeResource 进程中,会封闭并开释 grpcConnection,这个进程中会先优雅封闭,等待超时假如未能优雅封闭则转为强制封闭。
因此,躲避该问题,只需求修正调小配置项 alluxio.network.connection.shutdown.graceful.timeout 即可。
| Master data 页面卡住的问题优化
Alluxio Master 的 data 页面,在有较多 in Alluxio 文件的时分,会呈现卡住的问题。这是由于,翻开这个页面时,Alluxio Master 需求扫描一切文件的一切块。
为了防止卡住的问题,选用约束 in Alluxio 文件个数的处理办法。能够配置最多展现的 in Alluxio 文件数量。
总结展望
✓ 腾讯 Alluxio(DOP) 支撑 BlockStore 层次化,前端为缓存层,后端为耐久层,同时,blockLocation 这种不需求耐久化的数据,不需求实时写入后端耐久层,只需求在前端缓存层失效的时分才需求溢出到后端,该功用正在内部评测。
✓ 腾讯 Alluxio(DOP) 作为一个中间组件,在大数据查询场景,遇到的功用问题,在事务侧,需求事务团队不只对自身事务非常了解,对 Alluxio 也需求有必定的了解。在底层 JVM 侧,需求 JVM 专业的团队选用专业的技能进行协作处理,然后最大限度的优化,使得整体计划发挥最优的功用。
✓ 这是一次非常成功的跨 BG,跨团队协作,快速有用的处理腾讯 Alluxio(DOP) 落地进程中的问题,使得腾讯 Alluxio(DOP) 在金融事务场景顺利落地。
往期阅览