阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

Apache Doris 在小米亿级用户行为分析平台的实践

  • 2023-01-05
    北京
  • 本文字数:4746 字

    阅读完需:约 16 分钟

Apache Doris 在小米亿级用户行为分析平台的实践

作者|小米数据智能部开发工程师 汤佳树

编辑|SelectDB


小米用户行为分析统一平台是基于海量数据的一站式、全场景、多模型、多维度、自助式大数据智能洞察分析服务平台,对接各类数据源,进行加工处理、分析挖掘和可视化展现,满足各类用户在用户洞察场景下的数据分析应用需求,提供高效极致的分析体验。

业务需求


平台可以基于数据进行时间分析,留存分析,分布分析,漏斗分析等,业务方主要基于事件进行分析,事件是追踪或记录的用户行为或业务过程,可以是单个事件也可以是多个事件组合的虚拟事件。


数据来源于各业务的打点数据,且基于事件模型进行建模,用户在产品中的各种操作都可以抽象成 Event 实体,并且里面都会包含五要素:


  • Who:即参与这个事件的用户是谁,例如用户的唯一 ID

  • When:即这个事件发生的实际时间,例如time字段,记录精确到毫秒的事件发生时间

  • Where:即事件发生的地点,例如根据 IP 解析出的省份和城市

  • How:即用户从事这个事件的方式,例如用户的设备,使用的浏览器,使用的 App 版本等等

  • What:描述用户所做的这件事件的具体内容,例如点击类型的事件,需要记录的字段有点击 URL,点击 Title,点击位置等


数据基于 OLAP 引擎 Doris 进行存储,随着接入业务不断增多,且接入的业务量不断膨胀,Top 级应用可以达到 100 亿条/天,查询压力和时间相继增大,用户对查询时延的吐槽愈来愈多,我们急切的需要提升查询性能来提升用户的体验。

痛点问题


针对于业务需求,我们总结了以下痛点问题:


  • 为了实现复杂的业务需求,OLAP 分析引擎需要留存、漏斗等分析函数支撑。

  • 增量数据 100 亿/天,导入压力大,部分业务要求数据导入不丢不重。

  • 业务接入不断增多,数据量膨胀,需要 PB 级的数据下的交互式分析查询达到秒级响应。


为了解决以上的痛点问题,我们对比了多款 OLAP 分析引擎,最终选择了 Apache Doris。Doris 提供了留存、漏斗分析等函数,极大程度的简化了开发的成本。在数据导入的过程中,我们尝试 Doris 刚推出的 Merge On Write Unique Key 导入模型,可以抗住 100 亿/天的增量数据压力。针对于向量化查询引擎的改造也是的性能较之前的版本有 3-5 倍的提升。

架构演进


一个优秀的系统离不开持续迭代与演进。为了更好的满足业务需求,我们在存储架构与查询引擎两个层面上不断进行尝试,小米用户行为分析系统在上线后,目前已完成 3 次改造,以下将为大家介绍改造历程。

数据存储结构:数据架构的演进


在小米的用户行为分析平台中,原始数据通过小米自研的消息队列 Talos,在 Flink 中清洗与建模后,被下游的 Doris 与 Hive 消费。全量的数据会存储在 Hive 中,进行批量 ETL 或历史数据召回的查询。实时增量数据被存储在 Doris 中,用来做热数据的查询操作。基于冷热数据分离的架构,我们进行了 3 次架构的演进。

第一阶段:基于明细宽表的查询


在最初的阶段我们使用了基于明细的宽表查询模式。为了处理灵活多样的分析请求,在系统中,我们配合统一埋点平台处理数据,接入的 OLAP 的数据是直接埋点的全字段展平。在入库之前,我们在 Flink 中将数据打平,以宽表的模式存储在 Doris 明细表中。根据查询的需求,我们将经常使用的列作为建表的维度列,利用前缀索引的特性进行查询加速。但某些头部大数据量业务容易查询多天数据,一个大查询可能就会将集群资源占满甚至导致集群不可用,且查询耗时相当之久

第二阶段:基于聚合模型的查询加速


