干货|从 ClickHouse 到 ByteHouse:实时数据分析场景下的优化实践

简介: 干货|从 ClickHouse 到 ByteHouse:实时数据分析场景下的优化实践


作为国内规模最大的 ClickHouse 用户,目前字节跳动内部的 ClickHouse 节点总数超过 1.8W 个。综合来说,字节跳动广泛的业务增长分析很多都建立在 ClickHouse 为基础的查询引擎上。

2021年8月,火山引擎基于字节跳动内部最佳实践,正式推出ByteHouse企业版,解决了开源技术上手难、试错成本高等企业数字化转型中遇到的技术痛点。

在打造ByteHouse的路程中,我们经过了多年的探索与沉淀,本文将分享字节跳动过去使用 ClickHouse 的两个典型应用与优化案例。

推荐系统实时指标

在字节跳动内部“A/B 实验”应用非常广泛,特别是在验证推荐算法和功能优化的效果方面。最初,公司内部专门的 A/B 实验平台已经提供了 T+1 的离线实验指标,而推荐系统需要更快地观察算法模型、或者某个功能的上线效果,因此需要一份能够实时反馈的数据作为补充:

• 能同时查询聚合指标和明细数据;

• 能支持多达几百列的维度和指标,且场景灵活变化,会不断增加;

• 可以高效地按 ID 过滤数据;

• 需要支持一些机器学习和统计相关的指标计算(比如 AUC)。

01 - 技术选型

字节内部有很多分析引擎,ClickHouse、 Druid、 Elastic Search、 Kylin 等,通过分析用户需求后选择了 ClickHouse:

• 能更快地观察算法模型,没有预计算所导致的高数据时延;

• ClickHouse 既适合聚合查询,配合跳数索引后,对于明细点查性能也不错;

• 字节自研的 ClickHouse 支持 Map 类型,支持动态变更的维度和指标,更加符合需求;

• BitSet 的过滤 Bloom Filter 是比较好的解决方案,ClickHouse 原生就有 BF 的支持;

• 字节自研的 ClickHouse 引擎已经通过 UDF 实现了相关的能力,而且有比较好的扩展性。

每个产品都有自己合适的场景,但是对于当前场景的需求评估下,ClickHouse 更加合适。

方案对比

确认技术选型后,在如何实现部分,也有两种方式:

最终方案及效果

由于外部写入并不可控和技术栈上的原因,我们最终采用了 Kafka Engine 的方案,也就是 ClickHouse 内置消费者去消费 Kafka。整体的架构如图:



• 数据由推荐系统直接产生,写入 Kafka——为了弥补缺少 Flink 的 ETL 能力,推荐系统做了相应配合,修改 Kafka Topic 的消息格式直接适配 ClickHouse 表的 Schema;

• 敏捷 BI 平台也适配了一下实时的场景,可以支持交互式的查询分析;

• 如果实时数据有问题,也可以从 Hive 把数据导入至 ClickHouse 中,除此之外,业务方还会将 1% 抽样的离线数据导入过来做一些简单验证,1% 抽样的数据一般会保存更久的时间。

除了技术选型和实现方案,我们在支持推荐系统的实时数据时遇到过不少问题,其中最大的问题随着推荐系统产生的数据量越来越大,单个节点的消费能力也要求越来越大,主要碰到如下问题:

02- 挑战与解决方案

问题一:写入吞吐量不足

在有大量辅助跳数索引的场景下,索引的构建严重影响写入吞吐量。

解决方案——异步构建索引



社区版本的实现里的具体逻辑如下:

• 解析输入数据生成内存中数据结构的 Block;

• 然后切分 Block,并按照表的 schema 构建 columns 数据文件;

• 最后扫描根据 skip index schema 去构建 skip index 文件。三个步骤完成之后才会算 Part 文件构建完毕。

在需要保证构建完 columns 数据之后用户即可正常查询的前提下,ByteHouse 同步完成前面两步,第三步把构建好的 Part  放入到一个异步索引构建队列中,由后台线程构建索引文件。

在改成异步后,整体的写入吞吐量大概能提升 20%。

问题二:Kafka 消费能力不足

社区版本的 Kafka 表,内部默认只会有一个消费者,这样会比较浪费资源并且性能达不到性能要求。

尝试优化过程:

• 尝试通过增大消费者的个数来增大消费能力,但社区的实现是由一个线程去管理多个的消费者,多个消费者消费到的数据最后仅能由一个输出线程完成数据构建,所以这里没能完全利用上多线程和磁盘的潜力;

• 尝试通过创建多张 Kafka Table 和 Materialized View 写入同一张表,但是对于运维会比较麻烦。

解决方案——支持多线程消费



