标题|使用 ByConity 搭建 OLAP 数据平台
作者| 程伟,MetaAPP 的研发工程师
GitHub |https://github.com/ByConity/ByConity
ByConity 是字节跳动开源的云原生数据仓库,在满足数仓用户对资源弹性扩缩容,读写分离,资源隔离,数据强一致性等多种需求的同时,提供优异的查询,写入性能。
MetaApp 是国内领先的游戏开发与运营商,专注移动端信息高效分发,致力于构建面向全年龄段的虚拟世界。截至 2023 年,MetaApp 注册用户已超 2 亿,联运合作 20 万款游戏,累计分发量过 10 亿。MetaApp 在 ByConity 开源早期便保持关注,是最早进行测试并在生产环境上线的用户之一,最终在生产环境全量替换 ClickHouse,使资源成本降低超 50%。
本文将介绍 MetaApp 如何使用 ByConity 搭建其数据平台的。
MetaApp OLAP 数据分析平台
随着业务的增长,精细化运营的提出,产品对数据部门提出了更高的要求,包括:
-
需要对实时数据进行查询分析,快速调整运营策略;
-
需要对小部分人群做 AB 实验,验证新功能的有效性;
-
需要减少数据查询时间,降低数据查询难度,让非专业人员可以自主分析、探查数据。
显然传统 T+1 的数仓模式已经无法在时效性与普适性上满足其需求。通过参考业界优秀的 OLAP 平台实现方案,MateApp 实现了其 OLAP 数据分析平台。具体具体功能如下:
平台功能简介
-
事件分析:对收集到的用户事件进行灵活的筛选、分组、汇总。根据埋点数据进行筛选,做一些用户属性的分组或者是全局属性的筛选,查询完成以后进行数据展示,可按列按天展示。
-
转化分析:分析用户使用产品的转化情况,即漏斗分析。根据开始事件和结束事件选定,查询具体时间内的转化。
-
留存:分析用户在使用产品后再次回到产品的时间。根据起始事件、回访事件生成阶梯图。
-
用户分群:用来对指定用户群体的数据进行过滤分析。根据条件将符合条件的用户筛选出来并进行分群,并根据分群结果查询对应指标,如停留时间、玩游戏的时间等,为业务提供辅佐。
-
行为流:用来对单个用户的单个行为流进行分析。主要是用来查看某些用户的具体事件,如是否完整观看广告。
平台功能对应的 SQL 实现
事件分析中参数与 SQL 查询流程
-
把 SQL 分解为查询表、查询列需求、过滤条件、分组列,排序列,分别制作对应的模版。
-
通过传入参数判断,选择对应的模版,填入参数,拼接为 SQL。
-
把拼接好的 SQL 提交给数仓引擎查询,等待结果返回后绘图展示。
转化分析
通过使用 ClickHouse 转化的查询函数进行的查询。考虑集群压力,默认等级做了 6 个。使用中可以根据自己的需求做更多的等级,查出更多的数据。
留存分析
留存分析中过滤条件比较常用。过滤条件选择一般放在起始事件上。另外在 where 条件筛选好要查询的数据,这样可以降低查询时长。
创建分群
用户分群分为两部分,首先根据查询条件筛选出分群用户。拿到用户后保存在中间表或 Redis。在进行查询时,通过查询子表的操作获取创建好的分群用户进行查询。
行为细查详情
行为细查是直接使用 uid 和时间对表进行查询。具体的一个 SQL 代码比较简单,我们只是在这里做了 in 的使用。
问题及解决方式
问题一:查询多天数据非常慢,每天查询的指标相似,重复查询消耗计算资源。
解决方案:由于我们按天显示数据,将多天的数据查询拆分为按天查询,使用代理软件来缓存查询,降低重复查询对集群的消耗,这样可以使查询速度更快。我们把每天的数据查询结果拼接起来,展示到数据分析或者其他的功能界面上。
问题二:多天的转化分析涉及数据太多,导致集群计算慢/无法计算出来。
解决方案:也是将多天的转化拆分为按天计算,将多天的结果相加即可。
这样会有一定的误差,因为每天的 12 点这个分段被分开了(Day 1 的 12 点和 Day 2 的零点),导致如果转化发生在这一段时间可能就会丢失。但是在我们的场景下,根据用户画像,大部分用户在 12 点之前退出,所以此方式对我们的场景影响可忽略不计。
问题三:多天留存涉及数据太多,导致集群要计算30~60分钟(30日留存,15日留存)。
解决方案:通过将留存计算拆分为按天计算,再合并起来的方式解决。具体可以简单地从 3 日留存来举例说明。
-
1 号用户在 2 号来了多少人,计算 1 号在 2 号的留存;
-
1 号用户在 3 号来了多少人,计算 1 号在 3 号的留存;
-
2 号用户在 3 号来了多少人,计算 2 号在 3 号的留存;
最后把这些分解的留存计算再拼接为一个留存阶梯图。
我们要计算 4 号的时候,前 3 号的数据一部分是可以直接使用的,不需要再次计算。这样就可以达到计算速度非常快的目的。因为留存查询它是几乎每天都会查的,这样可以把 30 分钟的留存查询降低到 30 秒钟左右。
问题四:看板、实验查询响应非常慢。
解决方案:对看板、实验查询内容在凌晨时进行自动预查询,在白天查询时可以最大程度的利用缓存,加快查询速度,降低集群压力。
问题五:在留存、行为细查、转化分析,在使用 ClickHouse 集群的分布式表查询时相对较慢。
解决方案:由于用户数据是分片进行哈希存储数据的,可以直接查询 ClickHouse 的本地表,将查询结果合并起来使用,这样可以实现快速的数据查询。目前测试数据查询能够提升 40% 左右。(目前只能在 ClickHouse 中使用的优化方式)
平台运维问题及解决方案
这是一个典型的 OLAP 的架构。通过下图可以看到,用户移动端设备、PC 电脑客户端以及云上服务端提供的一些日志数据,经过我们的日志服务被收集到 Kafka。后续流程分成两部分,一部分是离线,一部分是实时。
在离线场景中,我们使用 DataX 把 Kafka 的数据集成到 Hive 数仓,再生成 BI 报表。BI 报表使用了 Superset 组件来进行结果展示;
在实时场景中,一条线使用 GoSink 进行数据集成,把 GoSink 的数据集成到 ClickHouse,另外一条线使用 CnchKafka 把数据集成到 ByConity。最后通过 OLAP 查询平台获取数据进行查询。
ByConity 社区在之前的分享中对 ClickHouse 和 ByConity 从使用角度进行过对比,概括总结下:
Meta OLAP 平台构建过程中,我们主要关注资源隔离、扩缩容、复杂查询,以及对分布式事务的支持。
使用 ClickHouse 遇到的问题
问题一:读写一体容易抢占资源,无法保证读/写稳定
业务高峰期时,数据写入将大量挤占 IO 和 CPU 资源,导致查询受到影响(查询时间变长)。数据查询也是如此;
问题二:扩/缩容麻烦,周期长
-
扩/缩容时间长:由于机器在 IDC,属于私有云,其中一个问题在于,节点增加周期特别长。从增加节点需求发出到真正增加好节点需要一周到两周的时间,影响业务;
-
无法快速进行扩缩容:扩缩容以后要重新进行数据分布,否则节点压力非常大;
问题三:运维繁琐,业务高峰期无法保证 SLA
-
常常因为业务的节点故障导致数据查询缓慢,数据写入延迟(逐渐从延迟几小时到几天的程度);
-
业务高峰期时资源出现严重不足,短期内无法扩容资源,只能通过删减部分业务的数据,为优先级高的业务提供服务;
-
业务低峰期时,资源大量空闲,成本虚高。虽然我们在 IDC,但是 IDC 的机器购买也受成本控制,且不能无限制的节点扩容,另外在正常使用时也有一定的成本消耗;
-
无法和云上资源进行交互使用;
引入 ByConity 后的解决方案
首先,ByConity 读写分离计算资源隔离可以保证读写任务比较稳定。如果读的任务不够,可以扩展相应资源,哪里不够补哪里,包括使用云上资源进行扩容。
其次,扩缩容比较简单,可以在分钟级别进行扩缩容。由于使用 HDFS/S3 分布式存储,计算存储分离,所以扩容以后不需要进行数据重分布,扩容后可以直接使用。
另外,云原生部署,运维相对简单。
-
HDFS/S3 的组件相对成熟稳定,扩缩容,灾备方案成熟,出现问题可快速解决;
-
业务高峰期时,可以通过快速扩容资源保障 SLA;
-
业务低峰期时,可以通过缩减存储/计算资源达到降低成本的目的;
ByConity 运维中常见的问题
问题一:数据合并太慢,或者合并任务出现问题。这会导致查询数据非常慢,可能出现 S3 的 QPS/带宽非常高等现象。
解决方案:
1、查询分区情况,查看否存在某些分区的占用磁盘空间很小,但 part 文件数非常的多的情况。
2、查询表合并任务情况,如果发现当前合并任务比较少,可以通过开启 enable_addition_bg_task=true
允许更多 merge 任务同时运行, 并增大 max_addition_bg_task_num=200
,来配置允许同时运行的个数。
问题二:Kafka 引擎消费堆积问题排查
解决方案:
1、查询消费日志,查看 exception 列看是否出现消费错误,如下面常见错误
-
出现 memory limit 可以调小 kafka_max_block_size
-
出现字段类型不匹配,则需要修改kafka引擎列类型
2、调整消费者数量、消费模式、消费批次大小
-
消费者数量不足:调整 kafka_num_consumers 参数来调整消费者个数
-
消费者分布不均匀:调整 kafka_cnch_schedule_mode=least_consumers 来让 vw 分布消费者尽可能均匀
-
批次太小:调整最大批次大小(kafka_max_block_size)和调整最小拉取间隔(kafka_max_poll_interval_ms)
ByConity 替换 ClickHouse 的建议
-
在业务中测试你的 SQL 是否可以在 ByConity 平台上正常运行,如果兼容基本上都可以运行,可能个别有一些小的问题,具体问题可以在社区中提出;
-
控制测试集群的资源,测试数据集大小,对比 ByConity 集群与 ClickHouse 集群的查询结果,看是否符合预期。如果符合预期,可以进行替换计划。对于更侧重计算的任务,可能在 ByConity 中表现更好。
-
根据测试数据集的大小,消耗的 S3 和 HDF 空间、带宽、QPS 计算资源的使用量,来评估全量数据时存储与计算需要使用的资源;
-
将数据同时打入 ByConity 或者 ClickHouse 集群,开始一段时间的双跑,解决双跑期间出现的问题。例如我们公司在资源不足的情况下,使用是按业务进行,我们可以先在云上建一个 ByConity 集群,迁入某一部分的业务,之后逐步按业务来替换,腾出 IDC 资源以后,再把这一部分的数据迁移到线下。
-
双跑没有问题后就可以退订 ClickHouse 集群。
在此过程中有一些注意事项:
-
S3 和 HDFS 远程存储的读取带宽与 QPS 可能会要求高一些,需要做一定的准备。例如,我们峰值每秒读写带宽为:写 2.5GB/读 6GB,峰值每秒 QPS 为:6~8k;
-
Worker 节点的带宽用满,也会造成查询瓶颈;
-
如果遇到未缓存的数据,可能会有冷启动问题。对此 ByConity 也有一些操作建议,具体还需要更多结合自己的业务进行,比如我们使用在早上进行预查的方式来将这一部分的冷启动问题进行缓解。
写在最后
逐步替换 ClickHouse 之后,在资源的使用上,如按包年包月购买资源计算,ByConity 比原来至少降低 50% 左右;如按需启停,相比全量购买资源,成本将再降低 25% 左右。具体分析见 ByConity 替换 ClickHouse 构建 OLAP 数据平台,资源成本大幅降低。
本文作为搭建 OLAP 数据平台的参考方案,如在使用 ByConity 过程中遇到问题,可以联系下方小助手加入技术交流群与社区沟通,也欢迎在 GitHub 上提 issue。
GitHub |https://github.com/ByConity/ByConity