腾讯Alluxio(DOP)在金融场景的落地与优化实践

大数据 数据分析
本文将分享腾讯 Alluxio(DOP)在金融场景的落地和优化实践。DOP 全称为 data orchestration platform,数据编排平台,是腾讯内部 Alluxio 及其生态产品组成的一个大的产品。

一、业务背景

首先介绍一下业务背景。

在腾讯金融场景中,数据分析主要有两大入口:

  • 第一个是基于 SQL 的分析平台产品——idex;
  • 另外一个是图形化的分析产品——“全民 BI”。全民 BI 是一款类似于 tableau 一样,可以通过拖拉拽的方式进行数据探索分析的工具,因为不需要编写 SQL, 所以面向人群更广,不仅包括数据分析人员,还有产品、运营等等,对耗时敏感度也会更高。本次主要介绍全民BI。

为支持日益增长的各类分析场景,今年腾讯金融业务数据团队进行了大的架构升级,引入了 Presto 加上腾讯 Alluxio 的架构,用来满足用户海量金融数据的自由探索需求。

图片

​在大数据 OLAP 分析场景中,我们面临的挑战有以下两个:

首先,既要满足数据的快速增长,又要更快的数据探索性能,还要成本低。虽然这些年 SSD 的性能还不错,但现在HDD 还是有很大的市场。比如在中央存储系统中,由于数据量巨大,全换成 SSD 成本会难以接受。

第二个挑战是在多种计算任务的 workload 当中 ,OLAP 分析的性能如何在 IO 瓶颈中突围。常见大数据计算的两种负载就是 ETL 和 OLAP。OLAP 主要是用在对数据的多维度分析上,特点是仅涉及少量的数据列,但可能涉及较大的数据范围。虽然 ETL 的峰值可能在凌晨,但是其实白天也会有各种各样的任务在不断的执行,这两种任务的负载会相互影响,再加上中央存储的底层是硬盘,所以其 IO 性能会受到硬盘的约束。所以对于 OLAP 分析的特点,硬盘的 IO 是随机碎片化的, SSD 更适合。​

图片

​针对上述挑战,一种比较流行的解决方案为,把需要的热数据复制到专用的存储当中,这样可以解决 IO 的竞争问题。就比如有一个中央的 HDFS,又搭建了一个 HDFS,把里边的数据拷到这个搭建的 HDFS 中,这样 IO 就天然隔离了。

小的集群里面存储的都是热数据,所以其实也可以用 SSD 进一步加速 OLAP 性能。但是这样又会引来一些新的问题,比如数据的边界问题,以及数据认证鉴权一致性的问题。​

数据的边界问题:因为数据需要提前复制,如果需要临时分析超出约定范围的数据,就会导致只能降级到中央存储上面去执行查询,这样不仅涉及到存储的切换,也涉及到计算引擎的切换。

数据认证鉴权一致性问题:因为要复制到另一个存储系统,就可能存在一致性问题,另外数据的属主、permission mode , 以及认证鉴权方式等都要完全一样才行。对于金融这样一个强监管行业,不能出一点差错。

显然这个方案无法解决我们的问题,所以我们就采用了另外一种解决方案:Alluxio。

图片

Alluxio 需要满足两个需求。如上图所示,因为 Alluxio 是一个中央存储的透明缓存层,拥有完整的中央存储文件系统的视图,文件的权限属主以及认证鉴权的策略都是与底层一致的,并且可以采用 SID 或内存盘作为缓存热数据集的介质。这样 IO 也隔离了,性能也高了,并且数据的认证和鉴权也都是一致的。所以我们认为它是一个更好的解决方案。

Alluxio 有两种使用方式:

  • 一种是倾向于使用 Alluxio 的缓存加速,把 Alluxio 跟计算引擎亲和性地部署在一起,可以换取更好的 IO 本地性,从而提升性能。
  • 另外一种使用方式是更看中 IO 隔离的特性。不一定把Alluxio和计算做一个完全亲和本地性的部署,也可以做分离的部署,这样可以独立的扩展。如果是1比1的时候,其实受限于机器上面的资源,比如 SSD的大小,可能 Alluxio 的机器没办法承担那么大的缓存的资源量,缓存容量受限那么缓存的能力也就受限了。所以我们希望是混合部署,加上分离部署。

二、Alluxio 方案

图片

​引入 Alluxio 面临的第一个挑战是,我们只想把 Alluxio 用于 OLAP 引擎,不想修改 HIVE 的元数据,我们由 Pretro 团队去做了一些改动,改动的思路就是引入了一个 Alluxio 库表的白名单模块,相当于做了一个路径的转换。然后就可以在用户无感,并且 HIVE meta store 里边也没有太多改动的情况下,就可以把一些特定库表的一些访问走到Alluxio里边,而一些较大的库表或者不需要缓存加速的,就不走 Alluxio 这里边了。