前面提到的优化手段都不尽如人意,最后决定改造 Kafka Engine 在其内部支持多个消费线程,简单来说就是每一个线程它持有一个消费者,然后每一个消费者负责各自的数据解析、数据写入,这样的话就相当于一张表内部同时执行多个的 INSERT Query。

通过多线程实现多消费者同时消费写入表,写入性能达到接近于线性的提升。

问题三:出现故障无法保证数据完整性

在主备模式下,如果数据同时两个节点都写入,一旦一个节点出现故障,新启的节点恢复过程中容易出现各种问题,包括性能下降,无法保证分片,最严重可能导致查询结果不正确。

解决方案——确保主备模式下只会写入一个主备其中一个节点

为了避免两个节点消费这个数据,改进版的 Kafka Engine 参考了 ReplicatedMergeTree 基于 ZooKeeper 的选主逻辑。对于每一对副本的一对消费者,会尝试在 ZooKeeper 上完成选主逻辑,确保选举成为主节点的消费者才能消费,另一个节点则会处于一个待机状态。



有了这样的单节点消费机制, 系统会检测 ReplicatedMergeTree 表数据是否完整,如果数据不完整则代表不能正常服务,此时消费者会主动出让 Leader,让副本节点上成为消费者,也就是新写入的数据并不会写入到缺少数据的节点,对于查询而言,由于查询路由机制的原因也不会把 Query 路由到缺少数据的节点上,所以一直能查询到最新的数据。



改进 Kafka Engine 确保主备模式下只有一个节点能消费数据,即使出现节点故障在新节点恢复过程中同样保障了解决了数据完整性的问题。

广告投放实时数据

第二个典型案例关于广告的投放数据,一般是运营人员需要查看广告投放的实时效果。由于业务的特点,当天产生的数据往往会涉及到多天的数据。这套系统原来基于 Druid 实现的,Druid 在这个场景会有一些难点:



选择了 ClickHouse 之后能解决 Druid 不足的地方,但还是有部分问题需要解决:

问题一:Buffer Engine 无法和 ReplicatedMergeTree 一起使用

社区提供了 Buffer Engine 为了解决单次写入生成过多 Parts 的问题, 但是不太能配合 ReplicatedMergeTree 一起工作, 写入不同 Replica 的 Buffer 仅缓存了各自节点上新写入的数据,导致查询会出现不一致的情况。



解决方案改进了 Buffer Engine 做了如下的调整和优化:

• 我们选择将 Kafka/Buffer/MergeTree 三张表结合起来,提供的接口更加易用;

• 把 Buffer 内置到 Kafka Engine 内部, 作为 Kafka Engine 的选项可以开启/关闭,使用更方便;

• Buffer table 内部类似 pipeline 模式处理多个 Block;

• 支持了 ReplicatedMergeTree 情况下的查询。

首先确保一对副本仅有一个节点在消费,所以一对副本的两个 Buffer 表,只有一个节点有数据。如果查询发送到了没有消费的副本,会额外构建一个特殊的查询逻辑,从另一个副本的 Buffer 表里读取数据。



增强 Buffer Engine,解决了Buffer Engine 和 ReplicatedMergeTree 同时使用下查询一致性的问题。

问题二:出现宕机后可能会出现数据丢失后者重复消费的情况

ClickHouse 缺少事务支持。一批次写入只写入部分 Part 后出现宕机,因为没有事务保障重启后可能出现丢失或者重复消费的情况。



解决方案



参考了 Druid 的 KIS 方案自己管理 Kafka Offset,实现单批次消费/写入的原子语义:实现上选择将 Offset 和 Parts 数据绑定在一起,增强了消费的稳定性。每次消费时,会默认创建一个事务,由事务负责把 Part 数据和 Offset 一同写入磁盘中,如果出现失败,事务会一起回滚 Offset 和写入的 Part 然后重新消费。

确保了每次插入数据的原子性,增强了数据消费的稳定性。

结语

实时数据分析是ClickHouse的优势场景,结合字节跳动实时数据场景的特点,我们对 ClickHouse 进行了优化和改造,并将这些能力沉淀到了 ByteHouse 上。ByteHouse 基于自研技术优势和超大规模的使用经验,为企业大数据团队带来新的选择和支持,以应对复杂多变的业务需求,高速增长的数据场景。

未来,ByteHouse将不断以字节和外部最佳实践输出行业用户,帮助企业更好地构建交互式大数据分析平台。

ByteHouse已经在火山引擎上全面对外服务,并且提供各种版本以满足不同类型用户的需求。在ByteHouse官网上提交试用信息即可免费试用!欢迎大家试用。

