小米正用时序数据库OpenTSDB,解决这个“硬核”问题

作者 | 许俊红

来源 | 小米云技术(id:mi-cloud-tech)

 

时序数据

根据维基百科[1]的定义,时间序列是按照时间发生的顺序排列的一组数据点序列。时间序列数据库(TSDB)是存储时间序列数据的数据库。近年来,随着物联网等概念的普及,TSDB已经成为数据库中一个相对独立的子领域,越来越受到重视。广泛应用于物联网、监控系统、金融、医疗、零售等各种场景。

时序数据

 

除了具备一般数据的共同特点外,受限于时间的因素,时序数据有很多独有的特点:

 

  • 数据通常按照时间顺序抵达

  • 抵达的数据几乎总是作为新条目被记录

  • 数据写入QPS通常远远大于读取QPS,而且读操作往往基于指标(即metric)读取与之相关的一簇数据

  • 数据写入速度通常比较平稳,无明显的波峰和波谷

  • 相邻数据之间通常具有一定的相似性

  • 在多数情况下,时序数据的价值会随着时间的推移而迅速下降

 

根据上述特点,时序数据系统设计有以下考虑:

 

  • 同一指标相关的数据最好分布在一起

  • 写操作侧重于高吞吐,读操作侧重于低延时

  • 因为时序数据的值都是数值,且前后有较大的相似性,因此数据压缩是有意义的,往往能显著提高读写效率,节约空间和其他成本

TSDB

如前所述,目前,时间序列数据库普遍受到重视,各种TSDB层出不穷[2]。图1是著名数据库排名网站db-engine[3]近两年的数据库趋势排名,其中TSDB的增速最为明显。时间序列数据由于其独有的特点,很少直接用于关系数据库或NoSQL数据库,而是独立设计、优化和实现。

 

小米正用时序数据库OpenTSDB,解决这个“硬核”问题

图1 过去两年数据库趋势排名(2019年3月)

OpenTSDB

OpenTSDB是一个可扩展的TSDB,可以在不降低准确性的情况下存储和处理海量数据。其结构如图2 [4]所示。该图以监控这一常见场景为例,展示了各部分之间的关系。服务器节点是被监控的服务器,通常为OpenTSDB提供一个HTTP接口来调用和收集状态信息。

TSD是OpenTSDB的一个实例。其内部结构用空心箭头表示,主要分为两部分。一部分是Netty,用来读取用户的请求,返回用户操作的结果。另一部分是异步回调调用链。这些回调的主要作用是将用户参数转换为hbase客户端的scan或put参数,包括参数验证和转换、HBase客户端参数设置、读操作时的过滤器设置,最后通过异步客户端读写HBase集群。这两部分都是异步的,这使得OpenTSDB能够以相对较低的资源消耗保证高吞吐量。此外,OpenTSDB还提供了其他工具来方便用户交互和维护。

 

小米正用时序数据库OpenTSDB,解决这个“硬核”问题

图2 OpenTSDB系统架构图

 

关于OpenTSDB,大家比较关注的有Row key设计、compaction等几个方面。

RowKey设计

 

OpenTSDB使用外部NoSQL存储引擎存储数据,支持HBase、BigTable等。由于NoSQL往往以无模式或半模式的键值形式存储,其行键的设计对读写性能有着非常重要的影响。这里以应用最广泛的HBase存储引擎为例进行分析。

 

行键的数据模型如图3所示[5]。第一个字节指示盐化是否打开,然后三个字节指示公制,接下来的四个字节指示数据时间戳,最后是数据的几个标签。默认情况下,OpenTSDB最多允许八个标记键。另外需要注意的是,每个度量和标签的uid实际上是存储在HBase的数据表中的,即OpenTSDB将度量映射成固定的字节id(即UID)存储在HBase的另一个表中,用UID来标识数据表中的某个度量或标签,以节省空间。

 

小米正用时序数据库OpenTSDB,解决这个“硬核”问题

图3 OpenTSDB存储在HBase中的Row Key设计

 

