全文 3286 字,预计浏览工夫 7 分钟
一、背景
百度广告业务零碎建设在分布式系统之上,面向商业服务,每天产生各类接口调用 PV 达到百亿次,产生 TB 级的监控数据,对监控零碎的设计也提出了微小的挑战。分位值对接口性能的敏感度高,在性能剖析中具备很大价值。
1.1 分位值是什么
分位值是一组数据中排名在某个百分比的值。如:开机时 360 提醒“您的电脑击败了全国 80% 的用户”,即代表启动工夫在全国所有电脑中排名 20% 分位值。
1.2 Why 分位值?
在接口性能剖析中,分位值至关重要。因为许多极其申请都集中在 99% 分位值以上,数量少但影响大,通过平均值无奈察看到。99% 的失常申请会把 1% 的极其数字均匀掉,导致看起来零碎响应很快。但这些多数极其申请会造成 1% 用户极为不好的用户体验。
二、分位值常见计算计划
2.1 流式计算
实时采集数据样本,上传到 Spark,Flink 等计算集群,进行流式计算。
- 长处 :最高能够失去 100% 准确的分位值;
- 毛病 :在百亿级场景下,将全量数据导入计算集群,耗费资源微小,老本极高。不实用监控场景。
2.2 离线计算
离线计算,将数据间接导入数仓,再由定时进行工作批量计算分位值。
对于 APM 线上监控的场景,对实时性要求较高,不实用离线计算架构。
2.3 压测端计算
应用 JMeter,LoadRunner 等压测工具,在压测过程中采集数据样本,实时排序,即时计算。
- 长处 :精度高,实时性强;
- 毛病 :但局限于单个利用,压测阶段。规模无限,且没有长周期的变化趋势等剖析能力。
2.4 即席查问计算
如 Prometheus 等监控工具,可收集各个实例数据样本,在须要查问分位值时,再即时计算。
- 长处 :节约计算资源,可按需计算,灵活性强;
- 毛病 :消耗存储资源,尤其是在百亿级场景下,存储数据结构的选取大幅影响资源开销和即席查问响应工夫,对技术可行性有决定性影响。
三、分而治之的计算架构
3.1 分而治之
分而治之是大数据计算的基本思路。然而分位值如何归并,是分而治之的重点难题。分位值的特点决定了分位值不能简略地分治计算再归并。与平均值不能再求均匀同理,同一个利用的多个实例求得的分位值再求均匀没有数学意义,不能代表集群整体的分位值。
既然分位值自身不能归并,那么原始数据能够归并吗?当然是能够的。既然原始数据能够归并,那么原始数据的摘要能够归并吗?也是能够的。
解释 :摘要是对原数据样本的一个数据分布的形象,能够在肯定误差内,等同于原数据样本。常见的数据摘要算法有,直方图,T-Digest,GK 算法等。
3.2 采集端聚合
基于数据摘要,咱们能够在各个实例本地保护一个数据分布(即摘要),每次失去一个申请耗时样本数据,就更新数据分布,在本地实现一次聚合。每隔固定周期将本地聚合的数据分布上传到数据仓库。
「这是第一次聚合」,能够将单个实例每小时数百万次申请,压缩成占用几十 kb 的数据分布,大幅升高数据规模,使承载百亿级场景成为可能。
3.3 汇聚层归并
在数据仓库中存储各个实例上传的数据分布,不进行计算。直到有用户查问某个接口的分位值数据时,才筛选出该接口下的所有数据分布,归并成一个数据分布,再用该数据分布推算出分位值。
「这是二次聚合」,假如一个接口有 100 台实例,每小时采集一次,则一天只有 2400 个数据分布。归并 2400 个数据分布,在 0.1s 内就能够实现。
通过两级聚合,可将计算开销摊派至数万实例上,对业务性能简直没有影响,又无需引入额定计算资源。联合即席计算的劣势,可实现秒级查问,和高度灵活性,高度合乎 APM 场景。
四、具体实现
总体架构如下图:
▲总体架构
原理具体分为如下步骤:
- 「接口拦挡」 在接口调用时进行拦挡,获取接口响应工夫;
- 「端上聚合」 将拦挡到的响应工夫聚合进数据分布中,每达到聚合工夫区间后,将本地的数据分布上传到数据仓库,而后清空数据分布;
- 「二次聚合」 在数据仓库端,对各个实例上传的数据分布按接口名进行二次聚合,按每个接口别离合并成接口总数据分布,从而推算接口总分位值。
Step1. 接口拦挡
在接口拦挡阶段,须要实现拦挡利用的各个接口,在接口执行前后执行监测逻辑,从而计算出接口的响应工夫,而后将响应工夫发送到数据分布,以进行后续聚合逻辑。具体逻辑如下图:
▲接口拦挡
接口拦挡的具体技术能够通过手工埋点、Java 字节码加强等形式来实现。
Step2. 端上聚合
数据分布是对接口响应工夫数据样本的摘要,用来在前面的环节中近似估算分位值。数据分布须要满足如下特色的数据结构:
- 形容原数据样本的散布构造
- 可接管新的数据样本,调整数据分布
- 合乎结合律,即多个数据分布能够合并成一个总的数据分布
- 能够用数据分布估算出原数据样本的近似分位值
- 应用常数大小内存空间,且精度可控
数据分布的具体实现有很多种,如 直方图,T-Digest,Q-Digest,DK 算法 等。分位值的精度取决于数据分布算法选型,咱们在实践中选用 T -Digest 构造。
每次拦挡到接口调用后,获取到本次调用的相应工夫,而后更新本接口的数据分布。流程如下:
▲更新散布
因为每个利用实例上会蕴含若干个(几十到上百个)接口。对于每个接口咱们须要别离记录响应工夫的数据分布。咱们利用一个表格数据结构来存储各个接口的数据分布。聚合项存储数据结构:
实例元信息:
- 「利用名:app1」
- 「实例:instance1 (10.20.30.40)」
- 「聚合开始工夫:2020-10-10 18:00:00」
- 「聚合周期:1h」
- 「下次提交工夫:2020-10-10 19:00:00」
聚合信息:
当采集到数据样本时,先依据接口名,在上述表格中找到接口对应的行(如果没有则新建一行),而后将数据样本(即本次调用响应工夫)合并进接口名对应的数据分布中。流程如下图:
聚合
利用实例在本地别离记录各个接口和其响应工夫的数据分布。每达到既定工夫后,将上表全部内容发送到数据仓库,并清空本地表格。流程如下:
上传
数据分布数据为内存中的二进制数据,在上传的过程中须要进行序列化。序列化的具体实现个别举荐如下解决:
- 「采纳小端格局」数据仓库多为 C ++ 实现。如果抉择 C /C++ 实现的数据仓库,则需采纳小端格局序列化。因为 x86 架构基于小端格局,序列化数据保持一致格局,不便 C /C++ 解析。如果采纳 Java 实现或其它大端格局的数仓(如 Hive),则无需采纳小端格局。实际中,咱们采纳百度自研的 Apache Doris 数仓,并应用 C ++ 开发分位值二次聚合算子。
- 「压缩」因为接口响应工夫样本数据往往具备强偏差性,数据分布数据结构外部会存在大量零值,启用压缩能够显著压缩数据体积,减小网络传输和存储资源占用。具体压缩算法能够采纳 GZIP,BZIP2 等。实际中咱们采纳 GZIP 算法,压缩比率在 30%-40% 左右。
- 「编码」因为直方图数据自身是二进制格局,通过例如 BASE64 等算法编码成文本格式,更加易于传输、存储和调试。实际中,BASE64 编码对体积有 20% 左右减少,但存储空间绝对便宜,相比带来的劣势,能够承受。
Step3. 二次聚合
数据仓库中存储了分布式系统中所有接口的响应工夫直方图。大体表构造如下:
为了计算某个接口的响应工夫分位值 p,咱们须要将各个实例上传的该接口的数据分布聚合项做二次聚合,用二次聚合后的数据分布聚合项来计算分位值 p,则此分位值即代表该接口在整个利用集群(所有实例)上的总分位值。
▲二次聚合
这里分位值 p 是由用户查问时实时指定的。也就是说,每次计算分位值的时候,都能够反对任意分位值的计算,而不是预设的分位值。咱们的 T -Digest 构造在百亿数据下每日 1GB 左右数仓存储,最高精度 0.1% 左右。
五、技术长处
总体架构简略,性能高,老本高度可控,易于保护,稳固,危险低,多快好省地满足线上系统监控分位值计算场景。同时对于其它大数据分位值需要场景,也是一种十分优良的参考计划。
举荐浏览 :
当技术重构遇上 DDD,如何实现业务、技术双赢?
接口文档主动更改?百度程序员开发效率 MAX 的秘诀
技术揭秘!百度搜寻中台低代码的摸索与实际
百度智能云实战——动态文件 CDN 减速
化繁为简 – 百度智能小程序主数据架构实战总结
百度搜寻中台海量数据管理的云原生和智能化实际
百度搜寻中“泥沙俱下”的加盟信息,如何靠 AI 解决?
———- END ———-
百度 Geek 说
百度官网技术公众号上线啦!
技术干货 · 行业资讯 · 线上沙龙 · 行业大会
招聘信息 · 内推信息 · 技术书籍 · 百度周边