另外,作为 Alluxio 开发团队,我们开发了 Alluxio(DOP)自适应客户端功能。把 Presto 做的所有事下沉到 Alluxio 这个客户端里边。不光是 Presto, Spark、 Flink 等其它计算引擎,想去用这样的一个黑白名单,或者限制一些表按时间范围等,都可以接到自适应客户端里边。​

图片

​第二个挑战是避免随意的大范围查询导致其他数据被大面积驱逐。我们之前使用白名单对 Alluxio 存储的数据有一个横向的限制,但是依然会有这样的风险,就是用户可能突然提交一个很大范围的查询,进而导致很多其它库表的数据被清理掉。因为我们采用的是 CACHE 读策略,所以只要是数据不在 Alluxio 里面,就会触发 Alluxio 的数据加载,就会导致其它的数据被清理掉。

为了解决这个问题,我们又采用了以下两个关键的策略。第一个是基于时间范围的库表白名单策略,在库表白名单的横向限制的基础上,又增加了一个纵向的基于分区的时间的限制机制。上图中所示的几个片段就是这个意思。第二方面就是降低 Alluxio worker异步缓存加载的最大线程数。默认情况下, async.cache.manager.threads.max 默认是 CPU 的 2 倍,这个可能还是太大了,所以我们把它调成 1/2 的 CPU 或 1/4 的 CPU 。这样查询突增的 load cache 请求就会被 reject ,这样就可以降低对存量数据的影响。

这样实际上就是为 Alluxio 构建起了一个保护墙,让 Alluxio 在更合理​的数据范围内进行数据的管理,而不是全局的,从而提升了缓存的利用率。而且采用这样的策略部分直接走 HDFS 的流量,不管是耗时还是对 Alluxio 内存的压力都会有所降低。

图片

第三个挑战是异构存储机型,缓存请求分配策略如何选择?我们现在就是异构的机型,有一些是混部的,有一些是分开的,就是独立的 Alluxio 的 worker。

这种情况下 Alluxio 已有的一些块选择策略就不适合了。比如 RoundRobinPolicy 和 DeterministicHashPolicy 都是均衡策略。

第一个是把请求转圈的分配给所有 worker,另外一个是按照 block ID 做一个哈希散列分配到所有的 worker 上。对于同样配置的缓存节点其实还是可以的,但是异构机型场景就不适合了。因为有的存储容量大,有的存储容量小,对于存储容量较小的 worker 其数据淘汰率就会更高。这样就无法使所有 worker 在同样的繁忙度上去运行。

另外一个是 MostAvailableFirstPolicy ,这也是一个在很长一段时间都非常流行的策略。是选择在剩余空间较多的 worker 上面去读数据。这会导致一开始请求就会堆积到大容量的 worker 上,分配就不均衡了,其它的 worker 都闲着,但是要把所有的 worker 全都灌满以后,那 most available也就失去意义了。

​所以腾讯设计贡献了一个基于容量的随机块选择策略。这里有两个关键词,一个是基于容量,另一个是随机。就是根据 worker 的容量,给不同的 worker 分配不同的分发概率。这个概率是随机的。我们做了一个测试实验,可以看到,异构的情况下,worker的使用量和总空间量都是按照一定比例去增长的,还算比较均衡。

另外为了优化pretro 查询导致多副本的一个问题。我们设计了CapacityBaseRandomPolicy。有某一个块已经分配给某一个 worker 了,那接下来再来到这个客户端上,还要对这个块做一个读请求,那还是会分配到那个 worker 里边,因为我们已经缓存了这个块跟 worker 位置的一个映射。这样就避免了同一个 block 在高并发的时候,会被分配到多个 wo​rker 上,那就会产生很多的副本。

图片

上图是最终的方案, Presto + Alluxio 混合部署的集群,并且额外申请了带 7T SSD 的一些机器作为 Alluxio 的 worker ,这个架构就具备了存储和计算独立扩展的能力。

三、运行效果

下面展示一下运行效果。

图片

这个测试并没有像以往一样找一些基准测试,而是采用真实的某一个工作日线上的执行查询的一些历史,我们把这个历史作为一些回放,是完全随机的。这样更靠近真实场景,因为完全随机的时候可能会有一部分不一定走 Alluxio 里边,我们可能限定了有些查询是走底层的,可以综合的去看其性能。

测试的时候我们选了两个时段,第一个是周末下午,500 个查询。这个时段是一个闲时。HDFS 大集群负载也比较低,这个时候考察的就是 SSD 的加速能力。第二个是工作日的早上,属于忙时,300 个查询,在这一时段, ETL 、画像标签、推荐、特征等任务都在执行着,所以 HDFS 集群繁忙度还是比较高的,这时主要考察的是 IO 的隔离性。测试结果如上图左下表格所示,可以看到,闲时有 68% 的性能加速,而忙时有 300% 左右的性能加速。