在改造的第二阶段,我们使用了聚合模型对业务查询进行加速。 我们对接入行为分析的应用进行统计分析,绝大多数接入行为分析的应用数据量在 1 亿/天数据量以内。对于部分使用频率较高的表,我们采用聚合表完成查询加速,对单天数据量超 10 亿且高频的头部应用做聚合表加速。具体流程为根据数据量挑选出头部应用,对其进行字段解析,并挑选出常用指标及维度,由 Hive 表数据进行聚合 T-1 产出数据,最后写入到 Doris 中,进行查询加速。该阶段的改造解决了集群头部业务大查询的问题,此时虽然独立集群存储没问题,但由于其他业务接入后还会持续增加数据量和埋点字段 ,这样会导致元数据最先进入瓶颈。


第三阶段(当前阶段):业务适配的建表改造


当前阶段,我们对业务需求进行深度解析后重新规划了建表结构。我们对某些应用的埋点字段进行分析,发现有些用户埋点字段多达 500+,但在行为分析里实际用到的可能只有 100+,这显然有所浪费。所以我们与用户沟通调研需求,配合行为分析平台侧的能力,用户可在平台对有用事件和属性进行筛选,同时设置字段映射和过滤逻辑,然后再进行建表。

查询服务架构:查询引擎的改造与演进


我们基于业务深度改造了查询的服务架构,构建了新的查询引擎架构,实现 SQL 的权重、路由、缓存和资源调度操作。根据查询条件,路由引擎会将 SQL 拆分成多条子查询,在 Doris 或 Hive 中执行后,将子查询的结果汇总,得到最终的结果。针对查询引擎,我们也进行了 3 次技术架构的改造。


第一阶段:基于集群粒度的查询资源管理


我们对集群粒度进行查询资源管理,在资源调度中,我们会给每一个 Doris 集群设置一个总的资源池大小(根据集群能力和测试进行量化),根据数据量大小和查询天数对每个 SQL 进行加权,并对资源池的最大最小并行 SQL 数进行限制,如果计算的 SQL 超过限制则进行排队。其次,还会利用 Redis 对数据进行 SQL 级别缓存。

第二阶段:基于 SQL 路由的改造


为适配聚合表加速做了路由层,提升缓存命中率和利用率,此阶段拆分原始提交 SQL,基于指标进行缓存,粒度更细,服务端可根据指标进行适当计算更易于缓存命中。值得一提的是排队时间往往会比较长,有些场景下可能会进行重复提交或拆分成同样的 SQL,为了提高效率会在 SQL 排队前和排队后各进行一次缓存校验。


第三阶段(当前阶段):基于 SQL 权重的改造


整体架构方面,由于采取了筛选埋点字段而非全量字段导入 Doris,针对头部问题用户,我们会基于查询历史统计指标及维度,根据指定的某些规则进行默认初始化操作,并以此沟通用户并进行引导升级。此外为了更精细的控制资源调度,本阶段对对 SQL 内容进行加权,如含有DISTINCTLIKEVARIANCE_SAMP等字样再加权。对于资源消耗较大的操作,如 DISTINCT,会给予更高的权重,调度引擎在执行时会分配更多的资源。

实践应用


数据建模


对业务来讲,分析查询需要较高的灵活度,且是对用户粒度进行分析,所以需要保留较多的维度和指标,我们选用 Doris 作为存储查询引擎,且采用明细表建模,这样可以保证用户能够根据分析需求查出数据。另一方面,由于查询分析是一个延时要求较高的产品,对于数据量大、查询天数多、语句复杂的情况,查询延时会很高,所以对于头部应用,我们根据高频指标维度进行了聚合表模型建模。


 CREATE TABLE `doris_XXX_event` (  `olap_date` bigint(20) NOT NULL COMMENT "",  `event_name` varchar(256) NOT NULL COMMENT "",  `uniq_id` varchar(256) NOT NULL COMMENT "",  `dim1` varchar(256) REPLACE NULL COMMENT "",  `dim2` varchar(256) REPLACE NULL COMMENT "",  ...  `cnt` bigint(20) REPLACE NULL COMMENT "",  `index1` double REPLACE NULL COMMENT "",  `index2` double REPLACE NULL COMMENT "",  ...) ENGINE=OLAPAGGREGATE KEY(`olap_date`, `event_name`, `uniq_id`)COMMENT "OLAP"PARTITION BY RANGE(`olap_date`)
复制代码


数据导入


