Hermes 是腾讯数据平台部自研的实时分析平台,在公司内服务于上百个业务,集群规模 5000 个节点,每日数据接入量 4 万亿,查询量千万级别。作为一个公共的平台,面对的业务场景非常复杂,包括在线高并发分析、即席交互分析、海量日志分析、实时接入数据和近实时增量更新。这样一个万亿级的实时计算开发引擎到底是怎么实现的?研发过程中遇到那些难点?作为开发者,我该怎么借鉴和避免;作为用户,又有哪些新的思考?
在 2021 年 4 月 22-24 日举办的 QCon全球软件开发大会(北京站)“大数据实时计算与分析“专题上,腾讯高级后台开发工程师邓启斌老师将分享《腾讯万亿实时分析引擎 Hermes 的实现与应用》,在会前 InfoQ 带着疑问对邓老师进行了采访。帮助大家了解高性能实时分析系统的底层技术实现原理,以及了解海量数据和大规模集群的实时分析平台的运营经验。
InfoQ:请介绍下自己?
邓启斌: 我是邓启斌 (kewndeng),腾讯大数据专家工程师。Hermes 实时分析平台的研发负责人,主导并负责了海量日志存储平台、智慧零售搜索引擎、Hermes 实时分析平台。目前 Hermes 团队聚焦于腾讯广告的实时 OLAP 分析,致力于提升查询分析性能和数据时效性,降低机器资源成本,并提升业务数据分析效能。
InfoQ:Hermes 研发的背景是?
邓启斌:Hermes 项目始于 2012 年,当时主要面向公司内的用户画像业务,提供多维分析、用户洞察、人群交叉等能力,让万级维度、千亿级数据下的秒级统计分析变为现实。
在 Hermes 1.0,数据通过离线的 MR 任务生成再同步到 Hermes,通常数据时效性是 T-1。但由于业务对数据时效性有越来越高的要求,譬如服务器日志、交易流水、安全风控需要以近实时方式入库和快速可查,于是在 2015 年研发 Hermes 2.0,业务把数据接入到 TubeMQ(腾讯大数据开源的消息中间件),再由 Hermes 进行消费,实现从数据接入到可查只需秒级的延迟。
而在面向海量数据的 OLAP 实时分析,业界没有通用高效的解决方案,为解决公司广告系统复杂分析场景,我们在 2019 年开始把重心放在分析型列存和计算引擎的研发,并推出了针对实时分析型业务的 Hermes 3.0。
而在我加入 Hermes 团队的时候,Hermes 2.0 已在中小规模的业务中使用,单个业务每天百亿到千亿的实时接入量。我的首个任务是优化写入、查询性能和可用性,从而支撑起了万亿级数据量的业务,实现了业务的规模化接入。
InfoQ:Hermes 能解决什么问题?
邓启斌: 通过前面 Hermes 背景的介绍,大家应该都了解到 Hermes 是应用于什么样的业务。下面我举三个案例让大家加深理解。
通过前面的采访,我们对 Hermes 有了一个比较直观的了解,正是因为知道 Hermes 是腾讯数据平台部自研的实时分析平台,面对的业务场景非常复杂。这样一个万亿级的实时计算开发引擎到底是怎么实现的?研发过程中遇到那些难点?
InfoQ:在研发 Hermes 过程中遇到了哪些让人头疼的问题,当时是怎么解决的。
邓启斌: 在实时分析的技术领域中,没有哪个项目在各个场景都是通吃的。业界的 ElasticSearch、Kylin、Druid、ClickHouse,分别在各自的细分领域做得很强大。在业务选型时 Hermes 经常被拿来跟它们进行对比,并挑战在性能上有哪些优势,功能是否更强大,为什么要用 Hermes?
因此,找准赛道是最让人头痛的问题,只有清晰认识到要做一个什么样的项目,才能决定使用什么样的技术,并持续把技术做好和做深。经过数年研发的演进,Hermes 具备了差异化的能力,在公司不少业务在遇到实时分析的落地难题时或走了弯路后找上门来。譬如腾讯视频用户画像,由于字段个数多而且标签个数不是固定的,因此需采用 schema-less 的引擎,业务原本使用 ES+ClickHouse,但遇到数据导入不稳定、查询维度或标签组合过多导致服务不可用,后来业务迁移到 Hermes,由于 Hermes 在该领域的成熟度,很轻易地解决了他们这些痛点,并且还原生地支持了他们用户包导入关联分析的产品需求。
另外,微信日志每天万亿的实时接入量,除了满足读写性能的要求,可用性要达到 4 个 9,机器资源成本是社区 ES 的一半。还有广告实验系统,业务原本使用一个自研的引擎,但是扩缩容不灵活、增加维度或维度基数膨胀后性能会急剧下降,已不能满足后续的业务增长的预期和实验系统的设计,因而促使业务迁移到 Hermes,当时经过测试性能提升 10 倍,后面业务还上线了一些广告维度的指标,如 adjust_cost、超收欠收比、空耗率等,这些在过去都只能通过离线方式计算。
至于实时分析系统相关的技术,大家容易想到的包括 SQL 编译优化、CodeGeneration、向量化计算、列式存储、分布式缓存,几乎各个引擎都用到了,但在实践过程中细节才是魔鬼。譬如我们在做数据缓存的时候,由于 Hermes 是用 Java 实现的,所以应该用堆外内存来做缓存,避免 GC 所带来的压力。但我们实现下来后,发现数据从堆外拷贝到堆内存产生消耗不可忽视,并且跟数据量成正比的。而在海量数据的分析场景中,这些消耗会非常突出,是不能接受的。于是我们采用了全链路堆内内存复用的方案,其中在向量化计算模型中,数据扫描和计算都以固定大小的 page 为单位,每个 page 复用内存进行传递和计算,对内存使用和 GC 压力的优化是十分显著的。
又譬如列存里的稀疏索引,通常业界采用统计信息,如 max、min、null num 等,但在查询分析时这些统计信息很难被应用上,因此需要研发适合在大数据场景的更细粒度的索引,但这些细粒度索引提升查询性能,同时增加内外存的空间,导致机器资源成本比其他竞品要高,受到业务和运管的挑战。但通过对数据特性的挖掘和和技术实验,最终使用 LZ4+BitShuffle 压缩技术使存储空间降低 50%,且对查询性能无损;另外通过对冷热数据索引降级,以释放 25% 的存储空间。
对于邓老师来说,他们在研发过程中的坑,首先是要找准赛道,然后才是往技术深处走;往技术深处走的时候,发现数据从堆外拷贝到堆内存产生消耗不可忽视,然后开始采用了堆内内存复用的方案,结合向量化的计算模型去解决。我们从别人的实践中,总是能发觉一些可以借鉴的点;对于邓老师团队来说,还是有很多架构实现的经验给到大家。
InfoQ:Hermes 技术架构的实现过程中,你认为有哪些关键因素?
邓启斌: 对非在线的数据分析业务来说,易用性和稳定性是非常重要的,甚至高于性能的体验。
而索引和列存是实时分析性能的基石,根据我们多年运营经验的总结,大多数的业务之间的数据和分析场景是有共性的,从而对它们的查询模式和资源消耗进行抽象设计,实现了多种类型的索引和列存,包括低基数列存、压缩型列存、并发型列存,以及跳表索引、倒排索引、主键索引和 LBS 索引等,做到对大部分业务场景的覆盖,满足业务的功能和性能要求。
InfoQ:在 Hermes 研发过程中,有哪些经验你想和大家分享。
邓启斌:
通过对 Hermes 实时分析平台的研发背景的了解,以及研发过程中的坑的具体分析,作为开发者,你该怎么借鉴经验和避免研发过程中的坑呢?作为用户,你又有哪些新的思考?
领取专属 10元无门槛券
私享最新 技术干货