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) 在金融业务场景顺利落地。