导读:今天分享的主题是《Kyuubi 在小米大数据平台的应用实践》,主要分为四部分内容:
第一个主题:关于 Kyuubi 在小米的大数据平台落地过程和实施路径的分享。

先介绍一下背景,小米的大数据体系在不断更新和迭代,随着业务架构、组织架构和技术架构的调整,内部大数据平台逐渐出现一些状况:
a. MySQL/Doris: 系统的自有的 User&Password 认证和权限体系
b. Hive/Kudu 基于 Kerberos 认证和 Sentry 的权限体系
c. Talos 是基于小米内部平台组织和团队的认证与授权体系

上述现象直接导致了如下问题:
①对用户:
②对平台:
面对数据平台难用的情况,提出了构建统一易用的大数据服务平台整体目标。整体架构能力围绕数据链路解决方案、数仓解决方案、数据服务解决方案来进行建设,提供统一的元数据管理和权限管理体系。
在这个大背景和动机下,统一的数据入口服务成为了一个非常重要的能力,它主要解决:

从上面的背景问题中可以看到,小米内部有几套大数据处理的 SQL 服务入口,总体还是围绕经典的 SQL On Hadoop 架构体系来构建,逐步从 ThriftServer 演进到向上抽象一层的 SQL Proxy 服务,在底层集成了 Hive/Spark/Doris 等引擎为 ETL 作业、Ad-Hoc 查询提供支持。
抽离的 SparkThriftServer 的实现模块作为独立的 SQL Proxy 服务,提供:
从这里可以看到 SQL Proxy 和 Kyuubi Server 的定位非常相似,但是存在很多不足:
a. SQL Proxy 没有完全剥离 STS 的实现,通过反射的方式进行复用,代码耦合很高,依赖 Spark 特定版本,升级困难
b. 底层引擎代理层没有统一抽象,与其他引擎适配困难,对底层引擎扩展性差
c. 无法本地调试,依赖 hadoop 配置,在办公和服务环境网络隔离情况下,必须在开发机上完成完整的功能测试和调试,开发和部署路径长
(1) 为什么选择 Kyuubi

通过上面的分析,我们发现在业务和架构上都存在着一些问题需要解决。
① 业务上:
SQLProxy 架构需要升级:
Kyuubi 的优势在于:
SQLProxy 和 Kyuubi 的架构非常相似,切换成本低。在业务需求和架构升级的双重推动下,我们选择了 Kyuubi。

升级过程和效果与我们的预期一致,可以看到架构相比 SQLProxy 更加简洁,扩展底层引擎非常容易,而且本地可测试可调试,极大提升了开发效率。从开发到上线新架构两周时间就完成了平滑迁移。
升级新架构带来的效果也非常明显,相比之前的架构不论代码质量、服务稳定性、可维护性和可扩展性上都有了重大提升:

经过半年的迁移推动,每日 SQL 有效处理量从 5W 提升到现在的 50W 规模,已经占据了整个 SQL 流量的 80%。特别是 SparkSQL 的流量半年新增到 30W。大体流量分布:Spark 36w/ Trino 12w / Hive 2.5w
各个引擎请求耗时:
目前 Kyuubi Server 承载真实的 SQL 流量日均 100w 左右,可用性仍然可达 99.9% 以上,非常稳定。
1. 构建符合业务需求的 Kyuubi
(1) 整体架构

整体架构和流程,主要分为入口服务、认证和权限适配、底层引擎管理及服务的可观测性:
(2) 用户使用交互

以工作空间(workspace)粒度来保计算资源的隔离的存储资源(表)安全,与 Kyuubi Group 的多租户类似,我们这里扩展到了其他引擎。
一次完成交互过程:
WorkspaceA 下面的用户使用平台发放的 Token,选择各类客户端工具,向引擎提交 SQL 查询,Kyuubi Server 会自动将用户 SQL 提交到该空间所属的计算引擎上去,来保证用户使用资源的隔离性。与其他 workspace 用户虽是同一入口,但是资源的使用上是隔离的。
Kyuubi Server 服务并不具体执行 SQL,同一的入口服务不会有太大压力。
2. 提升用户侧的易用性
(1) 统一认证和表坐标的统一
去 Kerberos 化,采用平台统一 Token 方式,解决:
表资源命名的统一规范化,小米内部存在多区域和多类数据源,如果使用统一的 SQL 入口服务,需要统一 SQL 语句的表名规范来避免冲突和统一的管理:
(2) Kyuubi Engine 公共资源池

引入 Kyuubi Engine 公共池主要解决用户首次进入空间提交 SparkSQL 的查询性能问题。上面提到的用户提交的 SQL 分析统计,50% 的 SQL 查询延时都在 5 秒以下。在没有提前分配的资源的情况下,用户提交查询会冷启动一个 Kyuubi Engine,这是 Kyuubi 当前的机制。由于小米 Yarn 提交一个 APP 的延时在分钟级别,用户一个简单的秒级查询会延迟到分钟级别,体感非常差。
因此,借助 Kyuubi Engine Pool 的实现,对没有提前配置和指定资源的 workspace 用户,会将 SQL 路由到已经预先启动好的 Kyuubi Engine Pool,以加快用户的查询速度,提升 SQL 查询体验。
3. 升级 Spark2.X 到 Kyuubi Engine