四、优化调优

最后介绍一下我们的优化实践。

图片

首先我们采用了腾讯的 KonaJDK 加上经过腾讯优化的 G1GC。我们只是将底层的 GM 下的一些基础设施换成了腾讯 KonaJDK + GGC。我们就看到 GM 还有平均的一些延时都降得很低,性能表现都特别好,这里非常感谢 GM 团队给我们的支持。

图片

这里分享一下我们解决的一些问题。

​第一个是我们采用 KonaJDK 中的一个工具 Kona- profiler 来定位了高并发访问 Alluxio master FGC 的问题。当来自业务的海量的请求一块到来的时候,Alluxio master 的 Java 虚拟机的垃圾回收器出现了一个现象,就是回收对象的速度跟不上创建对象的速度,那最终会导致 OOM 。我们用 Kona-profiler 做了一个分析,这个分析的输入就是 OOM 的时候出现的一个 hip dump 文件。最后我们得到了上图所示的一个饼图,一个对象的分布图。可以看到大部分的都是 finalizer 这样一个对象。

一个小知识, Java 的对象在被回收的时候,都是在最后一刻会被调用该对象的 finalizer 的这样一个方法。finalizer 本身是 object 对象的一个方法,所有的是空实现,所有底下的一些类都不需要实现,但是现在却看到了这个Finalizer方法被调用,所以显然是有一些类实现了这个方法,并且实现比较耗时。进一步去看,所有的类或对象的引用关系,最后找到了 rocksdb 中的 ReadOptions 对象,它的祖先类里面确实是重写了这个函数,并且逻辑也过于复杂,还会调 native 还会调回​来,所以拖慢了对象的回收速度,7.0 以后版本已经修复了。但我们当时用的是 6.X 版本,所以我们的一个思路是把 rocksdb 升级。

另外一个思路,是去定位它为什么要去这么高频的调这个 ReadOptions 对象,把它创建出来,最后又释放掉。通过看 Alluxio 相关的一些代码,我们找到了原因是底层的块 block store 用的是 rocksdb,rocksdb 存的有两项,第一个是 block 的 meta, 第二个是 block 的 location。而 block location 这个位置信息在去查询他们的时候要有一个前缀匹配,就要把 ReadOption打开。我们的 block location 并不多,因为在这种 OLAP 查询底层的这些数据都是大块的,缓存容量也是有限的,一个 Alluxio 集群里,容量这么大,如果都存满了存的 block location 也不会过亿,我们把它都放在内存里边也没有问题。所以我们就将 block location 放到内存里边,而 block meta 以及inode 等是放在rocksdb。基于这一优化,耗时从 120 秒减少到 28 秒。因此通过一些 GM 调优工具,是可以看到性能的瓶颈的,也可以从根本上去解决问题。

图片

另外一个问题是慢查询。大部分查询都是7秒,周期性会出现 50 秒的慢查询。我们定位问题,发现是 client 与 worker 连接不畅导致一个叫优雅关闭的时间设置的太久了。这个默认值是 45 秒,只需要缩小就可以了。

图片

另外一个就是 master data 页面卡住的问题。如果往里边缓存了特别多块的时候, master 页面后台的逻辑是扫描所有的 inode 里边所有的 block, 看看哪些 block 都在内存里,然后展示出来。这个页面打开就太慢了。现在优化这个问题不光是因为页面打不开,而是它把 Alluxio 性能也都拖垮了。

所以我们开发了一个能力,就是在默认情况下不把所有的 Alluxio 的这样一些数据给它在页面展现出来,只是展示一部分,如果想要更多,那么去做动态更新这样的一个配置阈值就可以了。

五、总结展望

最后进行一下总结。

腾讯 Alluxio(DOP)支持 BlockStore 层次化,前端为缓存层,后端为持久层,同时,blockLocation 这种不需要持久化的数据,不需要实时写入后端持久层,只需要在前端缓存层失效的时候才需要溢出到后端,该功能正在内部评测。

腾讯 Alluxio(DOP)作为一个中间组件,在大数据查询场景,遇到的性能问题,在业务侧,需要业务团队不仅对自身业务非常了解,对 Alluxio 也需要有一定的了解。在底层 JVM 侧,需要 JVM 专业的团队采用专业的技术进行协作解决,从而最大限度的优化,使得整体方案发挥最优的性能。

Alluxio 之所以能够在我们现有的金融场景里边落地,是很多个团队一起协作,一起去努力的。所以要感谢兄弟团队们给予的支持。

今天的分享就到这里,谢谢大家。

责任编辑:姜华 来源: DataFunTalk
点赞
收藏

51CTO技术栈公众号