Fork me on GitHub

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

以下文章来源于 https://zhuanlan.zhihu.com/p/607128197

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

文章将包括以下几大部分:

  1. 业务背景

  2. Alluxio 方案

  3. 运行效果

  4. 优化调优

  5. 总结展望


分享嘉宾|毛宝龙 腾讯 高级工程师

编辑整理|卢梦桃 巴斯大学

出品社区|DataFun


01/业务背景


首先介绍一下业务背景。

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

  • 第一个是基于 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 的机器没办法承担那么大的缓存的资源量,缓存容量受限那么缓存的能力也就受限了。所以我们希望是混合部署,加上分离部署。

--

02/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 在高并发的时候,会被分配到多个 worker 上,那就会产生很多的副本。



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

--

03/运行效果


下面展示一下运行效果。



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

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

--

04/优化调优


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



首先我们采用了腾讯的 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 的这样一些数据给它在页面展现出来,只是展示一部分,如果想要更多,那么去做动态更新这样的一个配置阈值就可以了。

--

05/总结展望


最后进行一下总结。

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

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

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

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


分享嘉宾

毛宝龙|腾讯TEG数据平台部数据中心 高级工程师

毛宝龙,腾讯高级工程师,Alluxio PMC & Maintainer,Apache Ozone committer,腾讯 Alluxio OTeam 开源协同团队负责人。主要负责腾讯 Alluxio 的研发和落地工作和 Apache Ozone 的文件系统方向的研发工作。


《数据智能知识地图》下载

上下滑动⬆️⬇️,查看《数据智能知识地图》数据中台模块,完整版请关注公众号"大话数智"下载


DataFun新媒体矩阵


关于DataFun

专注于大数据、人工智能技术应用的分享与交流。发起于2017年,在北京、上海、深圳、杭州等城市举办超过100+线下和100+线上沙龙、论坛及峰会,已邀请超过2000位专家和学者参与分享。其公众号 DataFunTalk 累计生产原创文章900+,百万+阅读,16万+精准粉丝。


本文地址:https://www.6aiq.com/article/1676810486698
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出