除了通过uid节约存储空间外,row key的构成也是很有趣的,即metric + timestamp + tagk1 + tagv1…,采用这种顺序,是为了访问模式和性能的考虑:

 

  • 首先,timestamp 不适合作为前缀。timestamp作为前缀容易造成热点问题,而且对于多数较大时间跨度的查询都需要对这段时间内的绝大多数数据做扫描,效率比较低下。

  • 其次,tag 也不适合作为前缀。tag作为前缀避免了热点问题,但无法避免查询的低效。主要原因是用户关心的是以包含metric的一簇数据,如果使用metric作为前缀,不但避免了热点问题,还能大大缩小扫描数据的范围。

  • 再次,timestamp应该放在tag之前。前面两点决定了必须以metric为前缀,那么如果tag放在timestamp前面有什么坏处呢?这里必须提到OpenTSDB设计的初衷。对于时序数据而言,我们不可能在保证高性能的情况下,同时满足高精度、长时间跨度和多标签(即tag)的查询。不同的TSDB对此有不同的折中。OpenTSDB选择限制tag(限制tag key数量,虽然可以配置)以保证比较长的时间跨度。因此,tag的筛选度低于时间这一因素,也就是说timestamp应该放在tag前面。

 

另外,这里的timestamp是整点小时的时间戳。qualifier是事件发生的时间戳相对整点时间的偏移,分为秒、毫秒和秒与毫秒混合三种类型。在某些场景下(比如下文的compaction),qualifier也支持将多个时间戳拼接在一起,构成一个qualifier,与拼接的value值一一对应。图4以秒为例展示了整个HBase数据表的结构[6]

 

小米正用时序数据库OpenTSDB,解决这个“硬核”问题

图4 OpenTSDB存储在HBase中的数据表结构

Compaction

 

OpenTSDB compaction是把存储在HBase数据表中的每一行中的多个qualifier按照时间顺序拼接成一个qualifier,多个value拼接成一个value,以节约存储空间、提高查询效率。这一设计,主要基于以下事实:

 

  • 由于时序数据的特点,用户很少会只读取某一个时刻的数据,往往是读取一个时序序列,实际上OpenTSDB也没有API提供对某一特定时间点的读操作。

  • 存储引擎HBase对每个时间点的存储格式是row key + column family + qualifier + value(略去无关内容)。显然,对于每行的多列数据来说,row key、column family是冗余的

 

压缩的实现是一个单独的线程从HBase中读出每一行数据,然后合并这些数据,写入一个新的限定符和对应的值,最后从HBase中删除过期的数据。这个过程增加了HBase客户端和HBase服务器的负载,会造成HBase的性能抖动。一般在生产环境中关闭该功能,或者在时序数据库物理资源消耗比较低的时候可以定期进行压缩,以达到数据压缩的目的。

最佳实践

 

OpenTSDB作为一款高性能TSDB,有很多优点,但使用不当也会造成预料之外的后果,以下是一些实践上的参考:

 

  • 优化HBase:在很多情况下,HBase是读写处理流程的核心,也是耗时最多的环节,优化OpenTSDB首先要优化HBase。这些措施包括调整BlockCache、优化GC和开启压缩等。优化HBase本身是一个复杂的话题,这里不展开。

  • 使用explicitTags:对于基数(Cardinality)比较高的tag来说,使用explicitTags时,OpenTSDB会为HBase Client添加一个额外的过滤器Fuzzy Filter,使筛选过程更高效;对于多个tag的metric,使用explicitTags能过滤掉多余的数据,保证结果正确。

  • 启用盐化:启用盐化之后,OpenTSDB会启动多个线程并发对请求进行处理,降低请求的延时。

  • 控制tag的状态空间:合理选择tag,使所有tag的组合数不要过大。如前所述,tag key状态空间过大会导致HBase RegionServer的scan操作加载过多的无关数据,导致响应缓慢。Tag key的最大个数是可以配置的,谨慎考虑改变这个配置项。

小米时序数据库服务

