从 Spark 到 StarRocks:实现58同城湖仓一体架构的高效转型

作者:王世发,吴艳兴等,58同城数据架构部

导读:

本文介绍了58同城在其数据探查平台中引入StarRocks的实践,旨在提升实时查询性能。在面对传统Spark和Hive架构的性能瓶颈时,58同城选择StarRocks作为加速引擎,增强数据湖的分析能力。在迁移过程中,团队克服了多个兼容性问题,并对系统进行了稳定性和易用性的改进,特别是在Java UDF支持和SQL黑名单功能方面。

项目实施一年多以来,58同城取得了显著的成果:

  • 日均迁移SQL数量约 6.5 万条 ,查询成功率稳定在 98% 以上

  • 查询性能较迁移前提升 20 倍以上 ,平均查询时间缩短至 3.3 秒 ,P90查询时间为 5 秒

1 背景

“数据探查平台”是 58集团统一的 SQL 开发平台,旨在提供一个便捷的环境,让用户能够轻松编写、调试和执行 SQL 查询,并实时查看结果,每天超过10万+SQL 运行,包括 ETL,AdHoc 等场景,针对存储在 HDFS 上的海量数据查询,其底层执行引擎是由我们数据架构部门来提供的技术支持。

1.1 执行引擎原有架构

在引入 StarRocks 引擎之前,针对存储在 HDFS 上的海量数据查询,底层执行引擎的整体架构如下:

图片

在该架构下,大部分的探查 SQL 是通过 Spark 来执行的,少部分查询会路由到 Hive,查询响应时间整体在分钟级,随着公司对降本增效需求的日益增长,这已经无法满足即席查询(Ad-Hoc)对快速响应时间的要求,因此 Ad-Hoc 查询加速就成为亟待解决的问题。

1.2 探查场景引入 StarRocks 引擎

经过深入调研与评估后,我们最终选择了 StarRocks 作为我们数据探查场景的加速引擎,主要基于以下几个原因:

  • 统一数据湖分析能力: 我们只需要简单的创建一个 Hive Catalog,即可实现无缝衔接查询 Hive 表的数据,无需经过复杂的数据预处理。

  • MPP 框架与向量化执行引擎: 可以大大提升 Ad-Hoc 查询速度,综合官方基准测试结果及我们内部 POC 测试结果,使用 StarRocks 引擎,可以将查询性能提升 10 倍以上。

  • 架构简洁: StarRocks 架构简洁,运维成本较低。

引入 StarRocks 引擎后,数据探查执行引擎的整体架构如下:

图片

当有查询请求到来时,Kyuubi 会首先根据路由规则判断是否可以使用 StarRocks 执行。如果查询满足 StarRocks 的执行要求,我们将优先使用 StarRocks 进行处理。如果在 StarRocks 执行期间遇到异常情况,系统会自动降级到 Spark 执行,以确保用户的查询结果不会受到影响。

我们的整体目标是尽可能多地将数据探查 SQL 透明地迁移到 StarRocks 引擎,并且该过程对用户来说是无感知的,下文将围绕探查 SQL 迁移到 StarRocks 引擎过程中,遇到的一系列问题及其解决方案展开详细讲解。

2 StarRocks 兼容 Spark 改造

在推进探查 SQL 迁移过程中,遇到的最主要的问题就是 StarRocks 与 Spark 查询结果不一致的问题。为了确保迁移过程对用户透明无感知,我们就需要对 StarRocks 进行改造,使其能够兼容 Spark的执行逻辑。

虽然不同查询引擎在架构上存在差异,但概括起来 SQL 语句的执行流程无外乎如下几个步骤:

图片

而在我们迁移过程中遇到的 StarRocks 与 Spark 不兼容问题,基本上贯穿了上面整个执行流程,下面我将按照上述执行流程,依次讲解每个环节中我们发现并解决的不兼容问题。

2.1 语法解析阶段

语法解析阶段主要工作是将查询语句转化成语法树,在这个阶段我们遇到的主要问题就是语法不兼容问题,概括起来包括以下两类问题:

  • 语法不兼容问题

在迁移过程中,语法不兼容问题是比较常见的问题。对于一些相对容易解决的问题,我们通过直接修改 StarRocks 源码来向 Spark 兼容。例如,Spark 对表别名的大小写不敏感,而 StarRocks 则是大小写敏感的。针对这种情况,我们对 StarRocks 源码进行了相应的修改。