明细表部分,我们接入 Json 格式 TalosTopic,动态获取 Doris 表的 Schema 信息,通过双缓冲区循环攒批的方式,利用 StreamLoad 向 Doris 中写数据,如果在导入 Doris 时有出现失败的批次,重试 10 次仍然失败,会将数据按照应用粒度存入 HDFS,并在凌晨定时调度任务重新写入 T-1 未写入的数据。聚合表部分,我们由 Talos 落盘的 Iceberg 表,每日进行 T-1 数据的聚合,根据服务端选取的维度和指标,以及聚合类型(count ,count distinct , sum ,max ,min ),进行聚合存入中间 Hive 表,再由统一导入 Doris 程序进行导入。


数据管理


明细数据和应用聚合表分库存储,TTL 均为 33 天。数据表会有数据质量监控,如果总行数或者设置指标环比波动太大,会进行告警人工介入确认数据是否有误,视紧急程度进行回补处理。


数据查询及应用


绝大多数用户会锚定事件,进行含指标聚合,去重用户数(几乎占总查询的 50%)的事件行为分析,同时还会有留存分析,漏斗分析,分布分析等分析类型。


建表模型的维护


为了适配业务的变更,上游的埋点信息会周期性的更新。原有的表结构需要进行变更以适配埋点的增加。在过去的 Doris 版本中,Schema Change 是一项相对消耗较大的工作,需要对文件进行修改。在新版本中开启 Light Schema Change 功能后 对于增减列的操作不需要修改文件,只需要修改 FE 中的元数据,从而实现毫秒级的 Schame Change 操作。

应用现状


小米目前在 300 多个业务线上线了 Doris 集群,超过 1.5PB 的业务数据。在初期我们选择了两个使用较为频繁的集群进行向量化升级。


现迁移 Doris 向量化集群的行为分析业务有 2 个,7 天增量数据的平均值在百亿左右,存储空间占用 7T/天左右。在升级到向量化的版本后,存储资源有较大的节省,只需要原有集群约 2/3 的存储空间



性能提升

请求粒度


升级 Doris 向量化版本后,行为分析平台以请求粒度统计查询耗时 P80 和均值,P80 耗时下降 43% ,平均耗时下降 27% ;统计口径:汇总 12.07-12.11 期间,行为分析请求粒度查询执行时间。



SQL 粒度


升级 Doris 向量化版本后,行为分析平台以 SQL 粒度来统计查询耗时 P80 和均值,耗时 P80 下降 70% ,平均耗时下降 54%统计口径:汇总 12.04-12.11 期间,行为分析 SQL 粒度查询执行时间(未含排队)




升级 Doris 向量化版本后,行为分析平台以 SQL 粒度统计查询耗时 P80 和均值,耗时 P80 下降 56% ,平均耗时下降 44%


统计口径:汇总 12.02-12.11,行为分析 SQL 粒度查询总时间 (含排队)



去重优化


在 ID-Mapping 的时候,通常需要针对 ID 进行去重操作。在最初我们使用了COUNT DISTINCT来完成去重。


SELECT      a.`olap_date` AS `time`,             count(distinct a.`distinct_id`) AS distinct_id FROM        analysis.doris_XXX_event a WHERE       `a`.`olap_date` BETWEEN 20221218 AND 20221220 AND             a.`event_name` IN(XXXX, XXX, XXX, XXX) AND             ... ... GROUP BY    1 ORDER BY    2 DESC LIMIT       10000
复制代码


在经过优化后,我们使用子查询+ GROUP BY来替代COUNT DISTINCT的功能


SELECT      z.`time`,             count(distinct_id) var1 FROM        (SELECT     a.`olap_date` AS `time`,                         a.`distinct_id` AS distinct_id             FROM        analysis.doris_XXX_event a             WHERE       `a`.`olap_date` BETWEEN 20221218 AND 20221220 AND                         a.`event_name` (XXXX, XXX, XXX, XXX) AND                         ... ...            GROUP BY 1, 2) z GROUP BY    1 ORDER BY    2 DESC LIMIT       10000
复制代码


相较于原有的COUNT DISTINCT,使用子查询+ GROUP BY 的模式性能有 1/3 的提升

未来规划