我们使用Kubernetes解决时间序列服务的申请、创建、扩展、删除等繁琐流程,快速响应流量突变的需求,提高效率,节约成本。其结构如图5所示。整个结构分为两部分,一部分是OpenTSDB的管理系统,另一部分是OpenTSDB集群。两者都运行在Kubernetes的Pod中,应用程序状态由Kubernetes维护。

OpenTSDB管理系统负责创建、编辑和删除OpenTSDB集群、监控等管理功能。系统与公司内部的身份认证系统连接,赋予不同的角色不同的权限。管理系统有三个作用:

 

  • 一种是普通用户,可以使用所属的OpenTSDB资源进行读写,还可以通过管理系统查看本集群的信息,比如读写QPS、所占用的空间等信息。

     

  • 另一种是管理员权限,可以申请、编辑和删除集群,集中管理某个具体业务线的OpenTSDB资源。

     

  • 还有一种是超级管理员,负责审批资源和其他一切权限。整个流程只需线上操作,申请通过后,一般在一分钟之内OpenTSDB集群即可创建成功,并自动生成可供用户读写的域名。用户根据OpenTSDB协议即可进行读写操作。整个过程避免了用户申请物理机器和域名、搭建集群、监控和维护集群状态等繁琐的线上线下操作,大大提高了效率。

 

另一部分是OpenTSDB的读写系统。用户可以通过域名读写OpenTSDB,OpenTSDB集群自然继承了Kubernetes服务治理的一整套机制和工具,包括日志记录、监控、自动重启等。我们还将为每个OpenTSDB集群提供相应的图形访问和监控界面Grafana。对于用户来说,访问部署在Kubernetes上的OpenTSDB集群和访问部署在物理机上的集群没有体验上的区别。

 

目前内部产品已经上线,产品文档:http://docs.api.xiaomi.net/opentsdb-manager/ ,使用demo gitlab地址:git@v9.git.n.xiaomi.com:infra/opentsdb-demo.git。欢迎使用及反馈,也欢迎公司外部的技术爱好者一起交流讨论。

 

小米正用时序数据库OpenTSDB,解决这个“硬核”问题

图5 小米时序数据库服务

展望

 

未来,我们将在以下方面改进我们的服务:

 

  • 密切关注社区最新进展。特别地,OpenTSDB 3.0提供了更多更新的特性,功能强大,值得期待。同时,我们也将积极参与和回馈社区。

  • 如有需要,我们将使系统的执行过程更加弹性和可观测:比如根据负载情况自动伸缩;可以方便地观测每个读写请求的执行路径、耗时情况、失败或者异常发生的位置等,以便能更快地定位和解决问题。

  • 针对公司内部的需求做定制。比如对tag提供更强大的支持、与云原生技术更好地结合等

  • 对标商业化产品,为用户提供更方便易用的功能。

 

总之,OpenTSDB的设计迎合了计算与存储分离的趋势,具有高性能、高精度、易扩展等诸多优点。这项由我们开发的时间序列数据服务已于近日推出。欢迎试用。同时,我们也将密切关注时间序列数据库的技术趋势,拥抱开源,提供越来越好的用户体验。

参考文献:

[1]https://zh.wikipedia.org/wiki/%E6%99%82%E9%96%93%E5%BA%8F%E5%88%97

[2]https://misfra.me/2016/04/09/tsdb-list/

[3]https://db-engines.com/en/ranking/time+series+dbms

[4] http://opentsdb.net/overview.html

[5] http://www.nosqlnotes.com/technotes/opentsdb-tabledesign/

[6] https://blog.csdn.net/b6ecl1k7bs8o/article/details/84207777

本文章来源于互联网,如有侵权,请联系删除!

相关推荐: LoRaWAN 全球区块链 Helium 网络接入腾讯云IoT 物联网平台实战

Helium People’s Network 是一个全球性、分布式的开放网络。通过热点网关,可以为支持 LoRaWAN 协议的物联网设备提供公共的无线网络覆盖,使物联网设备更方便地接入互联网和传输数据。 本文介绍Helium Console的使用,将标准的L…