微信海量数据查询如何从1000ms降到100ms?

导读
微信的多维指标监控平台 , 具备自定义维度、指标的监控能力 , 主要服务于用户自定义监控 。作为框架级监控的补充 , 它承载着聚合前 45亿/min、4万亿/天的数据量 。当前 , 针对数据层的查询请求也达到了峰值 40万/min , 3亿/天 。较大的查询请求使得数据查询遇到了性能瓶颈:查询平均耗时 > 1000ms , 失败率居高不下 。针对这些问题 , 微信团队对数据层查询接口进行了针对性的优化来满足上述场景 , 将平均查询速度从1000ms+优化到了100ms级别 。本文为各位分享优化过程 , 希望对你有用!
目录
1 背景介绍
2 优化分析
2.1 用户查询行为分析
2.2 数据层架构
2.3 为什么查询会慢
3 优化方案设计
3.1 拆分子查询请求
3.2 拆分子查询请求+redis Cache
3.3 更进一步-子维度表
4 优化成果
4.1 缓存命中率>85%
4.2 查询耗时优化至 100ms
5 结语
 
01
 
背景介绍
 
微信多维指标监控平台(以下简称多维监控) , 是具备灵活的数据上报方式、提供维度交叉分析的实时监控平台 。
 
在这里 , 最核心的概念是“协议”、“维度”与“指标” 。例如 , 如果想要对某个【省份】、【城市】、【运营商】的接口【错误码】进行监控 , 监控目标是统计接口的【平均耗时】和【上报量】 。在这里 , 省份、城市、运营商、错误码 , 这些描述监控目标属性的可枚举字段称之为“维度” , 而【上报量】、【平均耗时】等依赖“聚合计算”结果的数据值 , 称之为“指标” 。而承载这些指标和维度的数据表 , 叫做“协议” 。
 
多维监控对外提供 2 种 API:
 

  • 维度枚举查询:用于查询某一段时间内 , 一个或多个维度的排列组合以及其对应的指标值 。它反映的是各维度分布“总量”的概念 , 可以“聚合” , 也可以“展开” , 或者固定维度对其它维度进行“下钻” 。数据可以直接生成柱状图、饼图等 。
  • 时间序列查询:用于查询某些维度条件在某个时间范围的指标值序列 。可以展示为一个时序曲线图 , 横坐标为时间 , 纵坐标为指标值 。
  •  
然而 , 不管是用户还是团队自己使用多维监控平台的时候 , 都能感受到明显的卡顿 。主要表现在看监控图像或者是查看监控曲线 , 都会经过长时间的数据加载 。
 
团队意识到 , 这是数据量上升必然带来的瓶颈 。目前 , 多维监控平台已经接入了数千张协议表 , 每张表的特点都不同 。维度组合、指标量、上报量也不同 。针对大量数据的实时聚合以及 OLAP 分析 , 数据层的性能瓶颈越发明显 , 严重影响了用户体验 。于是这让团队人员不由得开始思考:难道要一直放任它慢下去吗?答案当然是否定的 。因此 , 微信团队针对数据层的查询进行了优化 。
 
02
 
优化分析
 
2.1 用户查询行为分析 
要优化 , 首先需要了解用户的查询习惯 , 这里的用户包含了页面用户和异常检测服务 。于是微信团队尽可能多地上报用户使用多维监控平台的习惯 , 包括但不限于:常用的查询类型、每个协议表的查询维度和查询指标、查询量、失败量、耗时数据等 。
 
在分析了用户的查询习惯后 , 有了以下发现:
 
  • 【时间序列】查询占比 99% 以上
出现如此悬殊的比例可能是因为:调用一次维度枚举 , 即可获取所关心的各个维度 。但是针对每个维度组合值 , 无论是页面还是异常检测都会在查询维度对应的多条时间序列曲线中 , 从而出现「时间序列查询」比例远远高于「维度枚举查询」 。
 
  • 针对1天前的查询占比约 90%
出现这个现象可能是因为每个页面数据都会带上几天前的数据对比来展示 。异常检测模块每次会对比大约 7 天数据的曲线 , 造成了对大量的非实时数据进行查询 。


推荐阅读