在过去的三年时间里,Apache Doris 已经在小米内部得到了广泛的应用,支持了集团数据看板、广告投放/广告 BI、新零售、用户行为分析、A/B 实验平台、天星数科、小米有品、用户画像、小米造车等小米内部数十个业务,并且在小米内部形成了一套以 Apache Doris 为核心的数据生态 。随着业务的持续增长,未来我们会进一步推动小米的其他业务上线向量化版本。


非常感谢 Apache Doris 社区与 SelectDB 公司的鼎力支持,小米集团作为 Apache Doris 最早期的用户之一,一直深度参与社区建设,参与 Apache Doris 的稳定性打磨,未来我们也会密切联系社区,为社区贡献更多的力量。

2023-01-05 10:274526

评论

发布
暂无评论
发现更多内容

如何在几分钟内创建一个带有业务数据的官网 AI 智能客服?

Dify

开源 AI开发 LLMOps

业务模块在你做之前,一定要多想呀?

Bonaparte

产品 产品经理 产品设计 产品思维 产品需求

开心档之CSS !important 规则

文心一言 VS 讯飞星火 VS chatgpt (68)-- 算法导论6.5 7题

福大大架构师每日一题

福大大架构师每日一题

JVM 调优神器 arthas

java易二三

编程 计算机 Arthas

使用Keepalived实现Nginx的自动重启及双主热备高可用

java易二三

编程 程序员 计算机

Sharepoint安装SSL证书?

百度搜索:蓝易云

Linux 运维 https SharePoint ssl

用Orange Pi Zero3定制安卓电视盒子备忘

sai

Orange Pi Android TV

ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型

汀丶人工智能

人工智能 自然语言处理 NLP 大模型 关系抽取 命名实体识别

Mac部署AIGC图片生成服务——基于stable-diffusion

珲少

Apache服务器上安装SSL证书?

百度搜索:蓝易云

Apache Linux https SEO ssl

Ctyun系统升级OpenSSH 9.3详细教程

百度搜索:蓝易云

云计算 Linux 运维 openssh Ctyun

懒得改变原始对象?JavaScript代理模式教你怎样一步步偷懒!

控心つcrazy

JavaScript 设计模式 代理模式 Proxy Design Pattern

使用Appuploader工具将IPA上传到App Store的最新流程和步骤

雪奈椰子

活动回顾|火山引擎DataLeap分享:DataOps、数据治理、指标体系最佳实践(文中领取PPT)

字节跳动数据平台

数据中台 数据治理 抖音 DataOps 企业号 7 月 PK 榜

JVM类加载器子系统ClassLoader

java易二三

编程 程序员 计算机

请别再问Spring Bean的生命周期了!

java易二三

程序员 Spring Boot 计算机 Spring Bean生命周期

基于中文金融知识的 LLaMA 系微调模型的智能问答系统

汀丶人工智能

人工智能 自然语言处理 知识图谱 LoRa NLP 大模型

从互联网到云时代,Apache RocketMQ 是如何演进的?

阿里巴巴云原生

Apache 阿里云 RocketMQ 云原生

重塑思维模式,实践致富法则

少油少糖八分饱

读书笔记 分享 思维 搞钱 致富

Dify.AI 用户直面会:Dify 产品规划与 LLM 应用落地常见问题

Dify

开源 AI开发软件 LLMOps

Nginx的高可用

java易二三

编程 程序员 计算机

Spring Boot学习路线1

小万哥

Java spring 后端 Sprint Boot Sprint Cloud

Appuploader工具让ipa上传到App Store 的最新流程和步骤

想学Python高级编程?必须了解这个小技巧:match-case!

程序员晚枫

Python

大厂程序员的水平比非大厂高很多嘛?

程序员小毕

Java 程序员 面试 程序人生 架构师

解决 go-zero 注册 etcd 出现 “Auto sync endpoints failed.” 的问题

非晓为骁

golang etcd go-zero etcd-client 服务注册发现

容器化应用程序的配置管理策略与实践

DS小龙哥

7月月更

CSS !important 规则

雪奈椰子

iOS 应用上架流程详解

雪奈椰子

深入理解 HDFS(一):Block

冰心的小屋

hadoop hdfs 数据存储 文件分块 block

Apache Doris 在小米亿级用户行为分析平台的实践_文化 & 方法_SelectDB_InfoQ精选文章