Kyuubi Engine 目前只支持 Spark3 以上,之前我们内部版本都是 Spark2,在升级到 Kyuubi Engine 之前做了相关对比测试,在 Kyuubi 架构和 SQLProxy 架构下,有明显的性能提升:
4. Kyuubi Server 的容器化

在 Kyuubi Server 的高可用上利用容器化的方式替换了当前 Kyuubi Client 端通过 ZK 进行服务发现的高可用模式:
5. 基于 Workspace 的计算资源管理
(1)Engine Manager

由于之前已经实现了对 Spark Engine 的管理服务,我们将 Kyuubi Engine 的管理直接从 Kyuubi Server 剥离,形成了单独的 Engine Manager 服务,负责 Engine 的生命周期管理,配置上下文管理,同时提供服务发现和负载均衡能力。
用户提交的 SQL 的流程:
(2) 用户提交

图上是我们的用户平台 SQL 查询入口,在 workspace 下的用户可以非常方便地启动一个 Kyuubi Engine。为降低用户的门槛,只暴露了资源相关和排队策略的配置。同时,用户还可以配置多个 Kyuubi Engine 实例,来保障当前 workspace 下的 SQL 执行的高可用。
(3) Engine 的高可用

为什么需要 Kyuubi Engine 的高可用?因为在实际环境中,Kyuubi Engine 是一直长时间运行的,Spark 的 SQL 执行过程非常复杂,时间一长其稳定性就有了问题:
因此实施了一些高可用的保障策略:
03 基于 Kyuubi 的改造
1. Trino 和 Doris 的代理

引入 Trino 和 Doris 主要解决 OLAP 场景的查询效率问题。
对于 Doris 的适配也采用了 JDBC 的方式,由于 Doris 客户端本身支持 Mysql JDBC,MySQL JDBC 的实现方式是全量拉取模式,Kyuubi Server 端有 OOM 的风险。目前通过限制 Doris 查询的超时时间来降低大结果集导致 OOM 的风险。
如果大家后面要扩展 Kyuubi 代理其他 JDBC 的数据库支持,一定谨慎处理。
2. SQL HTTP API 的支持
关于 HTTP API 的支持一共实现了 V1 版本和 V2 版本,相比社区还是有一些区别。
① V1 版本

但是也存在一些问题:
②V2 版本

为了彻底解决 V1 的水平扩展性问题,在 V2 版本中将 Kyuubi HTTP Server 完全无状态化,通过 Kyuubi Engine 直接提供 HTTP SQL API。Kyuubi Server 只起到出代理的作用。
另外的两点改进:
同时,也不用维持长链接,非常适合 ETL 的场景。
3. SQL 表列解析

我们在 Kyuubi Server 端做了权限认证,需要获取用户 SQL 的真实表名,单独开发了一个纯 SQL 的解析模块:支持表列血缘关系和 SQL 类型的提取,支持 SparkSQL、Trino 两种语法。
具体解析后的格式如图,包括类型、输入输出表和队列的列。
后续在具体实际场景中该模块的也应用到了其业务场景,比如表血缘审计日志,SQL 的统计请求分析等安全质量场景,完全复用了我们的 SQL 表列提取的能力。
04 Kyuubi 新特性的应用
1. 小文件合并

解决用户写场景可能导致的小文件过多的问题。用户一般会提交两个 SQL:一个是业务处理 SQL,一个是合并 SQL,通过通过 workflow 方式串联起来,维护不变。
开启也非常简单,可以在 Kyuubi Engine 启动阶段,SQL 提交阶段开启开关。
2. 增量获取和获取结果集限制

3. Z-Ordering

在我们内部画像场景做相关的测试,Z-Ordering 有显著的提升。
在具体应用中,Z-Ordering 的排序规则需要根据实际业务表的数据做相应调整:
Kyuubi Engine Z-Ordering 的实现非常巧妙,没有增加额外的列,直接复用了 parquet 的原生能力,所以一次生成可以支持多个引擎查询(只要该引擎支持 parequet 格式的读取)。
4. PlanOnly 模式

主要用于非 SQL 执行的 SQL 相关场景,比如:
PlanOnly 模式下 SQL 不会真正执行,只会输出解析后的 LogicalPlan/SparkPlan。目前为数据平台单独提供了语法语义校验服务,就是采用 Kyuubi Engine 的 PlanOnly 模式。
这种应用场景也为我们提供了一种新思路:将 Kyuubi Engine 作为 Yarn APP 的服务框架,提供其他场景的服务,比如校验服务、血缘关系提取服务和 SQL 的预计算服务等。
5. Scala mode

Scala Code 模式完全解放了 Kyuubi Engine 能力,具备直接通过 JDBC 提交 Scala 代码的能力,专门处理一些复杂逻辑的业务。
目前我们的应用场景在运维这块做了一些尝试,主要解决我们的运维效率。例如我们要在运行时动态加载用户自定义的 jar 包,读取 Thrift 格式化的数据。相比之前登录到生产集群机器打包代码运行的流程大大简化。
05 未来规划和总结
规划:
总结:
今天的分享就到这里,谢谢大家。
分享嘉宾