相关文章
|
1月前
|
机器学习/深度学习 数据采集 数据挖掘
实战派教学:掌握Scikit-learn,轻松实现数据分析与机器学习模型优化!
【10月更文挑战第4天】Scikit-learn凭借高效、易用及全面性成为数据科学领域的首选工具,简化了数据预处理、模型训练与评估流程,并提供丰富算法库。本文通过实战教学,详细介绍Scikit-learn的基础入门、数据预处理、模型选择与训练、评估及调优等关键步骤,助你快速掌握并优化数据分析与机器学习模型。从环境搭建到参数调优,每一步都配有示例代码,便于理解和实践。
88 2
|
1月前
|
SQL 存储 OLAP
ClickHouse 在什么场景下才管用?
ClickHouse 是一款以速度快著称的分析型数据库,尤其在列式宽表遍历方面表现出色。然而,面对复杂查询和关联运算时,ClickHouse 的性能急剧下降,甚至无法执行某些任务。相比之下,esProc SPL 通过更简洁的 SPL 语法和强大的优化能力,在各种复杂场景下均表现出色,全面超越 ClickHouse。实际案例显示,esProc SPL 在处理大规模数据时,性能提升可达数十倍。
|
5月前
|
数据采集 机器学习/深度学习 数据可视化
使用Jupyter Notebook进行数据分析:入门与实践
【6月更文挑战第5天】Jupyter Notebook是数据科学家青睐的交互式计算环境,用于创建包含代码、方程、可视化和文本的文档。本文介绍了其基本用法和安装配置,通过一个数据分析案例展示了如何使用Notebook进行数据加载、清洗、预处理、探索、可视化以及建模。Notebook支持多种语言,提供直观的交互体验,便于结果呈现和分享。它是高效数据分析的得力工具,初学者可通过本文案例开始探索。
|
19天前
|
数据采集 存储 分布式计算
ClickHouse大规模数据导入优化:批处理与并行处理
【10月更文挑战第27天】在数据驱动的时代,高效的数据导入和处理能力是企业竞争力的重要组成部分。作为一位数据工程师,我在实际工作中经常遇到需要将大量数据导入ClickHouse的需求。ClickHouse是一款高性能的列式数据库系统,非常适合进行大规模数据的分析和查询。然而,如何优化ClickHouse的数据导入过程,提高导入的效率和速度,是我们面临的一个重要挑战。本文将从我个人的角度出发,详细介绍如何通过批处理、并行处理和数据预处理等技术优化ClickHouse的数据导入过程。
38 0
|
19天前
|
存储 Prometheus 监控
构建高可用性ClickHouse集群:从理论到实践
【10月更文挑战第27天】在数据驱动的时代,构建一个稳定、高效的数据库系统对于企业的业务发展至关重要。作为一名数据工程师,我深知数据库系统的高可用性和可扩展性对于支撑企业应用的重要性。在这篇文章中,我将分享如何构建一个高可用性的ClickHouse集群,从分布式表的设计到数据复制与分片,再到故障恢复机制,确保系统在大规模数据处理中的稳定性和可靠性。
49 0
|
1月前
|
数据采集 数据可视化 数据挖掘
使用Python进行数据分析:从入门到实践
使用Python进行数据分析:从入门到实践
50 2
|
1月前
|
SQL 分布式计算 数据挖掘
加速数据分析:阿里云Hologres在实时数仓中的应用实践
【10月更文挑战第9天】随着大数据技术的发展,企业对于数据处理和分析的需求日益增长。特别是在面对海量数据时,如何快速、准确地进行数据查询和分析成为了关键问题。阿里云Hologres作为一个高性能的实时交互式分析服务,为解决这些问题提供了强大的支持。本文将深入探讨Hologres的特点及其在实时数仓中的应用,并通过具体的代码示例来展示其实际应用。
171 0
|
1月前
|
SQL 消息中间件 分布式计算
大数据-143 - ClickHouse 集群 SQL 超详细实践记录!(一)
大数据-143 - ClickHouse 集群 SQL 超详细实践记录!(一)
75 0
|
1月前
|
SQL 大数据
大数据-143 - ClickHouse 集群 SQL 超详细实践记录!(二)
大数据-143 - ClickHouse 集群 SQL 超详细实践记录!(二)
58 0
|
2月前
|
数据采集 算法 搜索推荐
R语言营销数据分析:使用R进行客户分群的实践探索
【9月更文挑战第1天】R语言以其强大的数据处理和统计分析能力,在金融数据分析、营销数据分析等多个领域发挥着重要作用。通过R语言进行客户分群,企业可以更好地理解客户需求,制定精准的营销策略,提升市场竞争力和客户满意度。未来,随着大数据和人工智能技术的不断发展,R语言在营销数据分析中的应用将更加广泛和深入。