演讲嘉宾简介:
柴武,阿里巴巴高级开发工程师,有多年APM SaaS产品研发经验,曾经使用过多款业界主流时序数据库产品,包括Druid、ClickHouse、InfluxDB等。对时序数据库领域有多年经验,目前负责阿里巴巴TSDB核心引擎开发。
本次直播视频精彩回顾,戳这里!https://yq.aliyun.com/live/863
以下内容根据演讲嘉宾视频分享整理而成。
本次的分享主要围绕以下三个方面:
一、时序业务全景
二、TSDB 介绍
三、核心技术
四、总结展望
一、时序业务全景
TSDB自2016年开始服役,到现在已经三年了,参与了三次阿里巴巴双11大促。2016年是 TSDB 元年,2017年开始在阿里巴巴内部做大规模推广。下图展示了2017年和2018年大促状态下TSDB吞吐表现。写入的峰值从2017年的2000w TPS到2018年有了翻倍的增长,增长到了4000w TPS。查询峰值从8000 QPS转到了2w QPS。这些都是阿里巴巴核心业务的吞吐量情况,日均有800TB的时序数据,累计超过了数百亿的时间线,覆盖了集团130+的业务。
时序业务覆盖场景
时序业务覆盖的场景从基础设施到上层应用,覆盖各个主要系统层面。基础设施层主要负责物理机器和操作系统的监控。基础运维层包括Sunfire,云监控和GOC。Sunfire是阿里巴巴统一监控和日志采集报警系统;云监控是阿里云上统一的监控系统;GOC是全球应急调度指挥系统,包含报警数据,故障定级数据等。资源调度层包含海量的容器,包括现在在服役的集团调度系统以及业界流行的Kubernetes。集群管理层面最突出的是DBPaaS业务,DBPaaS承担阿里巴巴所有数据库实例的监控和调度,每秒的吞吐量在千万量级。上层应用包括IoT场景应用如盒马门店和菜鸟IoT;以及APM场景应用如黄金眼和电商指标监控,还有安全部的核心链路监控等。覆盖的场景从DC到上层的SaaS。
面临的挑战
目前,时序数据库所面临的挑战有很多,包括业务方提出的需求和挑战。如淘宝魔兔这个无线端APM应用,他和终端用户的具体交互行为相关,会遇到高频率,低延迟查询的挑战。另外,大多数OLAP系统和分布式系统都会涉及的长时间,多维度海量数据聚合分析。还有时序数据库特有的发散时间线,比如如何聚合大量时间线?以及双11大促状态下的极高流量冲击,对整个时序数据库容量的挑战是非常大的。
二、TSDB介绍
TSDB架构
阿里巴巴内部TSDB和在阿里云上售卖的TSDB是同一套架构,只是在能力上有所不同。下图从左到右分别是采集端,云端(Server)TSDB,以及更靠近用户的各种协议(可视化,Grafana展示和时序洞察,时序洞察可以将时序数据导入进来直接查看分析)。采集端实现了一套边缘计算的方案。边缘计算主要应用在IoT场景下、资源受限或不稳定的环境下;另外边缘计算与云端TSDB打通,云端TSDB可以直接下发规则,在边缘做数据清洗和计算,最终实现边云一体化。
时序引擎整个架构包含的内容比较多,最核心的是底层TSDB核心的时序引擎,上层包括计算引擎,TSQL引擎和智能分析引擎。底层TSDB核心的时序引擎包含几个模块,时序索引,流式数据的聚合,存储引擎和稳定性管理。时序索引指的是关于时间线的查询和过滤。流式数据的聚合指的是如何在内存里做高效的海量数据的聚合分析。存储引擎提供了时序数据海量数据存储的解决方案。稳定性管理阿里巴巴最看重,即如何保证TSDB能够长时间在集团和云上安全稳定的运行。其中计算引擎是阿里自研的时序流计算引擎,提供了预聚合,降精度(降采样)持续查询的能力,其中持续查询在告警或复杂事件分析场景下用的比较多。TSQL引擎也是阿里自研的,带有分布式执行器和优化器。TSQL引擎能够扩充时序分析的能力,降低用户使用的门槛。智能引擎可以提供一些已训练好或生成好的模型算法库,提供行业定制的解决方案。
TSDB能力对比
动态schema支持。NoSQL数据库基本都支持tags写入,但TimescaleDB基于传统的关系数据库 Postgres,所以不支持动态schema。
多值模型。多值模型在时序场景下能极大地提升写入速度。在监控一个风力发电点的时候,它可能既有风向又有风速,一次性写入两个指标要比单值模型下一次写入一个指标要好很多。另外多值模型对上层的SQL模型更友好,比如做select查询时可以基于多个值做分析等。
时序索引。相对来说,OpenTSDB基于HBase行过滤,没有时序索引。但TSDB,InfluxDB等都构建了时序索引,这样做是为了优化查询的效率。
预聚合和降精度。Facebook Gorrila出来以后,时序压缩开始越来越引起大家关注,针对时序数据的特点做一些压缩,比如时间戳是连续的,数据是稳定的,采用 delta-of-delta 或者 xor 等方式进行时序压缩,最终压缩的效率要比通用压缩提高很多倍。
SQL能力。SQL 接口能够降低用户使用 TSDB 的门槛,可以让熟悉 SQL 的用户直接上手操作时序模型;并且能通过 SQL 扩充时序分析能力等。
集群能力。InfluxDB在开源领域有一些高可用、集群的解决方案,但稳定的高可用方案需要收费的商业版本支持。TimescaleDB目前还在开发过程中。OpenTSDB基于Hadoop生态,所以其可扩展性没有问题。
TSDB给2018年双11补充了哪些弹药。首先在保证稳定性的前提下,提供一套能够满足各个业务方的解决方案。满足高频率低延迟查询、高性能聚合、海量数据低成本存储、海量时间线管理的方案。另外,在功能模块上优化了时序索引,做了一个基于KV存储的索引,可以实现无限时间线的读写。以及参考 Facebook Gorilla做的分布式缓存存储,满足高频率低延迟查询。最后是计算引擎。在技术方面,首先做的也是时序索引优化,流式聚合引擎,预聚合和降精度,工作负载管理,以及自研的时序压缩。
三、核心技术
- 海量时序数据存储
如何解决低成本存储问题?下图是双11阿里内部业务的具体使用场景。DBPaaS专注于阿里巴巴集团内部所有数据库实例监控和分析。其涉及的指标包括底层所有机器,容器,操作系统以及上层各种数据库实例指标。所有指标存在一套数据库里面,可以做统一的查询和分析,而且DBPaaS保存了历年双11数据库表现性能的数据,每一年双11当天的详细数据都在一套数据库里。DBPaaS业务带来的挑战实际上是非常大的,首先因为DBPaaS监控的是所有数据库实例,这些实时监控指标要纳入双11光明顶大屏,也就是阿里巴巴核心作战指挥室大屏,如何保证准确、及时、稳定的大屏展示就给 TSDB 带来了极大挑战;另外,日常写入均值是1000w TPS,到了双11峰值达到1400w+ TPS,如此大量的数据怎么存储。最后每天新增数据达数百TB,数据的保存本身就是一个挑战。
时序数据压缩。下图左边是一个表格,每一行代表一个时间序列,与OpenTSDB中表结构一样。由于时序模型比较单一,KV基本上都是类似设计。0到3600代表过去一小时的数据,数据是秒级采集的,也就是说一行数据一共有3600列,每列都有一个值。对于OpenTSDB来说整个存储没有压缩。如果是毫秒级,一列需要360w秒,当然时间窗口是可以调的,但总的来说是受限制的。阿里在存储层参考Facebook Gorilla的思想,引入了时序压缩算法。通过列合并的方式将所有时间戳和value分别聚合成两个大的数据块,之后对数据块应用时序压缩算法,接着底层KV存储会使用通用的块压缩进行压缩。整体压缩率可以达到15:1,这里压缩率是根据线上真实的业务数据计算出来的。具体的压缩算法如下,时间戳使用了delta-delta,浮点型用了XOR编码,整型用了简单的variable length encoding,字符串使用通用压缩。需要说明一点。因为阿里内部有明确需求,所以不会使用有损压缩,但是这些算法实际上是支持的。
下图是真实业务场景下的数据压缩效果。压缩前数据有6T,使用通用的块压缩,压缩完的结果是715G,不到1/10。时序压缩和块压缩一起应用的场景下可以到413G,整个压缩效率可以达到15:1左右。时序压缩加块压缩相比块压缩仍有40%的提升,这对于存储成本的降低是有很大意义的。另一个好处就是时序压缩在块压缩之前,做完时序压缩数据体积已经很小了,块压缩效率也不会受到影响。在大查询场景下,rt降低一半,当做长时间范围scan时,数据已经被高度压缩,IO效率很高,rt可以降低一半。
预聚合和降精度
数据降采样,多层级时间缩放。比如给客户做一个报表,这个报表有多个时间层级,给客户看过去一年,一个月或一周不同粒度的详细数据,这是一个下钻的过程。如果直接使用TSDB从详细数据做聚合的话用户体验很差,响应时间可能特别长。
海量数据的聚合,统计分析。对过去半年的数据做sum 、min、max操作,甚至做P99,P55分位的统计。这种情况下计算量特别大,如果直接从详细数据里聚合也是不可行的。
时间线的Join。统计交易量的成功数量,失败数量和总量,并且计算其成功比率等。因为整个数据的采集是成体系的从采集端到展示端,直接修改采集端的采集来源可能不太灵活,因此需要引擎支持多个时间线做 join 计算。
实时异常检测,实时计算。给整个运维大屏提供准确,及时的数据,或者将异常的点发送给客户做报警等。
下图是计算引擎和存储引擎一起提供的解决方案。首先阿里有一套自研的时序流计算引擎。考虑到TSDB团队既要输出阿里云公有云客户,也要输出阿里巴巴集团内部客户,还要输出专有云客户。在不同场景下部署资源是受限的。我们基于 Apache Beam,设计了一套自研的时序流计算引擎的语义的框架。底层可以支持Flink,Spark,JVM内存,在大规模或小规模场景下都能做计算。在此基础上,时序流计算引擎提供了持续查询能力,可以提供持续查询的视图,做报警或者复杂事件分析时可以直接查询、分析数据流中的时序数据。时序流计算引擎和TSDB是打通的,用户的数据写进来之后,一部分数据转发给流计算引擎。用户可以和TSDB交互制定策略来决定哪些数据需要降采样,哪些数据需要预聚合。另外可以制定一些报警的规则,下发给TSDB,然后TSDB将规则下发给时序流计算的持续查询,最终实现报警。TSDB写入的是详细数据,时序流计算写入的是概要数据,就是降采样或预聚合以后的数据。TSDB端做查询时用户可以查询预聚合数据。上层支持包括各种聚合算子,如 min,max,sum,count,p99,P95 和中位数分位统计等,多个时间线之间的Join,乱序数据和重复数据的写入等。
2.高频、低延迟查询
淘宝魔兔支撑着阿里内部500+移动端应用无线数据的分析和监控,是一个Mobile APM 场景的应用。Mobile APM的特点是读写吞吐与用户的交互相关,属于事件型时序数据。比如双11大促的某一刻突然有一个活动上来,用户集中访问应用中的某个功能时,会产生成倍的突发流量。双 11 监控到的淘宝魔兔的查询峰值达到了4000 QPS,下图能够看到写入流量由均值 60万 TPS 飙升到峰值600万 TPS 左右,约有10倍的流量冲击。另外,业务方根据 TSDB 而制定的一些实时的策略和决策会直接影响移动端应用的用户体验,所以业务方要求TSDB rt在20ms以内。在这样的场景下,传统TSDB,比如 OpenTSDB在查HBASE时IO路径是非常长的,整个查询中会发生很多抖动和毛刺。读写rt P99分布在20ms内对OLAP系统来说是很难达到的。
为了支持高频、低延迟查询,我们参考Facebook Gorilla 设计了基于Java的分布式缓存方案,集群基于Zookeeper实现分片和容量调整,可以实现动态的扩容和缩容。整个双11下来支撑了1000w+TPS写入和 10 倍流量冲击。其中最关键的是TSMem节点的设计。TSMem首先要解决两个问题,一是如何实现如此高的吞吐。二是怎么保证查询99% 的 rt 都维持在20ms以内,保持极低的延迟。TSMem 基于Disruptor 框架,将用户并发读写的请求在 RingBuffer里做暂存。采用多个生产者,一个消费者模式。一个消费者在消费到用户请求后,会将请求分发到对应的 worker线程。Worker线程池里面每一个线程对应一个时序缓存分片,所以实际上是基于Disruptor 做了内存 sharding。一个 worker 线程对应一个shard,这样的好处不用考虑锁或其它资源的竞争。另外值得注意的是把写请求和读请求都分配到同一个请求的链路上来,由同一个worker线程同时处理,可以实现无锁的读写。另外利用RingBuffer的batching特性,一个简单的写入或小批量的写入通过RingBuffer之后可以积攒成一个大的batch,然后在worker线程里做一次批量操作,可以极大提升吞吐量。另外一个的问题怎么保证高效的内存管理和极低毛刺的rt。首先要降低JVM GC 的影响,把所有的时序数据存在时序数据块中,在内存里做基于引用计数的chunk池化管理。这样做的好处是没有过多临时对象的创建,所以整个 GC 很平稳。减少了大量数据块的创建和开销。也会抹平掉在极端条件下突然申请一个新的很大的时序块所造成的延迟的抖动。
3.高效聚合分析
Sunfire是阿里统一的日志和基础监控报警平台。整个平台覆盖了集团内部5w+的应用。监控指标覆盖从基础设施到上层应用,包括IaaS,PaaS,SaaS以及无线应用。这个场景带来的挑战是由于覆盖的应用特别多,业务复杂,数据体量大,因此每秒扫描的时序数据量特别大。比如,在大促时某个业务要做提前的扩容,上一批新的机器就相当于一批新的时间序列的创建。最高的情况下可以达到每秒几十万时间线的创建。下图展示的是在某一天有一批新的机器上线后的整个消费过程。累计的时间线在大促当天统计达到60亿,而且还在不停增长。如何解决每秒扫500w时间点?如果在OpenTSDB内存里做聚合计算直接响应用户查询,需要把所有点堆在内存中,这会给系统造成极大的不稳定因素。另外一个是时间线创建的速度。比如说 OpenTSDB 是基于UID表的,那字典表的原子操作也会有一个性能瓶颈,大概是20w TPS,这个瓶颈也会阻止业务的发展。
时序索引
高维聚合分析涉及到TSDB引擎两个内部的模块。流式聚合引擎和时序索引。时序索引包括两部分内容,一部分是构建出来的索引,另一部分索引的评估器。时序索引整个查询流程如下图,首先会解析查询,然后通过评估器给查询做优化,最终会把查询具体执行的步骤交给时序索引进行查询,最终返回时间线。然后流式聚合引擎会根据查询出的时间线从底层时序数据存储中把查询时间范围内的时序数据全部提取上来,最终通过降采样、预聚合计算后返回给用户。
下图展示的是时间线的生命周期图。在不同阶段有的时间线会消亡,有的时间线会创建出来。用户在查询t2~t3时间范围的时序数据的时候,不会希望查到t0~t2时间范围内已经消亡的时间线。因为多一条时间线,在流式聚合引擎去底层存储捞数据点的时候就会多一次IO 操作。之前的存储在InfluxDB 1.3之前是全内存的时间线索引。全内存的时间线索引不会对时间范围做筛选,在用户查询t2~t3的数据的时候,会返回所有的时间线,InfluxDB 1.3之后有基于文件的索引之后,可以直接返回这两条时间线,性能提升很多。
与InfluxDB创建落盘的时序索引的出发点一样,我们 TSDB 基于KV做了一套落盘的索引,其本质上就是倒排索引。时序索引的一个特性是给倒排索引增加了时间戳。在倒排基础上增加了时间戳后,索引查询时支持首先根据tag和value过滤出目标时间线,接着根据时间维度再做一次筛选,最终过滤效果会好很多。另外把整个倒排索引持久化到KV存储总,这样索引节点可以实现无状态运行,支持水平扩展,并支持时间线的TTL。
下图是时序索引的评估器,评估器要做的事情就是在用户查询时序索引时实现更高的查询效率。评估器的数据来源包括 HyperLogLog 计数器,比如倒排里面某个tag或者整个倒排究竟有多少时间线;另外还来自 BloomFilter,记录某个时间线究竟是否存在;另外评估器的数据来自内存里面的时序索引缓存。评估器在查询的时候首先会选择整个倒排里面较小的集合进行运算,并支持对运算查询条件的优先级排序。如用户提供了等于查询或模糊匹配时,我们会首先执行确定性更强的等于查询,当然同时也要比较集合的大小。比如用户查询提供了两个条件,分别是机房维度和IP维度,评估器首先判断要优先查询IP维度,因为IP维度对应的 tag 包含的时间线更多,过滤时效率会更高。因此,BloomFilter和HLL虽然是粗略的统计,但在两个查询条件涉及的集合存在数量级差别时,依然能有效提高查询效率。另外比如如果BloomFilter 反馈时间线不存在,那整个查询就可以立即终止。!
流式聚合引擎
前面介绍的预聚合和降采样是在数据写入TSDB之前进行的,流式聚合引擎是TSDB进程内部的用户查询时的聚合和计算的引擎。流式聚合引擎基于pipeline 方案设计,整个 pipeline 包含有不同的步骤,它提供10+核心聚合算子,20+ 填充策略,10+插值算法。可以把用户的复杂查询转化成一些简单的算子组合,转换的结果可以保证整个查询结果准确性。前面提到的时序索引查到时间线后会交给流式聚合引擎,从时序数据存储里面将具体的时间序列捞出来,根据用户的查询条件做降采样,或者缺点填充,聚合操作等。整个pipeline里其实不止图上列出的几类算子,还包括 topN、limit、插值等算子,采用松耦合方式设计,扩展性很好。另外整个pipeline从数据库捞数据时,是以小批量的方式捞出来,然后再交给流式引擎里面其它算子。本质上是一个火山模型。捞出来的小批量数据在内存里面是以列式存储,每一个算子计算性能很高。另外内存里的流式聚合引擎可以与写入 TSDB 之前做的预聚合和降精度生成的结果做无缝衔接。假设降采样提前计算出五分钟粒度的数据并写入 TSDB,此时如果用户的查询刚好是五分钟粒度降采样查询,那么流式计算引擎就不需要从时序数据库里面捞详细数据进行计算,而是直接捞五分钟粒度的数据做进一步迭代计算即可。所以说整个TSDB和计算引擎是打通的。
- 稳定性保障
工作负载管理
因为TSDB既要提供集团内部和专有云客户,同时也要在公有云上服务外部客户,所以稳定性是非常重要的。TSDB 从三个层面做了稳定性和安全层面的保障。第一是资源隔离。第二是做时间线和时序数据细粒度的流控。最后是全面的指标监控。
资源隔离。主要是读写线程的分离,保证查询的链路突然有故障时不会影响写入,写入链路有故障的时候也不会影响查询。另外是慢查询和大查询的资源隔离。根据用户提供的查询条件,计算一个指纹,通过指纹和历史查询记录,可以判断是不是一个大查询或者慢查询。如果是慢查询,TSDB会直接将该查询放入一个单独的隔离队列里面,该队列是资源受限的。假如是一个正常查询,TSDB 就会将当期查询放到资源更加充足的队列里面,从一定程度上可以加速整个查询。
全面监控指标。包括TSDB整体吞吐量,响应时间,IO层面的关键指标,还包括各个核心模块如时序索引模块或者流式聚合模块的核心指标。可以很清晰,快速地了解到TSDB内部究竟发生了什么,快速定位客户的问题。
时间线和时序数据细粒度的流控。端到端流控目的是在突发流量场景下或用户负载突然增加时,保护引擎不会受到影响甚至 crash。首先,TSDB 会在读写入口做IO线程的资源控制。其次会在 TSDB 内部两个大的核心模块的入口和IO出口处对流量做一个控制。另外,流控的维度非常多,比如可以针对时间线模型进行流量控制。时间线过多的时候,说明该业务在设计时序模型时可能是有问题的,需要做预聚合之类,降低查询覆盖的时间线。其他维度,诸如查询覆盖的时序数据点数量,IO层面如吞吐量等,以及整个查询耗时统计等。
四、总结和展望
上面提到的几个场景都是 TSDB 在 2018年已经解决或者正在解决的问题。接下来介绍下,TSDB要往那些方向发展,要做些什么功能、特性,满足哪些需求。第一个是冷热数据的异构存储,其目的就是降低用户的成本。因为现在数据价值越来越受到重视,最好能把用户的详细数据给长久保存下来,因此需要提供一个详细数据、长时间的存储解决方案,比如跟阿里云OSS打通等。第二个是Serverless的读写能力。Serverless读写能力实现之后,可以让TSDB有全域的分析计算能力。全域分析计算能力指的是首先高频低延迟的短时间的查询,另外是OLAB系统长时间高维度的聚合分析,然后是历史详细数据或历史某一段时间数据的分析。历史数据怎么分析,或者冷数据怎么分析都是Serverless来解决的。Serverless还可以降低计算,查询,写入等的成本,降低客户成本。第三是拥抱时序生态。比如说学习和借鉴Prometheus 系统设计或者其他商用 TSDB 和监控解决方案,以及拥抱开源社区,提供高可用、稳定的适配和替代方案,把 TSDB 的优势,如流式计算、时序索引、计算引擎或SQL引擎等等提供出来,给客户一个更好的解决方案。然后是时序智能分析,希望能够做更多的稳定、可靠的模型,深入到行业内部给客户解决一些具体问题。