每天如何处理150亿条日志并保持大查询在1秒内完成
如何处理150亿日志并在1秒内完成大查询
这个数据仓库使用案例与规模有关。用户是中国联通,世界上最大的电信服务提供商之一。他们使用Apache Doris,在数十台机器上部署了多个PB级别的集群,支持每天从他们的30多个业务线中添加的150亿条日志。这样一个庞大的日志分析系统是他们网络安全管理的一部分。为了实时监控、威胁追踪和警报,他们需要一个能够自动收集、存储、分析和可视化日志和事件记录的日志分析系统。
从架构的角度来看,该系统应该能够实时分析各种格式的日志,并且当然要支持庞大且不断增加的数据规模。本文的其余部分将介绍他们的日志处理架构是什么样的,以及他们如何通过它实现稳定的数据摄入、低成本存储和快速查询。
系统架构
这是他们数据流水线的概述。日志被收集到数据仓库中,并经过多个处理层。
- ODS:来自所有源的原始日志和警报被收集到Apache Kafka中。同时,它们的副本将存储在HDFS中,用于数据验证或重放。
- DWD:这是事实表所在的地方。Apache Flink会清理、标准化、补填和去标识化数据,并将其写回Kafka。这些事实表也将被放入Apache Doris中,以便Doris可以追踪某个项目或将其用于仪表盘和报告。由于日志不排斥重复,事实表将按照Apache Doris的重复键模型进行排列。
- DWS:该层从DWD中聚合数据,并为查询和分析奠定基础。
- ADS:在这一层中,Apache Doris使用其聚合键模型自动聚合数据,并使用其唯一键模型自动更新数据。
2.0架构是从1.0架构演变而来的,1.0架构由ClickHouse和Apache Hive支持。转变是由于用户对实时数据处理和多表连接查询的需求。在他们使用旧架构的经验中,他们发现并发性和多表连接的支持不足,表现为仪表盘频繁超时和分布式连接中的OOM错误。
现在让我们看看他们在2.0架构中在数据摄入、存储和查询方面的实践。
实际案例实践
每天稳定摄入150亿条日志
在用户的案例中,他们的业务每天产生150亿条日志。快速稳定地摄入如此大量的数据是一个实际问题。使用Apache Doris,推荐的方式是使用Flink-Doris-Connector。这是由Apache Doris社区开发的大规模数据写入组件。该组件需要简单的配置。它实现了流式加载,并且可以达到每秒20万~30万条日志的写入速度,而不会中断数据分析工作负载。
一个经验教训是,在使用Flink进行高频写入时,您需要为您的情况找到正确的参数配置,以避免数据版本积累。在这种情况下,用户进行了以下优化:
- Flink Checkpoint:他们将检查点间隔从15秒增加到60秒,以减少写入频率和Doris每单位时间处理的事务数量。这可以缓解数据写入压力,并避免生成过多的数据版本。
- 数据预聚合:对于来自不同表的相同ID的数据,Flink将根据主键ID进行预聚合,并创建一个扁平表,以避免多源数据写入导致的过多资源消耗。
- Doris Compaction:这里的技巧包括找到适当的Doris后端(BE)参数,为数据压缩分配适量的CPU资源,设置适当的数据分区、桶和副本数(过多的数据分片会带来巨大的开销),并调高max_tablet_version_num以避免版本积累。
这些措施共同确保了每日摄取的稳定性。用户在Doris后端观察到了稳定的性能和低压缩分数。此外,Flink中的数据预处理和Doris中的唯一键模型的组合可以确保更快的数据更新。
降低50%成本的存储策略
日志的大小和生成速率也对存储施加了压力。在海量日志数据中,只有其中的一部分具有较高的信息价值,因此应该进行存储区分。用户有三种降低成本的存储策略。
- ZSTD(ZStandard)压缩算法:对于大于1TB的表,在表创建时指定压缩方法为“ZSTD”,可以实现10:1的压缩比。
- 热数据和冷数据的分级存储:这是Doris的新功能支持。用户设置了一个7天的数据“冷却”期。这意味着过去7天的数据(即热数据)将存储在SSD中。随着时间的推移,热数据逐渐“冷却”(超过7天),将自动转移到更便宜的HDD中。随着数据变得更“冷”,它将被移动到对象存储中,以更低的存储成本。此外,在对象存储中,数据将仅存储一份副本,而不是三份。这进一步降低了成本和冗余存储带来的开销。
- 不同数据分区的差异化副本数量:用户根据时间范围对数据进行了分区。原则是对于较新的数据分区,有更多的副本,而对于较旧的数据分区,则有较少的副本。在他们的情况下,过去3个月的数据经常被访问,因此他们对这个分区有2个副本。3~6个月前的数据有两个副本,而6个月前的数据只有一个副本。
通过这三种策略,用户已将存储成本降低了50%。
基于数据大小的差异化查询策略
某些日志必须立即被跟踪和定位,例如异常事件或故障日志。为了确保对这些查询的实时响应,用户针对不同的数据大小采用了不同的查询策略:
- 小于100G:用户利用Doris的动态分区功能。小表将按日期进行分区,大表将按小时进行分区。这可以避免数据倾斜。为了进一步确保数据分区的均衡,他们使用雪花ID作为分桶字段。他们还设置了一个起始偏移量。最近20天的数据将被保留。这是数据积压和分析需求之间的平衡点。
- 100G~1T:这些表具有物化视图,即在Doris中存储的预计算结果集。因此,对这些表的查询速度更快,资源消耗更少。Doris中物化视图的DDL语法与PostgreSQL和Oracle相同。
- 大于100T:这些表被放入了Apache Doris的聚合键模型中,并进行预聚合。通过这种方式,我们可以在1~2秒内查询20亿条日志记录。
这些策略缩短了查询的响应时间。例如,以前查询特定数据项需要几分钟,但现在可以在毫秒内完成。此外,对于包含100亿数据记录的大表,对不同维度的查询都可以在几秒钟内完成。
正在进行的计划
用户目前正在测试Apache Doris中新添加的倒排索引。它旨在加速字符串的全文搜索,以及数值和日期时间的等价和范围查询。他们还就Doris中的自动分桶逻辑提供了有价值的反馈意见:目前,Doris根据上一个分区的数据大小来决定分区的桶数。用户遇到的问题是,大部分新数据都是在白天产生的,而晚上产生的数据很少。因此,在他们的情况下,Doris为夜间数据创建了太多的桶,但在白天创建的桶太少,与他们的需求相反。他们希望添加一种新的自动分桶逻辑,其中Doris决定桶数的参考是前一天的数据大小和分布。他们已经向Apache Doris社区提出了这个优化建议,我们正在进行此优化工作。 Zaki Lu 曾是百度的产品经理,现在是Apache Doris开源社区的DevRel。