作者:蔚来汽车数字化业务发展部大数据团队
小编导读:
蔚来汽车是一家全球化的智能电动汽车公司,是高端智能汽车市场的先驱及领跑者。蔚来致力于通过提供高性能的智能电动汽车与极致用户体验,为用户创造愉悦的生活方式。
为了提升内部大数据分析的效率,蔚来陆续尝试了多种组件,如 Apache Druid、TiDB 和 Apache Doris,最终选择了StarRocks,落地场景包含:用户画像平台、数据运营平台、BI 自助取数和整车三电可靠性数据库。引入 StarRocks 之后,在不同场景下分别有 4-8 倍的提升。
OLAP 架构演进
蔚来汽车内部有丰富的 OLAP 使用场景需求,包括销售潜在客户人群圈选、供应链/生产/物流时效看板、车主用车行为分析、车辆电池报警监控、售后维修归因等。
为了提升大数据分析的效率,我们陆续尝试了多种组件,如 Apache Druid、TiDB 和 Apache Doris,最终我们选择了StarRocks。相较于同类 OLAP 产品,StarRocks 表现出以下显著优势:
- 支持较高程度的并发(主键模型)
- 实时与离线分析的双重支持
- 支持明细和聚合模型
- 支持一定程度的更新
- 优秀的 Rollup 和物化视图能力,显著提升了查询效率
- 兼容 MySQL 协议,开发和使用成本比较低
- 全面的向量化引擎,支持 SIMD 指令,读写性能非常优异,满足我们的要求
- 架构简洁,运维成本比较低
首先我们来快速回顾下StarRocks的架构。StarRocks 架构简洁,整个系统的核心只有 FE(Frontend)、BE(Backend)两类服务进程,不依赖任何外部组件,方便部署与维护。FE 和 BE 模块都可以在线水平扩展,元数据和业务数据都有副本机制,确保整个系统无单点。StarRocks 提供 MySQL 协议接口,支持标准 SQL 语法。用户可通过 MySQL 客户端方便地查询和分析 StarRocks 中的数据。FE 是 StarRocks 的前端节点,负责管理元数据,管理客户端连接,进行查询规划,查询调度等工作。每个 FE 节点都会在内存保留一份完整的元数据,这样每个 FE 节点都能够提供无差别的服务。BE 是 StarRocks 的后端节点,负责数据存储、SQL执行等工作。
(StarRocks 架构简洁且提供 MySQL 协议接口)
在我们的大数据架构中,来自 Kafka/Hive 的业务/用户数据源,通过 Broker Load/Routine Load/Stream Load/Flink Connector 等多种离线/实时导入方式写入 StarRocks,主要用来存储 DWD/DWS/ADS 层的数据,用于离线和实时指标的快速分析。我们深度自研的 DataSight 一站式数据治理与开发平台,已经集成了 StarRocks,支持通过配置化方式方便的读写 StarRocks。
将历史任务迁移到 StarRocks 后,改善和收益显而易见。无论是查询速度还是运维成本,都得到了提升。以某车辆数据指标的 BI 服务为例,过去该指标采用 Druid 和 Cassandra 两种数据库存储,在迁移到 StarRocks 后,通过合理的 Rollup 策略,平均查询延迟从 2s+ 降低到 500ms,查询效率提高 4-5 倍,并且仅需使用一种 OLAP 查询引擎。
目前,公司已有 20 多个业务线开始使用 StarRocks,广泛应用于研发、生产制造以及用户车辆运营等多个领域的业务 BI 看板和指标大屏。
主要应用场景介绍
StarRocks 在我们团队主要有几个典型的应用场景:用户画像平台、数据运营平台、BI 自助取数、整车三电可靠性数据库等。
用户画像平台
蔚来数字化业务发展部门自主研发的用户画像平台是具备标签、分群、洞察和触达能力的平台,可以帮助业务全方位了解用户。这个平台全面帮助业务部门深入了解用户,通过标签圈选人群,生成用户画像定制个性化内容,并在用户生命周期中与他们进行深入互动。同时,平台会自动跟踪触达效果,确保高效地为用户提供极致贴心的服务。
用户画像平台主要使用 StarRocks 来存储用户的标签和分群数据,利用 StarRocks 强大的数据分析能力,可以通过用户的标签自由组合出各类用户画像,并运用于营销、运营、服务和数据分析等众多场景。
如图所示,我们用户画像平台主要包含以下几个部分:
- 离线标签部分:使用了 Spark 任务计算出日级更新的标签,并导入 StarRocks 的离线标签表。
- 实时标签部分:使用了 Flink 任务实时监听业务数据库表变更,并实时进行数据加工处理,最后将实时标签数据导入到 StarRocks 的实时标签表。
- 算法标签部分:包含了离线的打标和实时的打标,最终数据都会进行到 StarRocks 相关表里。
- 数据服务部分:结合离线和实时标签数据,计算出各类分群数据,并存储到 StarRocks 分群表,在此基础上对外提供标签和分群服务,上层业务系统可据此构建各种各样的基于特定人群的功能。
数据运营平台
数据运营平台主要为一线服务人员提供低时延、低代码、多维分析等功能的云表格和图表产品。对数据使用有如下特点:
- 较低延时:业务数据产生到可使用,以秒级延迟为主,分钟级~小时级延迟为辅。
- 灵活使用:分析指标多样性,指标由平台使用人员根据明细自由拖拉组合产生。
- 大数据聚合和极速查询:包含业务全生命周期数据,99th 查询需要在 3s 以内。
- 多种更新周期:同一数据表的不同字段的更新周期不同(有近实时、小时级 T+1、天级 T+1)。
StarRocks 支持流式数据和 HDFS 外部离线数据导入、主键模型部分列更新(Partial Update)、分区原子替换、分区数据裁剪以及索引等能力,很好的贴合以上数据使用的特点。在数据运营平台的落地过程中,我们遇到了一些StarRocks 使用上的问题,在社区积极的技术支持下逐一得到了解决和优化,以下是一些具体例子:
- 物化视图(MATERIALIZED VIEW)导致 Disk Storage 只增不减及查询无法命中物化视图
StarRocks DWS 表由 DIM 表和 DWD 表关联后得到,原设想 DWS 使用多表关联建立 MATERIALIZED VIEW,同 Rollup 表一样是可以在 DWS 中及时对 DIM 和 DWD 的行级变更做出更新,在 StarRocks v2.4.3 版本验证使用过程中发现 MATERIALIZED VIEW 底层实现为 insert overwrite,Disk I/O 耗时较大,实测 500w 的数据行大约需要 10s~15s,需要更新数据量的大小直接影响了数据的更新时效。
创建的 MATERIALIZED VIEW 会导致 Disk Storage 只增不减,反馈 StarRocks 社区后定位为 bug,后续已经修复。
另一个问题是查询执行计划无法命中物化视图,经排查得知创建初始表时采用的流式写入方式是造成该问题的原因。在周期性更新的表中,物化视图能够被有效利用(在更新周期内),但对于初始表则无法实现。因此,采用 MATERIALIZED VIEW 方式要考虑适用场景和限制。
- 并行 Insert Load 导致 Mem 和 CPU 负载过高
由于物化视图存在的问题,DWS 层的产出受到限制。为了克服这个问题,我们采用了与底层实现相同的 insert overwrite 方法,通过多个规则,包括分区规则和数据量规则,对数据进行分片更新。为确保所有 DWS 层数据几乎同时产出,我们为所有 DWS 表配置了相同的调度频次和时间。在 DWS 更新过程中,曾出现 CPU 和 MEM 过高的情况,但后来经过优化,我们采用了几个优先级队列来串行更新,从而保持 CPU 和 MEM 的占用相对平稳,最大限度地减少了资源热点问题。下图显示了资源占用在优化前后的变化情况:
尽管我们已经进行了优化,Insert Load 的资源占用仍比 Broker Load 和 Routine Load 高很多。为了进一步改善 DWS 的数据产出,我们会基于 Flink+Iceberg 做 row-level 级别的更新,这样 StarRocks 集群只作为存储提供查询服务,不再执行相关 ETL 的操作。
- Broker Load 和 Routine Load 监控告警
StarRocks 提供的集群监控指标在 Broker Load 只有各个状态的统计数量,而对于 load 失败后欠缺及时告警机制。对此问题我们制作了一些工具,基于 show load 和 show routine load 查询当前 Broker Load 和 Routine Load 的状态信息,在 load 失败后进行重试、自动拉起并发出通知告警。
一站式数据开发平台——Datasight 的 BI 自助取数板块
Datasight 的 BI 数据应用模块,主要解决的是用户看板需求、日常取数、分析、挖掘等场景。这些场景的数据有以下特点:数据变更频繁、报表需要实现准实时更新和大规模查询。
在 Datasight-BI 第一版的实现中,所有自主取数和数据集等需求,因用户 SQL 变更频繁,由于用户 SQL 频繁变更且为了解决查询性能问题,均通过 Presto 直连查询来完成。随着平台的扩展,大量业务使用案例涉及到数据跨度较大且涉及多个大型维表的查询,导致 Presto 查询变得缓慢,查询延迟可长达数十秒甚至几十秒,给 Presto 集群造成了巨大压力。
经过调研,考虑到业务在使用报表的过程中不同报表的查询速度和更新频率有所不同,我们最终决定选用 StarRocks 作为存储引擎进行改进。改进过程中,用户在直接连接 Presto 的时候编写 SQL 进行即时查询,确认数据后创建抽取计划。简言之,即将用户通过 Presto 查询获取的数据导入到 StarRocks。此后,用户所有查询都通过直接连接 StarRocks 进行。通过这一改进,整体报表的查询速度得到了提升,同时 Presto 查询压力得以分散至不同时间段。
整车三电可靠性数据库
可靠性是指产品在规定条件下和特定时间内完成预定功能的能力或概率。产品的可靠性涵盖了整个寿命周期的各个方面。我们的数据平台会基于已有车辆的可靠性相关指标数据,对整车零部件、EDS 电机核心零件上市后的可靠性进行预估。这能够揭示零件的过度设计或欠缺设计情况,为下一代车型和电驱动系统的研发提供数据依据和支持。
可靠性指标一般为月度指标,涵盖了多样的维度,如车型、电机组合等(约 20 个维度)。这些指标需要实时获取,包括次数、持续时长等统计度量。我们选择 StarRocks 来存储可靠性数据,目前 DWD 层的存量数据已达到数十亿条,而每月新增数据达到亿级。利用 StarRocks 强大的数据分析能力,我们能够快速计算频数、分位数等用户所需的指标。
鉴于可靠性精准载荷指标维度的多样性,我们采用 StarRocks 聚合模型表,针对用户频繁查询维度建立多个维度的 Rollup 索引。增加 Rollup 索引后,多指标同时查询计算速度可由 15 秒缩减至 2s 左右,性能提升了近 8 倍。下图展示了集成 StarRocks 的可靠性数据库系统架构:
在表设计方面,由于可靠性数据库涉及业务指标较多且指标来源频繁更新(经常增加新的零部件数据),同时历史数据同步表时间较长(每次需要同步几年的历史数据)等业务特点,如果将多个指标存入一张表中,后期的可维护性较差,并且会影响用户使用体验。因此,我们的可靠性数据库在设计中将每个指标都对应一个表,而将公共数据单独存储在维度表中。这样在灌历史数据时就不会对其他的指标数据造成影响了。
此外,对于一些 ID 数量的统计,如车辆 ID 的统计,由于其是聚合表的一个维度,直接使用 SELECT COUNT(DISTINCT id) 进行统计仍可能导致全表扫描。此时可通过改写 SQL,在计算聚合指标值之前先对该 ID 进行聚合操作,从而实现对 Rollup 查询的有效利用,可以一定程度上增加聚合查询速度。
集群运维
我们当前在线上运维着多个StarRocks生产集群,根据业务场景来划分,在国内和海外均有部署。未来随着业务规模持续增长,我们也将进一步扩容集群,以满足不断增长的业务需求。为确保运维工作的有效进行,我们采取了以下关键措施:
- 稳定性:为保证生产集群的稳定性,我们每个集群都部署三个 FE 节点,以确保高可用性,避免因单点故障引起的问题。
- 易运维:集群所有 FE 和 BE 进程都使用 system 进行托管,并加入开机自启动。
- 监控告警:采用 Prometheus+Grafana 方案进行监控和告警,保证集群稳定性
在过去关键版本升级时(如跨大版本升级),我们得到了 StarRocks 社区团队的大力支持。他们协助我们制定了详尽的升级计划,而且在我们为了最小化对业务的影响而选择在半夜进行升级时,社区的技术支持同学也为我们提供了远程协助,在这里特别表示感谢。
在集群运维过程中我们遇到过一些问题,在社区的支持下均得到了较快的响应和解决,例如:
- 内存泄漏问题
在集群版本升级到 2.5.5 之后,业务方上线了一些作业,每天凌晨 0:00 到 4:00 左右集群经常有任务报错使用内存超限制。具体错误如下:
errMsg":"Sql 执行失败, 原因Memory of process exceed limit. Used: 107658772696, Limit: 107657841622. Mem usage has exceed the limit of BE"}]
通过监控数据的分析,我们注意到 Backend 的内存使用率会在达到 100GB 后突然出现下降。初期我们猜测这可能是由于内存资源不足导致任务失败,然而在进行了扩容后,内存使用依然呈直线上升的趋势,而且即便在进行了一天的扩容之后,仍然出现了内存不足的情况。基于这些情况,我们开始怀疑系统存在内存泄漏的问题。
根据系统的内存使用,也发现将近 50GB 的内存不知所踪,具体如下图所示:
后来查询社区论坛,看到社区有人说2.5.4版本之后有内存泄漏问题,和我们的情况很类似 (备注1: https://forum.mirrorship.cn/t/topic/6535),经过多方确认之后,我们升级到最新的版本解决了该问题。
- Delete 操作未生效
业务同学反馈 FlinkSQL 同步 Kafka 的数据到 StarRocks 的时候遇到了一个问题。Kafka 的存储格式是 debezium-json,在某些情况下,当数据的操作类型(op)为 delete 时,StarRocks 未能正确地将该数据删除。这问题表现为似乎 delete 操作没有生效。举例来说,对于同一个主键 id,print 输出显示一条insert 和一条 delete 的操作,但在将数据写入 StarRocks 后,该条数据仍然存在。后来经过和 StarRocks 的专家沟通之后,确认了这个问题。相关 PR 已合入 2.5.9 版本。(备注 2: https://github.com/StarRocks/StarRocks/pull/26719) - 集群扩容后的数据均衡
当集群 BE 扩容后,由于当前集群 tablet 数量比较多,都是通过副本在各个 BE 之间拷贝完成的。如果同一台 BE 同一时间执行过多的任务,则会带来较大的 I/O 压力。因此,StarRocks 在调度时控制了每个节点上能够执行的任务数目。最小的资源控制单位是磁盘(即在 be.conf 中指定的一个数据路径)。StarRocks 默认为每块磁盘配置两个 slot 用于副本修复。一个 clone 任务会占用源端和目的端各一个 slot。如果 slot 数目为零,则不会再对这块磁盘分配任务。该 slot 个数可以通过 FE 的 tablet_sched_slot_num_per_path 参数动态配置。
因为 StarRocks 的架构简单清晰,天然具有易运维的性质。经过多版本的更新升级后,当前版本集群已经十分稳定,在未来的运维工作中我们会针对集群资源隔离和查询队列做进一步的探索,限制查询对资源的消耗,防止单一用户,或者单一大查询占用集群过多资源和影响其他租户的正常使用,从而实现多租户之间的资源隔离与合理利用,增加集群可用性和稳定性。
未来规划
未来我们打算从以下几方面对 StarRocks 进行提升改进,以更好地服务于公司内各个使用 StarRocks 的业务方:
- 大数据元数据管理和 Iceberg 数据湖整合:我们计划将多个 StarRocks 集群接入大数据元数据管理系统,并和 Iceberg 数据湖进行打通,为构建基于元数据的统一数据查询分析平台奠定基础。
- 存算分离和成本优化:我们计划尝试使用 StarRocks 3.x 版本的存算分离架构,把海量车联网明细数据放到腾讯云对象存储上,从而降低海量车联网数据的存储成本。
- 资源隔离和多租户管控:启用资源隔离功能,进行更好的多租户资源管控和审计,以保证高优租户读写稳定性。
同时,我们也向社区提出了一些建议,希望能进一步完善产品:
- 扩展云服务支持:我们希望 StarRocks 能够支持更多的公有云服务,如腾讯云和亚马逊 AWS,并期待能推出 serverless 云服务。这将有助于未来的迁移工作,显著降低数据团队在 StarRocks 运维方面的成本。
- 权限管理增强:支持更细粒度的权限管理(行级别、列级别权限),可以和 Ranger 权限系统打通。
- 流式读取和物化视图更新:支持 Flink 流式数据读取(row level 数据行变更);支持流式物化视图,能根据上游依赖表的 row level 级变更自动更新物化视图。
- 复杂嵌套类型支持:在内置原生 OLAP 引擎中支持 Struct 和 Map 等复杂嵌套类型 (已在 3.1 支持)
积极参与开源社区:
在引入 StarRocks 后,我们团队除了积极向社区反馈问题外,也向官方贡献了一些代码。到目前为止,我们提交的 PR 有包含比特位运算函数支持和 StarRocks Spark Connector 写数据 bug 修复等。后续我们也会积极参与开源社区,贡献我们的一份心力。我们对于 StarRocks 小伙伴们一直以来所提供的支持和协助表示感激,同时也祝愿 StarRocks 开源社区能够继续取得更大的成就!
本文由mdnice多平台发布