滴滴基于 Clickhouse 构建新一代日志存储系统

ClickHouse 是2016年开源的用于实时数据分析的一款高性能列式分布式数据库,支持向量化计算引擎、多核并行计算、高压缩比等功能,在分析型数据库中单表查询速度是最快的。2020年开始在滴滴内部大规模地推广和应用,服务网约车和日志检索等核心平台和业务。本文主要介绍滴滴日志检索场景从 ES 迁移到 CK 的技术探索。

背景

此前,滴滴日志主要存储于 ES 中。然而,ES 的分词、倒排和正排等功能导致其写入吞吐量存在明显瓶颈。此外,ES 需要存储原始文本、倒排索引和正排索引,这增加了存储成本,并对内存有较高要求。随着滴滴数据量的不断增长,ES 的性能已无法满足当前需求。

在追求降低成本和提高效率的背景下,我们开始寻求新的存储解决方案。经过研究,我们决定采用 CK 作为滴滴内部日志的存储支持。据了解,京东、携程、B站等多家公司在业界的实践中也在尝试用 CK 构建日志存储系统。

挑战

面临的挑战主要来自下面三个方面:

  1. 数据量大:每天会产生 PB 级别的日志数据,存储系统需要稳定地支撑 PB 级数据的实时写入和存储。

  2. 查询场景多:在一个时间段内的等值查询、模糊查询及排序场景等,查询需要扫描的数据量较大且查询都需要在秒级返回。

  3. QPS 高:在 PB 级的数据量下,对 Trace 查询同时要满足高 QPS 的要求。

为什么选 Clickhouse

  • 大数据量:CK 的分布式架构支持动态扩缩容,可支撑海量数据存储。

  • 写入性能:CK 的 MergeTree 表的写入速度在200MB/s,具有很高吞吐,写入基本没有瓶颈。

  • 查询性能:CK 支持分区索引和排序索引,具有很高的检索效率,单机每秒可扫描数百万行的数据。

  • 存储成本:CK 基于列式存储,数据压缩比很高,同时基于HDFS做冷热分离,能够进一步地降低存储成本。

架构升级

fb32f7cedae1bc4d4b814fdad5c38c52.png

旧的存储架构下需要将日志数据双写到 ES 和 HDFS 两个存储上,由ES提供实时的查询,Spark 来分析 HDFS 上的数据。这种设计要求用户维护两条独立的写入链路,导致资源消耗翻倍,且操作复杂性增加。

在新升级的存储架构中,CK 取代了 ES 的角色,分别设有 Log 集群和 Trace 集群。Log 集群专门存储明细日志数据,而 Trace 集群则专注于存储 trace 数据。这两个集群在物理上相互隔离,有效避免了 log 的高消耗查询(如 like 查询)对 trace 的高 QPS 查询产生干扰。此外,独立的 Trace 集群有助于防止trace数据过度分散。

日志数据通过 Flink 直接写入 Log 集群,并通过 Trace 物化视图从 log 中提取 trace 数据,然后利用分布式表的异步写入功能同步至 Trace 集群。这一过程不仅实现了 log 与 trace 数据的分离,还允许 Log 集群的后台线程定期将冷数据同步到 HDFS 中。

新架构仅涉及单一写入链路,所有关于 log 数据冷存储至 HDFS 以及 log 与 trace 分离的处理均由 CK 完成,从而为用户屏蔽了底层细节,简化了操作流程。

考虑到成本和日志数据特点,Log 集群和 Trace 集群均采用单副本部署模式。其中,最大的 Log 集群有300多个节点,Trace 集群有40多个节点。

存储设计

存储设计是提升性能最关键的部分,只有经过优化的存储设计才能充分发挥 CK 强大的检索性能。借鉴时序数据库的理念,我们将 logTime 调整为以小时为单位进行取整,并在存储过程中按照小时顺序排列数据。这样,在进行其他排序键查询时,可以快速定位到所需的数据块。例如,查询一个小时内数据时,最多只需读取两个索引块,这对于处理海量日志检索至关重要。

以下是我们根据日志查询特性和 CK 执行逻辑制定的存储设计方案,包括 Log 表、Trace 表和 Trace 索引表:

Log 表