对于另一部分语法不兼容问题,我们是通过在 FE 端集成 SQLGlot 插件修复的,该插件能够实现查询语句在不同的 SQL 方言之间相互转换。例如,一些标识符如 key、show、system、group 等,在 Spark 中是可以在 SQL 语句中直接使用的,但在 StarRocks 中会被识别为关键字,无法直接使用。通过 SQLGlot 插件,可以将 SQL 语句中的这些标识符都加上反引号(`),从而使其在 StarRocks 中可以正常执行。

  • 语法不支持问题

对于 Spark 的一些高阶语法,如 LATERAL VIEW 语法、GROUP BY ... WITH CUBE 语法以及 GROUP BY ... GROUPING SETS(...) 语法,StarRocks 社区版本目前尚不支持,但是在我们的线上业务中,这部分语法的使用还是很频繁的。针对这些问题,我们扩展了 StarRocks 的能力,使其能够支持这些语法。

2.2 元数据绑定阶段

在元数据绑定阶段,主要工作是将 SQL 语句中的标识符(如表名、列名等)与数据库的实际元数据进行关联。在这个阶段,我们遇到的主要问题是由于 StarRocks 的 Hive Catalog 默认开启了元数据的缓存,导致的查询结果不一致问题。

例如,当 Hive 表的某个分区数据被重跑后,StarRocks 在一段时间内无法感知到分区元数据的变更,从而导致查询结果不一致。

针对这一问题,经过综合分析后,我们最终决定关闭了 Hive Catalog 的所有元数据缓存功能,这一决定看似简单粗暴,但主要基于以下两点考虑:

  1. 我们当前所做的工作是将一部分原来由 Spark 执行的查询迁移到 StarRocks 上执行,而 Spark 本身也并不缓存 Hive 表的元数据,因此即使关闭了 Hive Catalog 的元数据缓存功能,也并不会增加 Hive MetaStore 的整体访问量。

  2. 当前我们线上业务的查询并发并不高,缓存元数据并不会带来显著的收益。相反,如果开启了元数据缓存,并且查询了一些分区数很多的 Hive 表(一般为多级分区表),后续元数据缓存功能会周期性的刷新缓存中的元数据,这样反而会增加 Hive MetaStore 的负担。

2.3 查询优化阶段

在查询优化阶段,主要工作是基于 RBO(基于规则的优化)和 CBO(基于成本的优化)对执行计划进行重写,以获取最优的执行计划,提高查询性能。在这个阶段,遇到的主要问题是隐式转换问题。

在 RBO 规则中,有一类隐式转换规则,可以在优化查询时自动进行数据类型转换。例如,假设有一个分区表 t1,分区字段 dt 为字符串类型。如果用户在查询 t1 表时使用数值类型的分区过滤条件,如 where t1.dt = 20241201,那么针对这种不规范的用法,Spark 和 StarRocks 都会使用各自的隐式转换规则进行数据类型转换。

针对这类问题,我们系统的梳理了 Spark 和 StarRocks 在各类表达式中的隐式转换规则,并将StarRocks 的隐式转换规则与 Spark 进行了兼容,基本上彻底解决了这一类问题。

2.4 查询执行阶段

在查询优化阶段结束后,会生成一个由各种算子构成的查询计划树,在查询执行阶段,主要工作是在执行端执行这一系列的算子,例如 Scan 算子负责从存储层读取数据,Expr 算子负责进行表达式计算。在这个阶段遇到的兼容性问题也是最多的,概括起来主要包括如下两类问题:

text 格式的 Hive 表兼容性问题

在我们的生产环境中,有相当一部分 Hive 表使用的是 text+lzo 存储格式。针对这种存储格式,StarRocks 支持的并不完善,例如,早期 StarRocks 版本不支持查询 lzo 压缩的 text 格式的 Hive 表。为了解决这个问题,我们与 StarRocks 社区积极合作,扩展了 StarRocks 对 text+lzo 存储格式的支持。

另外,对于 text 格式的 Hive 表,StarRocks 社区版本也不支持查询 Map 类型的字段,我们也扩展了StarRocks 的能力,使其能够支持对 Map 类型字段的查询。

除此之外,我们还遇到了一些其他的兼容性问题,例如:

  • hive 表字段分隔符问题: 在某些特殊情况下,StarRocks 在处理 Hive 表字段分隔符时与 Spark 存在不兼容的情况。

  • 临时文件处理问题: StarRocks 在查询 Hive 表时没有忽略存储目录下的临时文件。

  • 空文件处理问题: StarRocks 在解压缩空文件时会抛出异常。

针对这些问题,我们都一一进行了修复,确保了 StarRocks 能够正确处理这些特定的场景。

函数不兼容问题

函数不兼容问题也是我们在迁移过程中花费最多精力处理的问题。具体又可以细分为以下两类:

  1. Spark 与 StarRocks 都有相同功能的函数,但是函数名称不同

这类函数处理起来比较简单,只需要在生成执行计划时,将 Spark 中的函数映射到 StarRocks 具有相同功能的函数即可。

  1. Spark 支持但 StarRocks 不支持或不兼容的函数

对于这类问题,我们采取了两种方式进行处理:

  • 逻辑简单的函数 :我们通过借助 StarRocks Java UDF 功能,创建 UDF 并在生成执行计划时将这些函数映射到自己实现的 Java UDF 函数来解决。

  • 逻辑复杂的函数 :我们直接修改 StarRocks 相关函数的代码,使其兼容 Spark 函数的处理逻辑。

通过以上方法,我们共计解决了 40 多个不兼容的函数,主要涉及日期处理,字符串处理,正则匹配,聚合函数等函数,基本上彻底解决了生产环境中存在的函数不兼容问题。

3 实践经验总结

在使用 StarRocks 的过程中,我们从实践中总结出了关于性能、稳定性和易用性的关键经验。

3.1 性能

我们的 StarRocks 集群开启了 Data Cache 功能,以提升查询性能。整体表现令人满意,但在个别场景中,查询性能受到 HDFS DataNode 慢节点问题的影响,出现了性能长尾现象。

针对这一问题,我们采用了自研的 HDFS 功能。当系统检测到某个 DataNode 响应缓慢时,会自动切换至其他副本读取数据。为实现这一功能,我们替换了 StarRocks 依赖的 HDFS JAR 包。经过优化后,系统的 P99 查询性能提升了 25%,效果显著。

3.2 稳定性

在项目初期,我们使用的是 StarRocks 3.0 版本,我们遇到了一些挑战,例如 FE 卡死或 BE 节点偶发性异常等。通过与 StarRocks 社区的积极交流,我们获得了社区的大力支持,并在升级至 StarRocks 3.2 后,整体系统的稳定性有了明显的提升。

其中,一个值得分享的案例是关于 CBO 统计信息的问题。在查询一张包含 3565 列的大宽表时,CBO 优化器会生成一个较大的 SQL 来获取统计信息,这可能导致 FE 内存占用过高,影响集群的正常运行。

针对这一情况,我们优化了相关逻辑,跳过了部分非必要的统计信息查询。这一改进有效降低了查询负载,同时进一步提升了系统的稳定性。

注意:稳定性问题在最新版本已优化。

3.3 易用性

为提升系统的操作便利性,我们对以下功能进行了优化:

  • Java UDF 支持从 HDFS 下载 JAR 包

增强了 UDF 功能,使 JAR 包可通过 HDFS 下载,简化了运维流程。

  • SQL 黑名单持久化

改进黑名单存储方式,实现多节点同步和持久化,降低了运维成本。

4 StarRocks 上云

4 .1 背景

为了进一步推进公司的降本增效战略,我们部门与 58 云平台团队进行通力合作,决定将一部分大数据组件迁移到 58 云平台。而对于 StarRocks 本身来说,数据探查场景主要借助其数据湖分析能力查询 Hive 表数据,集群本身是无状态的,并不会存储数据,天然就适合上云,因此我们决定将数据探查场景的 StarRocks 集群上云。

然而,由于各种情况的限制,上云使用的宿主机每台只能提供最多 5CORE 15GB 的资源。这给 StarRocks 的上云之路带来了一些挑战。

4 .2 上云架构

图片

上图为 StarRocks 云集群的整体架构:

  • 由于每个容器使用的资源限制在 5CORE 15GB,而 FE 节点需要存储集群的元数据,对内存资源要求较高,因此FE节点我们并没有上云,仍然使用物理机部署。

  • BE 集群只是为了存储审计日志表数据,需要开启云集群本地存储,只部署了少量实例。

  • CN 集群是主要的计算节点,无状态,支持快速的扩缩容。

4 .3 面临的挑战

上云过程中遇到的最大挑战就是容器内存资源不足,这导致 CN 节点容器频繁发生 OOM,被操作系统杀死。为了解决这一问题,我们采取了以下措施:

1 设置资源组隔离及查询队列

通过设置资源组隔离和查询队列,控制查询并发,确保资源的合理利用。

2 开启中间结果落盘功能

开启中间结果落盘功能,将部分计算结果暂存到磁盘上,从而降低内存消耗。

3 减少 CN 进程执行 线程数

CN 进程中有一些与执行线程数相关的参数,默认值通常设置为机器 CPU 的核数。而在容器环境下,CN 进程识别出的 CPU 核数是宿主机整体的 CPU 核数。因此,我们需要根据容器的实际资源配置手动调整这些参数。

4 限制 CN 进程 JVM 内存

在使用 StarRocks 数据湖分析能力查询 Hive 表场景下,有一部分功能是通过 JNI 来实现的,例如读取 HDFS 文件,还有就是一些 JAVA UDF 的使用。然而,由于 JVM 默认堆内存的上限是根据物理机的内存自动设置的,这种默认行为并不适配容器化环境。因此,需要通过设置 CN 进程的 JAVA_OPTS 参数 来限制 JVM 内存的使用,从而确保 CN 进程 的整体内存消耗不会超出容器的内存限制。

通过采取以上一系列措施,基本上解决了因容器内存溢出导致的系统不稳定问题。

5 整体收益

项目实施一年多以来:

  • 目前日均透明迁移到 StarRocks 集群的有效 SQL 数量约为 6.5W 条。

  • 路由到 StarRocks 集群的 SQL,整体查询成功率稳定在 98% 以上。

  • 已迁移的 SQL 中,平均查询时间在 3.3s 左右,P90 查询时间在 5s 左右,P99 查询时间在 52s 左右。

图片

  • 与迁移前相比,平均查询性能提升了 20 倍以上,查询体验得到了很大的提升。

图片

后续我们也将不断进行迭代,持续发现并解决 StarRocks 与 Spark 的兼容性问题,使得更多的 SQL 能够透明地迁移到 StarRocks 集群。

6 后续规划

统计发现,在我们的数据探查场景中,有相当一部分 SQL 是直接对明细表进行聚合和关联查询,并没有经过数仓建模。这种查询方式不仅效率低下,而且类似的复杂查询重复执行也在很大程度上浪费了计算资源。

如果能够根据这些类似的复杂查询自动提取出公共子查询来创建物化视图,并借助 StarRocks 的物化视图透明改写能力,就可以有效解决这一问题。

事实上,我们已经在进行智能物化视图方面的探索,并将持续关注社区在这方面的进展,尽快完成智能物化视图能力的落地,以助力降本增效战略的持续推进。

更多交流,联系我们:StarRocks

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探秘 Linux 进程状态:解锁系统运行的密码

🌟 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。🌟 🚩用通俗易懂且不失专业性的文字,讲解计算机领域那些看似枯燥的知识点🚩 在 Linux 系统…

深度学习-89-大语言模型LLM之AI应用开发的基本概念

文章目录 1 什么是智能体(Agent)2 什么是大语言模型(LLM)2.1 LLM的训练及使用2.2 Transformer架构2.3 基于LLM的Agent框架3 什么是检索增强生成(RAG)3.1 RAG是什么3.2 生成式AI应用开发3.3 RAG的整体流程3.4 RAG技术3.4.1 简单RAG(Simple RAG)3.4.2 校正RAG(Corrective RAG)3.4…

鸿蒙产业学院正式揭牌!软通动力与深信息签署校企合作框架协议

12月27日,深圳信息职业技术学院(简称“深信息”)与软通动力信息技术(集团)股份有限公司(简称“软通动力”)正式签署校企合作框架协议,并共同揭牌成立鸿蒙产业学院。深信息校长王晖&a…

python轻量级框架-flask

简述 Flask 是 Python 生态圈中一个基于 Python 的Web 框架。其轻量、模块化和易于扩展的特点导致其被广泛使用,适合快速开发 Web 应用以及构建小型到中型项目。它提供了开发 Web 应用最基础的工具和组件。之所以称为微框架,是因为它与一些大型 Web 框架…

2024年河北省职业院校技能大赛 “信息技术应用创新赛项”(高职组)样题解法

​有问题请留言或主页私信咨询 2024年河北省职业院校技能大赛 “信息技术应用创新赛项”(高职组)样题 一、初始化环境 1.账号及默认密码如表1所示。 表1 账号及密码规划表 账 号密 码root(服务端)kylin2024!desk&#xff08…

gozero获取数据库内容报错解决方案与实践

这个错误通常出现在 Go 语言的数据库查询中,表示你尝试将一个不支持的数据类型([]uint8,即字节切片)存储到一个 Go 类型(*time.Time)中。具体来说,create_time 列的类型可能是 DATETIME 或 TIME…

【学习笔记15】如何在非root服务器中,安装属于自己的redis

一、下载安装包 官网下载黑马程序员给的安装包(redis-6.2.6) 二、将安装包上传至服务器 我将安装包上传在我的文件夹/home/XXX,指定路径中/src/local/redis/,绝对路径为/home/XXX/src/local/redis/解压安装包 XXXomega:~$ cd …

PotPlayer 配置安装

文章目录 一、下载1、官网链接2、微软商店 Microsoft Store 二、安装1、双击安装包2、选择字体3、安装向导下一步4、接收许可协议5、选择组件及关联6、选择安装位置7、硬解选项 三、设置1、关闭自动更新2、左键单双击设置3、视频下自动隐藏3.1、效果对比 4、播放信息显示设置4.…

【PCIe 总线及设备入门学习专栏 2 -- PCIe 的 LTSSM 和 Enumeration】

文章目录 OverviewLTSSM StatesDetect StatesDETECT_QUIETDETECT_ACTDETECT_WAITPolling StatesPOLL_ACTIVEPOLL_CONFIGPOLL_COMPLIANCEConfiguration StatesCONFIG_LINKWD_STARTCONFIG_LINKWD_ACCEPTCONFIG_LANENUM_WAITCONFIG_LANENUM_ACCEPTCONFIG_COMPLETECONFIG_IDLERecov…

STM32 FreeROTS Tickless低功耗模式

低功耗模式简介 FreeRTOS 的 Tickless 模式是一种特殊的运行模式,用于最小化系统的时钟中断频率,以降低功耗。在 Tickless 模式下,系统只在有需要时才会启动时钟中断,而在无任务要运行时则完全进入休眠状态,从而降低功…

【机器学习实战中阶】书籍推荐系统

图书推荐系统机器学习项目 通过这个机器学习项目,我们将构建一个图书推荐系统。对于这个项目,我们将使用 K 最近邻(K-Nearest Neighbor, KNN)算法。 让我们开始构建这个系统。 数据集说明 关于数据集 背景 在过去的几十年中…

嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础

嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础 目录 1.NAND FLASH 和NOR FLASH异同 ? 2.CPU,MPU,MCU,SOC,SOPC联系与差别? 3.什么是交叉编译? 4.为什么要交叉编译? 5.描述一下嵌入式基于ROM的运行方式和基于RAM的运行方式有什么区别? 1…

【数据分享】1929-2024年全球站点的逐月平均气温数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、湿度等指标,其中又以气温指标最为常用!说到气温数据,最详细的气温数据是具体到气象监测站点的气温数据!本次我们为大家带来的就是具体到气象监…

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正 1 添加依赖2 测试代码3 测试结果 在OpenCV中,仿射变换(Affine Transformation)和透视变换(Perspective Transformation)是两种常用的图像几何变换方法。 变换方…

电梯系统的UML文档07

从这个类中得到的类图,构划出了软件的大部分设计。 系统结构视图提供软件和整个系统结构最复杂的也是最优雅的描述。和通常的软件系统相比,在分布式嵌入系统中了解系统组件如何协同工作是非常重要的。毕竟,每个类图仅仅是一个系统的静态设计…

文本摘要研究:从统计方法到大型语言模型

论文地址:https://arxiv.org/pdf/2406.11289 📖 文本摘要研究:从统计方法到大型语言模型 近年来,文本摘要研究经历了多次重大变革,从深度神经网络的出现到预训练语言模型(PLMs),再到…

MYSQL 5.7数据库,关于1067报错 invalid default value for,解决方法!

???作者: 米罗学长 ???个人简介:混迹java圈十余年,精通Java、小程序、数据库等。 ???各类成品java毕设 。javaweb,ssm,springboot,mysql等项目,源码丰富,欢迎咨询。 ???…

C ++ 也可以搭建Web?高性能的 C++ Web 开发框架 CPPCMS + MySQL 实现快速入门案例

什么是CPPCMS? CppCMS 是一个高性能的 C Web 开发框架,专为构建快速、动态的网页应用而设计,特别适合高并发和低延迟的场景。其设计理念类似于 Python 的 Django 或 Ruby on Rails,但针对 C 提供了更细粒度的控制和更高效的性能。…

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用 1. 建议按文章顺序从头看是看 第一篇:一文大白话讲清楚啥是个webpack第二篇:一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建然后看本篇,Loader的配置…

Kafka 日志存储 — 日志索引

每个日志分段文件对应两个索引文件:偏移量索引文件用来建立消息偏移量到物理地址之间的映射;时间戳索引文件根据指定的时间戳来查找对应的偏移量信息。 1 日志索引 Kafka的索引文件以稀疏索引的方式构造消息的索引。它并不保证每个消息在索引文件中都有…