共计 6994 个字符,预计需要花费 18 分钟才能阅读完成。
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) 在金融业务场景顺利落地。