Log 表旨在为明细日志提供存储和查询服务,它位于 Log 集群中,并由 Flink 直接从 Pulsar 消费数据后写入。每个日志服务都对应一张 Log 表,因此整个 Log 集群可能包含数千张 Log 表。其中,最大的表每天可能会生成 PB 级别的数据。鉴于 Log 集群面临表数量众多、单表数据量大以及需要进行冷热数据分离等挑战,以下是针对 Log 表的设计思路:

CREATE TABLE ck_bamai_stream.cn_bmauto_local
(`logTime` Int64 DEFAULT 0, -- log打印的时间`logTimeHour` DateTime MATERIALIZED toStartOfHour(toDateTime(logTime / 1000)), -- 将logTime向小时取整`odinLeaf` String DEFAULT '',`uri` LowCardinality(String) DEFAULT '',`traceid` String DEFAULT '',`cspanid` String DEFAULT '',`dltag` String DEFAULT '',`spanid` String DEFAULT '',`message` String DEFAULT '',`otherColumn` Map<String,String>,`_sys_insert_time` DateTime MATERIALIZED now()
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(logTimeHour)
ORDER BY (logTimeHour,odinLeaf,uri,traceid)
TTL _sys_insert_time + toIntervalDay(7),_sys_insert_time + toIntervalDay(3) TO VOLUME 'hdfs'
SETTINGS index_granularity = 8192,min_bytes_for_wide_part=31457280
  • 分区键:根据查询特点,几乎所有的 sql 都只会查1小时的数据,但这里只能按天分区,小时分区导致 Part 过多及 HDFS 小文件过多的问题。

  • 排序键:为了快速定位到某一个小时的数据,基于 logTime 向小时取整物化了一个新的字段 logTimeHour,将 logTimeHour 作为第一排序键,这样就能将数据范围锁定在小时级别,由于大部分查询都会指定上 odinLeaf、uri、traceid,依据基数从小到大分别将其作为第二、三、四排序键,这样查询某个 traceid 的数据只需要读取少量的索引块,经过上述的设计所有的等值查询都能达到毫秒级。

  • Map 列:引入了 Map 类型,实现动态的 Scheme,将不需要用来过滤的列统统放入 Map 中,这样能有效减少 Part 的文件数,避免 HDFS 上出现大量小文件。

Trace 表

Trace 表是用来提供 trace 相关的查询,这类查询对 QPS 要求很高,创建在 Trace 集群。数据来源于从 Log 表中提取的 trace 记录。Trace 表只会有一张,所有的 Log 表都会将 trace 记录提取到这张 Trace 表,实现的方式是 Log 表通过物化视图触发器跨集群将数据写到 Trace 表中。

Trace 表的难点在于查询速度快且 QPS 高,以下是 Trace 表的设计思路:

CREATE TABLE ck_bamai_stream.trace_view
(`traceid` String,`spanid` String,`clientHost` String,`logTimeHour` DateTime,`cspanid` AggregateFunction(groupUniqArray, String),`appName` SimpleAggregateFunction(any, String),`logTimeMin` SimpleAggregateFunction(min, Int64),`logTimeMax` SimpleAggregateFunction(max, Int64),`dltag` AggregateFunction(groupUniqArray, String),`uri` AggregateFunction(groupUniqArray, String),`errno` AggregateFunction(groupUniqArray, String),`odinLeaf` SimpleAggregateFunction(any, String),`extractLevel` SimpleAggregateFunction(any, String)
)
ENGINE = AggregatingMergeTree
PARTITION BY toYYYYMMDD(logTimeHour)
ORDER BY (logTimeHour, traceid, spanid, clientHost)
TTL logTimeHour + toIntervalDay(7)
SETTINGS index_granularity = 1024
  • AggregatingMergeTree:Trace 表采用了聚合表引擎,会按 traceid 进行聚合,能很大程度的聚合 trace 数据,压缩比在5:1,能极大地提升 Trace 表的检索速度。

  • 分区键和排序键:与 Log 的设计类似。

  • index_granularity:这个参数是用来控制稀疏索引的粒度,默认是8192,减小这个参数是为了减少数据块中无效的数据扫描,加快 traceid 的检索速度。

Trace 索引表

Trace 索引表的主要作用是加快 order_id、driver_id、driver_phone 等字段查询 traceid 的速度。为此,我们给需要加速的字段创建了一个聚合物化视图,以提高查询速度。数据则是通过为 Log 表创建相应的物化视图触发器,将数据提取到 Trace 索引表中。

以下是建立 Trace 索引表的语句:

CREATE TABLE orderid_traceid_index_view
(`order_id` String,`traceid` String,`logTimeHour` DateTime
)
ENGINE = AggregatingMergeTree
PARTITION BY logTimeHour
ORDER BY (order_id, traceid)
TTL logTimeHour + toIntervalDay(7)
SETTINGS index_granularity = 1024

存储设计的核心目标是提升查询性能。接下来,我将介绍从 ES 迁移至 CK 过程中,在这一架构下所面临的稳定性问题及其解决方法。

稳定性之路

支撑日志场景对 CK 来说是非常大的挑战,面临庞大的写入流量及超大集群规模,经过一年的建设,我们能够稳定的支撑重点节假日的流量高峰,下面的篇幅主要是介绍了在支撑日志场景过程中,遇到的一些问题。

大集群小表数据碎片化问题

在 Log 集群中,90%的 Log 表流量低于10MB/s。若将所有表的数据都写入数百个节点,会导致大量小表数据碎片化问题。这不仅影响查询性能,还会对整个集群性能产生负面影响,并为冷数据存储到 HDFS 带来大量小文件问题。

为解决大规模集群带来的问题,我们根据表的流量大小动态分配写入节点。每个表分配的写入节点数量介于2到集群最大节点数之间,均匀分布在整个集群中。Flink 通过接口获取表的写入节点列表,并将数据写入相应的 CK 节点,有效解决了大规模集群数据分散的问题。

写入限流及写入性能提升

在滴滴日志场景中,晚高峰和节假日的流量往往会大幅增加。为避免高峰期流量过大导致集群崩溃,我们在 Flink 上实现了写入限流功能。该功能可动态调整每张表写入集群的流量大小。当流量超过集群上限时,我们可以迅速降低非关键表的写入流量,减轻集群压力,确保重保表的写入和查询不受影响。

同时为了提升把脉的写入性能,我们基于 CK 原生 TCP 协议开发了 Native-connector。相比于 HTTP 协议,Native-connector 的网络开销更小。此外,我们还自定义了数据类型的序列化机制,使其比之前的 Parquet 类型更高效。启用 Native-connector 后,写入延迟率从之前的20%降至5%,整体写入性能提升了1.2倍。

HDFS 冷热分离的性能问题

用 HDFS 来存储冷数据,在使用的过程中出现以下问题:

  1. 服务重启变得特别慢且 Sys cpu 被打满,原因是在服务重启的过程中需要并发的加载 HDFS 上 Part 的元数据,而 libhdfs3 库并发读 HDFS 的性能非常差,每当读到文件末尾都会抛出异常打印堆栈,产生了大量的系统调用。

  2. 当写入历史分区的数据时,数据不会落盘,而是直接往 HDFS 上写,写入性能很差,并且直接写到 HDFS 的数据还需要拉回本地 merge,进一步降低了 merge 的性能。

  3. 本地的 Part 路径和 HDFS 的路径是通过 uuid 来映射的,所有表的数据都是存储在 HDFS 的同一路径下,导致达到了 HDFS 目录文件数 100w 的限制。

  4. HDFS 上的 Part 文件路径映射关系是存储在本地的,如果出现节点故障,那么文件路径映射关系将会丢失,HDFS 上的数据丢失且无法被删除。

为此我们对 HDFS 冷热分离功能进行了比较大的改造来解决上面的问题,解决 libhdfs3 库并发读 HDFS 的问题并在本地缓存 HDFS 的 Part 元数据文件,服务的启动速度由原来的1小时到1分钟。

8b0885394c2385dd3ef95f9901c62c4c.png

同时禁止历史数据直接写 HDFS ,必须先写本地,merge 之后再上传到 HDFS ,最后对 HDFS 的存储路径进行改造。由原来数据只存储在一个目录下改为按 cluster/shard/database/table/ 进行划分,并按表级别备份本地的路径映射关系到 HDFS。这样一来,当节点故障时,可以通过该备份恢复 HDFS 的数据。

收益

在日志场景中,我们已经成功完成了从 ES 到 CK 的迁移。目前,CK 的日志集群规模已超过400个物理节点,写入峰值流量达到40+GB/s,每日查询量约为1500万次,支持的 QPS 峰值约为200。相较于 ES,CK 的机器成本降低了30%。

02d547753da170e1dd58271d1e0ab675.png

查询速度相比 ES 提高了约4倍。下图展示了 bamailog 集群和 bamaitrace 集群的 P99 查询耗时情况,基本都在1秒以内。

40e6a0aea23b48fca730c696105bba23.png

总结

将日志从 ES 迁移至 CK 不仅可以显著降低存储成本,还能提供更快的查询体验。经过一年多的建设和优化,系统的稳定性和性能都有了显著提升。然而,在处理模糊查询时,集群的资源消耗仍然较大。未来,我们将继续探索二级索引、zstd 压缩以及存算分离等技术手段,以进一步提升日志检索性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SkyWalking 本地启动以及闪退问题

1. 下载包 Downloads | Apache SkyWalking SkyWalking APM包含OAP和UI Java Agent 就是Java 的探针 2. 运行 UI 默认端口是 8080&#xff0c; OAP 默认端口是 11800&#xff08;grpc&#xff09;12800&#xff08;http&#xff09; 如果占用可以修改配置文件 UI 项目的配…

LVS 负载均衡部署的三种模式 与搭建dr模式具体步骤

一 LVS 负载均衡部署的模式 LVS 有三种负载均衡的模式&#xff0c;分别是VS/NAT(nat 模式)、VS/DR(路由模式)、VS/TUN(隧道模式)。 &#xff08;一&#xff09;三种模式原理 及优缺点 1&#xff0c;nat 模式 1.1 原理 原理:首先负载均衡器接收到客户的请求数据包时&am…

GPT-4技术解析:与Claude3、Gemini、Sora的技术差异与优势对比

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚…

b站小土堆pytorch学习记录—— P18-P22 神经网络+小实战

文章目录 一、卷积层 P181.卷积操作2.代码 二、池化层 P191.池化层简单介绍2.代码&#xff08;1&#xff09;池化操作中数字的变化&#xff08;2&#xff09;池化操作对图片的影响 三、非线性激活 P201.简要介绍2.代码 四、线性层及其他层介绍 P211.线性层2.代码 五、搭建小实战…

Conda快速安装的解决方法(Mamba安装)

如果你的Conda安装了&#xff0c;你可能会发现一个问题&#xff0c;就是使用Conda install 安装某个软件时&#xff0c;会特别慢&#xff0c;这时候呢&#xff1f;你会上网去搜&#xff0c;然后大家解决的方法呢。一是告诉你镜像可以下载快一点&#xff0c;二是&#xff0c;Mam…

基于逻辑回归实现乳腺癌预测(机械学习与大数据)

基于逻辑回归实现乳腺癌预测 将乳腺癌数据集拆分成训练集和测试集&#xff0c;搭建一个逻辑回归模型&#xff0c;对训练集进行训练&#xff0c;然后分别对训练集和测试集进行预测。输出以下结果&#xff1a; 该模型在训练集上的准确率&#xff0c;在测试集上的准确率、召回率和…

hyperf 二十五 数据迁移 一

教程&#xff1a;Hyperf 版本说明 一 生成迁移 php bin/hyperf.php gen:migration create_users_table 执行文件&#xff1a;Hyperf\Database\Commands\Migrations\GenMigrateCommand 功能&#xff1a;创建迁移文件 参数&#xff1a; name 文件名称 选项&#xff1a; c…

Rust 安装与版本更新

Rust 简介 Rust &#xff0c;一门赋予每个人构建可靠且高效软件能力的语言&#xff0c;主打内存安全。 2024年2月&#xff0c;在一份 19 页的报告《回归基础构件&#xff1a;通往安全软件之路》中&#xff0c;白宫国家网络主任办公室&#xff08;ONCD&#xff09;呼吁开发者使…

NoSQL--3.MongoDB配置(Linux版)

目录 2.2 Linux环境下操作 2.2.1 传输MongoDB压缩包到虚拟机&#xff1a; 2.2.2 启动MongoDB服务&#xff1a; 2.2 Linux环境下操作 2.2.1 传输MongoDB压缩包到虚拟机&#xff1a; &#xff08;笔者使用XShell传输&#xff09; 如果不想放在如图的路径&#xff0c;删除操作…

Appium系列(1)安装启动Appium

Appium环境准备 Mac电脑jdk环境AndroidSDK环境node>8.1.0&#xff08;最好用最新版本&#xff09; 安装命令 npm i -g appium安装不成功请检查node 版本是否正确 安装成功命令行输入appium回车查看 安装驱动程序 1、先检查当前驱动情况 通过 appium driver list 进行…

RK356X RK3588 单独编译kernel 与烧录

RK356X RK3588 单独编译kernel 与烧录 可以快速提高我们开发与调试速度 网上可查到的方法如下&#xff1a; RK3568 Android12&#xff1a; 1.添加kernel-4.19/makekernel.sh #!/bin/sh make -j24 ARCHarm64 CC../prebuilts/clang/host/linux-x86/clang-r416183b/bin/clang …

RF接口测试(1)

RF是做接口测试的一个非常方便的工具&#xff0c;我们只需要写好发送报文的脚本&#xff0c;就可以灵活的对接口进行测试。 做接口测试我们需要做如下工作&#xff1a; 1、拼接发送的报文 2、发送请求的方法 3、对结果进行判断 我们先按步骤实现&#xff0c;再进行RF操作的…

比较 2 名无人机驾驶员:借助分析飞得更高

近年来&#xff0c;越来越多的政府和执法机构使用无人机从空中鸟瞰。为了高效执行任务&#xff0c;无人机必须能够快速机动到预定目标。快速机动使它们能够在复杂的环境中航行&#xff0c;并高效地完成任务。成为认证的无人机驾驶员的要求因国家/地区而异&#xff0c;但都要求您…

有一点好看的wordpress外贸独立站模板

手机配件wordpress外贸网站模板 充电器、移动电源、手机膜、手机电池、手机壳、手机转接头等手机配件wordpress外贸网站模板。 https://www.jianzhanpress.com/?p3809 车载电器wordpress外贸网站模板 车载吸尘器、空气净化器、行车记录仪、车载充电器、车载影音导航等车载电…

网络原理TCP_IP

文章目录 应用层自定义协议 传输层udp协议TCP协议1.确认应答2.超时重传3.连接管理建立连接, 三次握手断开连接, 四次挥手tcp的状态 4.滑动窗口5.流量控制6.拥塞控制7.延时应答8.携带应答9.面向字节流10.异常情况 网络层IP协议地址管理路由选择 数据链路层以太网 应用层 自定义…

以创新筑牢安全盾牌,广师大隐盾科技照亮软件知识产权保护之路

“很感谢隐盾科技团队的各位成员对我司计算机软件代码保护的鼎力相助……”广州市硬科技百强企业在给予隐盾科技团队的感谢信中写道。据了解&#xff0c;该公司在使用了隐盾科技团队研发的隐盾代码虚拟化系统后&#xff0c;企业开发盗版率从45%降至0%、保护该企业年侵权成本超过…

redis5种数据类型应用场景

Redis提供了以下五种基本数据类型及其应用场景&#xff1a; 1 , String&#xff08;字符串&#xff09;&#xff1a; 适用场景&#xff1a;用于存储统计网站访问数量、当前在线人数等信息。此外&#xff0c;它也适用于存#### 储JPG图片或者序列化的对象。 2 , Hash&#xff08…

预约自习室

预约自习室 1、技术介绍 自习室预约系统的后端开发语言采用Node&#xff0c;后端开发框架采用Express&#xff0c;数据库采用的Node的最佳搭档MySQL。采用Vue作为前端开发框架&#xff0c;Element-UI作为开发的组件库&#xff0c;微信小程序。期间采用axios实现网页数据获取&a…

精细调度:Apache DolphinScheduler脚本深度解析

在现代数据处理和工作流管理中&#xff0c;Apache DolphinScheduler以其灵活性和强大的调度能力受到开发者的广泛欢迎。 本文将逐步解析DolphinScheduler的关键脚本&#xff0c;希望能提供一个详尽的操作指南&#xff0c;帮助大家掌握安装、配置和操作的每一步。 建立在./bin/e…

精品中国货出海wordpress外贸独立站建站模板

旗袍唐装wordpress外贸网站模板 旗袍、唐装、华服wordpress外贸网站模板&#xff0c;适合做衣服生意的外贸公司官网使用。 https://www.jianzhanpress.com/?p3695 劳动防护wordpress外贸独立站模板 劳动防护wordpress外贸独立站模板&#xff0c;劳动保护、劳动防护用品外贸…