作者:滴滴 OLAP 开发工程师 刘雨飞
小编导读:
滴滴于 2022 年引入了 StarRocks。通过一年多的致力,StarRocks 逐步代替了原有技术栈,成为滴滴外部次要的 OLAP 引擎。截至 2023 年 12 月,滴滴曾经胜利建设了超过 40 个 StarRocks 集群,每日查问量在千万量级,领有超过 3000 张数据表。这一弱小的基础设施已广泛支持了滴滴公司简直所有的业务线,包含网约车、单车、能源、货运等多个畛域。
⚠️ 对于滴滴对立 OLAP 引擎的具体内容已在“StarRocks 对立 OLAP 引擎在滴滴的摸索实际”进行了具体解说,本文将着重探讨 StarRocks 物化视图在滴滴的理论利用。
高并发精准去重
实时数据洞察的拦路虎
实时数据洞察在业务管理中的重要性无可替代。在滴滴外部,网约车实时看板是公司最要害的业务监控工具之一,蕴含着超过 20 个重要的业务指标,如实时呼叫量、冒泡数量和 GMV 等。这些实时看板数据对于业务、数据和经营团队至关重要,提供了即时见解,帮忙咱们更好地理解业务的状态和趋势。
通过实时监测这些数据,咱们可能迅速应答市场稳定,做出及时决策,例如:
- 实时呼叫量变动可帮忙咱们满足顶峰需要,缩短乘客等待时间,进步司机收益;
- 冒泡数量稳定可提醒哪些地区需减少司机资源,满足潜在乘客需要;
- 然而,要害业务指标的计算通常须要大量的准确去重操作,尤其在顶峰访问期间,这可能会对资源造成微小压力,也是泛滥 OLAP 零碎始终以来的挑战之一。为了均衡计算成本,许多零碎就义了准确性,提供含糊去重的办法,这也是滴滴过来基于 Druid 的指标计算计划所采纳的策略。
然而,含糊去重办法存在计算误差,这意味着咱们可能无奈齐全精确地反映业务的理论状况,从而难以实现更精细化的经营决策。此外,即使为了升高资源耗费而就义了准确性,含糊去重节俭的资源在高并发场景下仍旧是无济于事。在大规模促销流动期间,高并发查问可能导致 Druid 集群的稳定性问题,引发性能降落、响应工夫缩短甚至零碎解体,这对一个依赖实时数据的业务来说是不可承受的。
因而,咱们迫切需要一种新的解决方案,在可控的资源开销下,实现高并发的准确去重,以更好地反对业务经营和决策。StarRocks 的物化视图帮忙咱们实现了这一指标。
StarRocks 物化视图
让精准去重的落地和减速不再是夸夸其谈
实时看板场景具备以下显著特点:
高基数的准确去重。看板须要面对日增量上亿规模的明细数据,并针对明细数据进行大量 count(distinct()) 计算。并且,在理论利用中,准确去重的用户、订单 id 通常是字符串,这对计算资源造成了微小挑战。
反对灵便的维度筛选。看板查问提供了多种筛选条件,包含工夫、城市、业务线等超过十个维度字段的组合。每天的实在查问可能会波及上千种维度组合。
查问并发高。尤其在大促期间,数据开发以及业务经营都会亲密关注业务刹时变化趋势,顶峰期间可能有上千规模的用户盯盘。指标数据依照分钟级别刷新,每次刷新会触发大概几十次查问计算,则顶峰期间可能有数百 QPS,对集群负载要求十分高。如果每次查问都间接应用原始明细数据进行计算,将耗费大量计算资源,这在老本上是难以承受的。
这样的业务场景对查问引擎提出了十分高的要求。自 2022 年起,滴滴曾经在网约车、单车、能源、货运等多个畛域利用了 StarRocks,咱们也在亲密关注社区的新性能。异步物化视图是针对通明查问减速、高并发场景研发的利器,自其公布之后,咱们就开始了这个场景的测试验证。尝试物化视图次要是因为其以下几个特点:
- 物化查问后果:物化视图能够通过 SQL 查问来将计算结果缓存下来。缓存下来的后果能够被看作是一张物理表,相比 index(同步物化视图),在高并发的场景下体现更加优良。
- 托管刷新流程:相较于手动保护导入工作,物化视图的刷新不仅能够定时触发,还可能依据数据变更做到分区级别的增量刷新,升高刷新老本。
- 通明查问改写:物化视图反对智能的通明改写,可能将物化的后果更大范畴的利用到更多查问减速上。用户无需感知物化视图的存在,即可减速查问体验。
StarRocks 实时准确去重最佳实际
在联合业务特点和 StarRocks 的物化视图能力,咱们设计了整个看板场景的减速优化链路。以下是设计的次要思路:
为了最大限度地升高去重操作对 CPU 的耗费、减速去重,咱们的整体思路是:
- 数据预处理:利用全局字典进行数据类型转换,用最小的代价做准确去重
最上游的数据来自数据仓库,通过荡涤加工后,通过 Flink 实时同步到 StarRocks。在 StarRocks 外部,首先进行一次全局字典转换。特地是对须要进行去重的指标列,将其从 String 类型映射为 BIGINT 类型,以便后续应用 BITMAP 类型进行上卷计算。
- ODS 层:利用明细模型存储原始数据
接下来,在 StarRocks 外部进行数据建模,生成原始明细表并造成 ODS 层 –StarRocks 明细模型层。
- DWD 层:利用同步物化视图构建增量聚合层
在 DWD 层,咱们创立了同步物化视图对不同维度组合进行上卷去重。同步物化视图相似于索引(Index),它具备较高的时效性,并且数据满足强一致性。在准确去重场景,同步物化视图能够通过存储 BITMAP 类型的两头计算结果,使后续单次明细查问性能显著晋升,同时还为下一步异步物化视图的更新提供便当。
- ADS 层:利用异步物化视图构建通明减速层
在 ADS 层,咱们创立了异步物化视图,这些视图应用定时刷新机制。尽管时效性绝对较差,存在肯定的数据更新提早,但因为存储的是最终计算结果,查问速度十分快。这能够被视为长久化的查问缓存。
- 减速策略:利用智能改写能力通明提速
通过剖析历史查问模式来构建增量聚合层的同步物化视图,在此之上进一步将最高频的查问定义为通明减速层的异步物化视图。同步和异步物化视图都反对通明的查问改写,按照这样的构建逻辑,用户基于原始明细表查问时,会遵循异步物化视图 -> 同步物化视图 -> 原始明细表的优先级来进行查问减速,从而保障了查问整体的实效性。
接下来开展解说每一部分是如何构建的。
数据预处理:利用全局字典进行数据类型转换,用最小的代价做准确去重
StarRocks 反对两种类型的去重形式:Hyper-loglog 和 BITMAP。对于须要准确去重的指标,咱们应用 BITMAP 类型。
StarRocks 外部采纳了 Roaring BITMAP 的实现形式,字段类型要求在 INT(64) 位以内,并在数据连续性较好的状况下性能体现更佳。如果数据具备间断递增的个性,相较于齐全随机的 ID 性能劣势可达数倍以上。因而,滴滴在 StarRocks 中实现了高基数全局字典的性能。
第一步:创立全局字典表(主键模型表)
这里利用到 StarRocks 主键模型表的局部列更新以及自增列性能。文档请见:
https://docs.starrocks.io/zh-cn/latest/using_starrocks/query_…
创立全局字典表:数据存储在 StarRocks 外部具备自增 ID 列的主键表中。表的主键应用须要去重的 STRING 字段,而 ID 列则是自增的 BIGINT 列。这样每一个须要被去重的 STRING 字段都会有一个对应的 BIGINT 值与之对应。
间断递增的数据生成:在写入 STRING 列数据时,自增 ID 列会主动生成间断递增的 BIGINT 值。并且,通过 StarRocks 的 partial_update 局部列更新性能,能够保障 BIGINT 列只在第一次写入时生成,后续即使写入雷同的 STRING 值,对应的 BIGINT 也不会被更新。确保数据写入的幂等性,从而保证数据能够有限次地反复写入。
第二步:字典映射函数
咱们实现了字典映射的函数 dict_mapping,其入参包含字典表表名和主键值。它能够在计算时实时查问字典表,并返回生成的 ID 值。为了进步性能,咱们应用了 StarRocks 的主键索引进行减速,相比于基于间接扫描,性能晋升十分显著。这个函数目前曾经奉献回社区,欢送大家应用。
第三步:Flink 数据写入
对 Flink 的 flink-starrocks-connector 进行革新,数据写入分为两步:
首先,将数据写入字典表,包含抽取须要写入字典表的列,以确保数据写入并落盘,同时提交事务以使其可见。
随后,将数据写入明细模型表。在写入时,StarRocks 反对设置参数和应用函数进行预处理。应用第二步的字典映射函数 dict_mapping 对须要去重的字段进行从新映射,将本来的 string 类型映射为字典表中 ID 列的值。
通过这一流程,实现了在 StarRocks 中的全局字典性能,用于高效解决须要准确去重的指标计算。这个优化计划显著进步了性能并升高了计算成本,使得解决高基数去重变得更加高效和可扩大。
DWD 层:利用同步物化视图构建增量聚合层
在增量聚合层咱们创立了同步物化视图。同步物化视图同样提供了基于 BITMAP 和 HLL 算法的去重形式。咱们能够不便地利用 BITMAP 聚合函数来创立同步物化视图。同步物化视图创立实现后,后续查问语句中的子查问 count(distinct order_id) 会被主动改写为 bitmap_union_count(to_bitmap(order_id)) 以便查问命中物化视图。例如:
CREATE MATERIALIZED VIEW mv_dwd AS
SELECT dt, time_slice(`table_time`, INTERVAL 5 minute, floor) AS `ts`, city, source_type, bitmap_union(to_bitmap(order_id))
FROM base_table
GROUP BY dt, ts, city, source_type;
同步物化视图不仅能够作为异步物化视图的两头计算结果,减速异步物化视图的刷新,也能够承载一部分异步物化视图未命中的查问对其减速。
ADS 层:利用异步物化视图构建通明减速层
在增量聚合层咱们创立了异步物化视图。这里以简化后的订单表为例,介绍如何通过创立异步视图来实现查问减速。订单表包含分区日期、数据工夫、城市、渠道、业务线等维度字段,以及须要去重的字段业务订单 ID。
在数据表中,咱们应用 time_slice 函数将工夫粒度取整为 5 分钟,并依照 5 分钟区间粒度进行数据聚合。聚合的维度包含城市、渠道等可累加的维度。这个聚合视图的益处在于,当用户须要查问 5 分钟粒度的数据,并且查问条件与视图中的聚合维度齐全匹配时,能够间接应用这个视图进行查问减速,而无需查问原始底表的明细数据。示例如下:
CREATE MATERIALIZED VIEW `mv_ads`
PARTITION BY (dt)
DISTRIBUTED BY HASH(`ts`) BUCKETS 1
REFRESH ASYNC START(“2023-06-28 21:00:00”) EVERY(INTERVAL 30 SECOND) PROPERTIES ("partition_refresh_number" = "3")
AS SELECT
`dt`,
time_slice(`table_time`, INTERVAL 5 minute, floor) AS `ts`, `city`,
`source_type`,
count(DISTINCT `order_id`) AS `order_num`
FROM `base_table` GROUP BY
`dt`,`ts`,`city`, `source_type`;
同样的操作能够反复进行,设置不同的区间聚合粒度(如 1 分钟、10 分钟、30 分钟等),并依照不同的维度列组合,创立多张异步视图。这样能够满足不同用户、不同维度组合的查问需要,实现了对应实时看板的查问减速成果。
在上述过程中,须要创立的异步物化视图数量能够通过以下形式进行优化,以升高视图建设的老本:
- 辨别出可累加维度和不可累加维度
依据订单表中维度列的查问特点,能够将维度列分为可累加维度和不可累加维度。可累加维度指的是蕴含附属关系的维度。例如,“城市”属于可累加维度,因为它隶属于“全国”这个概念;而订单状态是不可累加维度,因为每个订单都在不同状态之间流转。
- 对于可累加维度,仅创立必要的异步视图
对于可累加维度,只需创立一个基于该维度的异步物化视图,不须要为每个不同的可累加维度组合创立独自的视图,因为后果是能够复用的。例如只须要创立针对“城市”聚合的物化视图,当须要计算“全国”范畴的后果时,能够在城市的后果上进一步计算而来。如果所有维度都是可累加维度,则实践上只须要一张物化视图就能够解决。
- 对于不可累加维度,依据不同组合创立异步视图
对于不可累加维度,须要依据不同的不可累加维度创立异步物化视图。这些视图将独自解决每个不可累加维度的数据,以满足特定查问条件。
通过以上优化策略,如果数据表中有 M 个可累加维度列和 N 个不可累加维度列,那么只须要创立 2^(N-M) 个异步物化视图,而不是 2^N 个。这样能够大幅缩小视图数量的同时满足绝大多数查问条件的减速需要,升高了建设和保护的老本,进步了零碎的可维护性和效率。
减速策略:利用智能改写能力通明提速
StarRocks 提供了物化视图的通明减速性能,使用户能够无需手动抉择应用哪张表,而是通过主动改写查问来实现减速,同时放弃查问的语义一致性和性能晋升。
假如有以下查问示例:
SELECT
ts,
SUM(order_num)
FROM(
SELECT
time_slice(`table_time`, interval 5 minute) AS ts,
count(DISTINCT `order_id`) AS `order_num`
FROM
`base_table`
WHERE
(...)
GROUP BY
`dt`,
`ts`,
`city`,
`source_type`
) sub
WHERE
dt = '2023-07-01'
GROUP BY
ts;
在这个查问中,内层子查问对数据进行了 5 分钟粒度的聚合,并蕴含了多个可累加维度。外层查问对子查问的后果进行了进一步的聚合。基于这个查问,能够建设以下三张异步视图:
视图 1:包含 5 分钟粒度聚合、可累加维度分区(dt)、日期(ts)、城市(city)、渠道(source_type)。
CREATE MATERIALIZED VIEW `mv_1`
PARTITION BY (dt)
DISTRIBUTED BY HASH(`ts`) BUCKETS 1
REFRESH ASYNC START(“2023-06-28 21:00:00”) EVERY(INTERVAL 30 SECOND) PROPERTIES ("partition_refresh_number" = "3")
AS SELECT
`dt`,
time_slice(`table_time`, INTERVAL 5 minute, floor) AS `ts`,
`city`,
`source_type`,
count(DISTINCT `order_id`) AS `order_num`
FROM
`base_table`
GROUP BY
`dt`,
`ts`,
`city`,
`source_type`;
视图 2:在视图 1 的根底上,减少了业务线(product_line)作为可累加维度。
CREATE MATERIALIZED VIEW `mv_2`
PARTITION BY (dt)
DISTRIBUTED BY HASH(`ts`) BUCKETS 1
REFRESH ASYNC START(“2023-06-28 21:00:00”) EVERY(INTERVAL 30 SECOND) PROPERTIES ("partition_refresh_number" = "3")
AS SELECT
`dt`,
time_slice(`table_time`, INTERVAL 5 minute, floor) AS `ts`,
`city`,
`source_type`,
`product_line`,
count(DISTINCT `order_id`) AS `order_num`
FROM
`base_table`
GROUP BY
`dt`,
`ts`,
`city`,
`source_type`
`product_line`;
而后,StarRocks 的通明减速性能会自动识别查问条件,将查问主动改写为实用于这些视图的模式,以放弃查问后果的一致性。例如:
- Case 1:如果 WHERE 条件为空,则命中视图 1,并主动改写查问以应用该视图减速。
- Case 2:如果 WHERE 条件蕴含 city IN (…),则命中视图 1,并相应地改写查问。
- Case 3:如果 WHERE 条件蕴含 product_line=?,则命中视图 2,并主动改写查问以应用该视图。
- Case 4:如果 WHERE 条件蕴含多个业务线查问,不反对累加,无奈命中视图 2,但如果有创立同步视图的话,能够进行上卷减速。
通过这种形式,StarRocks 能够依据查问条件主动抉择适当的视图进行减速,而无需用户手动染指,从而进步了查问性能并简化了用户操作。这保障了查问的语义一致性和性能晋升。
总结与布局
设计方案的外围在于衡量,而计划的胜利关键在于综合性能的晋升。对于看板类查问,其并发性十分高,但查问模式绝对固定。大多数查问都是类似甚至反复的。因而,整体计划的思路在于在肯定水平上就义灵活性,以保障查问性能的极致晋升。相较于基于明细间接计算,基于 StarRocks 物化视图对业务监控看板进行减速优化的长处不言而喻:
- 单次查问耗时升高 80%,资源耗费缩小 95%;
- 在雷同规模的集群上,反对的查问 QPS 进步了 100 倍。
以后,线上通过物化视图反对了上百并发的准确去重查问,彻底解决了 Druid 仅能反对几十并发含糊去重的问题,相较于原有架构 QPS 晋升了 10 倍。然而,计划也存在一些显著的不足之处,包含:
- 数据链路绝对简单,须要人工配置视图,保护复杂度较高,老本较高;
- 异步视图的定时刷新策略无奈保证数据强统一,并且即便在没有看板拜访时也会刷新,对计算资源有肯定节约
将来,咱们会联结社区进一步优化物化视图,提高效率:
- 晋升 BITMAP 的计算性能。这能够包含批改 StarRocks 的 BITMAP 分桶策略为 range 分桶,从而不须要对 BITMAP 的两头后果进行 shuffle 就能够失去最终后果。另外,应用 Roaring BITMAP 的 fastunion 函数来进步大量 BITMAP 的合并速度。
- 优化异步视图在改写计算环节的资源耗费。对于同底表相干的所有视图,在分区数据一致性和版本一致性等方面,都存在晋升的空间。
- 在易用性方面进行改良。因为看板查问都是基于平台配置的,主动生成的查问 SQL,因而通过剖析历史查问记录,提取高频查问,进行物化视图的主动创立,能够缩小人工参加,从而更有利于实现技术的更大规模利用和推广。这将使整个零碎更加智能和用户敌对。
并且,社区也在研发更加高效的全局字典,通过将字典表间接缓存在 BE/CN 的内存上,以升高查问字典时的网络开销,以满足除准确去重之外的更多场景。