[转帖]时间序列数据库 (TSDB)

时间序列数据库 (TSDB)

https://www.jianshu.com/p/31afb8492eff

 

0.3392019.01.28 10:51:33字数 5598阅读 4030

背景

2017年时序数据库突然火了起来。开年2月Facebook开源了beringei时序数据库;到了4月基于PostgreSQL打造的时序数据库TimeScaleDB也开源了,而早在2016年7月,百度云在其天工物联网平台上发布了国内首个多租户的分布式时序数据库产品TSDB,成为支持其发展制造,交通,能源,智慧城市等产业领域的核心产品,同时也成为百度战略发展产业物联网的标志性事件。
例如:html

时间序列数据库 Time Series Database (TSDB)

随着分布式系统监控、物联网的发展,TSDB开始受到更多的关注。
维基百科上对于时间序列的定义是‘一系列数据点按照时间顺序排列’mysql

时间序列数据就是历史烙印,具备不变性,、惟一性、时间排序性git

时间序列数据跟关系型数据库有太多不一样,可是不少公司并不想放弃关系型数据库。 因而就产生了一些特殊的用法,好比用 MySQL 的 VividCortex, 用 Postgres 的 Timescale。 不少人以为特殊的问题须要特殊的解决方法,因而不少时间序列数据库从头写起,不依赖任何现有的数据库, 好比 GraphiteInfluxDBgithub

mysql 的引擎,除了常见的 innodb 和 myisam ,还有一个引擎叫 archive ,它的做用和 rrd 差很少,支持插入和查询操做。web

  • 时序数据是基于时间的一系列的数据。在有时间的坐标中将这些数据点连成线,往过去看能够作成多纬度报表,揭示其趋势性、规律性、异常性;往将来看能够作大数据分析,机器学习,实现预测和预警。sql

  • 时序数据库就是存放时序数据的数据库,而且须要支持时序数据的快速写入、持久化、多纬度的聚合查询等基本功能。shell

数据写入的特色

  • 写入平稳、持续、高并发高吞吐:时序数据的写入是比较平稳的,这点与应用数据不一样,应用数据一般与应用的访问量成正比,而应用的访问量一般存在波峰波谷。时序数据的产生一般是以一个固定的时间频率产生,不会受其余因素的制约,其数据生成的速度是相对比较平稳的。
  • 写多读少:时序数据上95%-99%的操做都是写操做,是典型的写多读少的数据。这与其数据特性相关,例如监控数据,你的监控项可能不少,可是你真正去读的可能比较少,一般只会关心几个特定的关键指标或者在特定的场景下才会去读数据。
  • 实时写入最近生成的数据,无更新:时序数据的写入是实时的,且每次写入都是最近生成的数据,这与其数据生成的特色相关,由于其数据生成是随着时间推动的,而新生成的数据会实时的进行写入。数据写入无更新,在时间这个维度上,随着时间的推动,每次数据都是新数据,不会存在旧数据的更新,不过不排除人为的对数据作订正。

数据查询和分析的特色

  • 按时间范围读取:一般来讲,你不会去关心某个特定点的数据,而是一段时间的数据。
  • 最近的数据被读取的几率高
  • 历史数据粗粒度查询的几率搞
  • 多种精度查询
  • 多维度分析

数据存储的特色

  • 数据量大:拿监控数据来举例,若是咱们采集的监控数据的时间间隔是1s,那一个监控项天天会产生86400个数据点,如有10000个监控项,则一天就会产生864000000个数据点。在物联网场景下,这个数字会更大。整个数据的规模,是TB甚至是PB级的。
  • 冷热分明:时序数据有很是典型的冷热特征,越是历史的数据,被查询和分析的几率越低。
  • 具备时效性:时序数据具备时效性,数据一般会有一个保存周期,超过这个保存周期的数据能够认为是失效的,能够被回收。一方面是由于越是历史的数据,可利用的价值越低;另外一方面是为了节省存储成本,低价值的数据能够被清理。
  • 多精度数据存储:在查询的特色里提到时序数据出于存储成本和查询效率的考虑,会须要一个多精度的查询,一样也须要一个多精度数据的存储。

开源时间序列数据库

RRDTool 是最先的时间序列数据库,它自带画图功能,如今大部分时间序列数据库都使用Grafana来画图。数据库

Graphite 是用 Python 写的 RRD 数据库,它的存储引擎 Whisper 也是 Python 写的, 它画图和聚合能力都强了不少,可是很难水平扩展。
OpenTSDB 使用 HBase 解决了水平扩展的问题
KairosDB 最初是基于OpenTSDB修改的,可是做者认为兼容HBase致使他们不能使用不少 Cassandra 独有的特性, 因而就抛弃了HBase仅支持Cassandra。
新发布的 OpenTSDB 中也加入了对 Cassandra 的支持。 故事还没完,Spotify 的人原本想使用 KairosDB,可是以为项目发展方向不对以及性能太差,就本身撸了一个 Heroic数组

InfluxDB 早期是彻底开源的,后来为了维持公司运营,闭源了集群版本。 在 Percona Live 上他们作了一个开源数据库商业模型正面临危机的演讲,里面调侃红帽的段子很不错。 而且今年的 Percona Live 还有专门的时间序列数据库单元服务器

数据模型

时间序列数据能够分红两部分

  • 序列 :就是标识符(维度),主要的目的是方便进行搜索和筛选
  • 数据点:时间戳和数值构成的数组
    • 行存:一个数组包含多个点,如 [{t: 2017-09-03-21:24:44, v: 0.1002}, {t: 2017-09-03-21:24:45, v: 0.1012}]
    • 列存:两个数组,一个存时间戳,一个存数值,如[ 2017-09-03-21:24:44, 2017-09-03-21:24:45], [0.1002, 0.1012]
      通常状况下:列存能有更好的压缩率和查询性能

基本概念

  • metric: 度量,至关于关系型数据库中的table。
  • data point: 数据点,至关于关系型数据库中的row。
  • timestamp:时间戳,表明数据点产生的时间。
  • field: 度量下的不一样字段。好比位置这个度量具备经度和纬度两个field。通常状况下存放的是会随着时间戳的变化而变化的数据。
  • tag: 标签,或者附加信息。通常存放的是并不随着时间戳变化的属性信息。timestamp加上全部的tags能够认为是table的primary key。

以下图,度量为Wind,每个数据点都具备一个timestamp,两个field:direction和speed,两个tag:sensor、city。它的第一行和第三行,存放的都是sensor号码为95D8-7913的设备,属性城市是上海。随着时间的变化,风向和风速都发生了改变,风向从23.4变成23.2;而风速从3.4变成了3.3。

 

 

应用场景

全部有时序数据产生,而且须要展示其历史趋势、周期规律、异常性的,进一步对将来作出预测分析的,都是时序数据库适合的场景。

例:
在工业物联网环境监控方向,百度天工的客户就遇到了这么一个难题,因为工业上面的要求,须要将工况数据存储起来。客户每一个厂区具备20000个监测点,500毫秒一个采集周期,一共20个厂区。这样算起来一年将产生惊人的26万亿个数据点。假设每一个点50Byte,数据总量将达1P(若是每台服务器10T的硬盘,那么总共须要100多台服务器)。这些数据不仅是要实时生成,写入存储;还要支持快速查询,作可视化的展现,帮助管理者分析决策;而且也可以用来作大数据分析,发现深层次的问题,帮助企业节能减排,增长效益。最终客户采用了百度天工的时序数据库方案,帮助他解决了难题。
(这个高逼格)

时序数据库遇到的挑战

不少人可能认为在传统关系型数据库上加上时间戳一列就能做为时序数据库。数据量少的时候确实也没问题,但少许数据是展示的纬度有限,细节少,可置信低,更加不能用来作大数据分析。很明显时序数据库是为了解决海量数据场景而设计的。

能够看到时序数据库须要解决如下几个问题

  • 时序数据的写入:如何支持每秒钟上千万上亿数据点的写入。

  • 时序数据的读取:又如何支持在秒级对上亿数据的分组聚合运算。

  • 成本敏感:由海量数据存储带来的是成本问题。如何更低成本的存储这些数据,将成为时序数据库须要解决的重中之重。

这些问题不是用一篇文章就能含盖的,同时每一个问题均可以从多个角度去优化解决。在这里只从数据存储这个角度来尝试回答如何解决大数据量的写入和读取。

RRD

RRD (Round Robin Database)数据库是一个环形的数据库,数据库由一个固定大小的数据文件来存放数据,此数据库不会像传统数据库同样为随着数据的增多而文件的大小也在增长,RRD在建立好后其文件大小就固定,能够把它想像成一个圆,圆的众多直径把圆划分红一个个扇形,每一个扇形就是能够存数据的槽位,每一个槽位上被打上了一个时间戳,在圆心上有一个指针,随着时间的流逝,取回数据后,指针会负责把数据填充在相应的槽位上,当指针转了360度后,最开始的数据就会被覆盖,就这样RRD循环填充着数据。

 

 
image.png

  • 源数据搜集:采用一些数据搜集工具,如脚本、shell命令、SNMP等工具在必定时间间隔里把数据搜集填充到rrd数据库中,这些须要数据搜集的对象叫DS,一个DS里在一个时间里能够搜集的数据能够有多个,好比一个时间点上对网卡来讲有进来的流量,也有流出的流量,因此这是2个数据成为一组数据。
  • 临时存储:源数据获取到后是存放在一个数据库的一个临时区域,这些源数据叫作PDP
  • 分组-聚合:RRDTool把这些PDP数据做为数据源经过分组、再利用聚合函数计算后把计算后的结果放在RRD数据库的时间槽(time slot)上,这些数据叫作CDP,CDP才是RRDTool绘图时真正打交道的数据,
  • 在从源数据中取数据作聚合计算时会有一个挑选数据的基准,也就是说是以几个源数据为一组作聚合,根据现实需求的不一样,对源数据能够很灵活的选择不一样的时间段提取源数据,再聚合提取不一样的聚合值,这样就产生不一样组别的CDP数据,这些有以相同时间段挑选源数据及相同聚合函数计算的结果组成的数据就叫RRA,因此根据挑选源数据的标准及采用的聚合函数的不一样,RRA能够有多组。

  • DS:Data Source 数据源,用于定义搜集数据的工具所搜集数据的一些特性
  • Time Solt:时间槽,用于存放经过聚合后的数据区域
  • PDP:Primary Data Point 主数据节点,每一个时间点产生的数据,便是搜集的源数据,没有作聚合的数据
  • CDP(Consolidation Data Point 聚合数据节点):经过对获取的源数据分组、聚合计算后获得的数据叫CDP,
  • RRA(Round Robin Archive 轮转归档):以相同的分组、聚合函数计算后的CDP数据组就组成了RRA
  • Resolution(解析度):这是一个时间跨度,表示在作聚合计算时是以几个连续的time slot里的数据作聚合,在默认时rrd是以300秒的间隔产生一个time slot。
  • CF:Consolidation Function,合并函数或聚合函数,以RRDTool中有AVERAGE、MAX、MIN、LAST4种

以一个图来讲明PDP、CDP、RRA之间的关系:

 

 

 

PDP是以规定的时间间隔(默认为300秒)搜集的源数据,第一个RRA以4个PDP(即4*300秒)为一组作CF后组成的数据,第二个RRA则是以10个PDP为一组作CF后组成的数据。

InfluxDB

InfluxDB 在存储引擎上纠结了好久, leveldb, rocksdb, boltdb 都玩了个遍,最后决定本身造个轮子叫 Time Structured Merge Tree。

Time Structured Merge Tree (TSM) 和 Log Structured Merge Tree (LSM) 的名字都有点误导性,关键并非树,也不是日志或者时间,而是 Merge。

  • 写入的时候,数据先写入到内存里,以后批量写入到硬盘。
  • 读的时候,同时读内存和硬盘而后合并结果。
  • 删除的时候,写入一个删除标记,被标记的数据在读取时不会被返回。
  • 后台会把小的块合并成大的块,此时被标记删除的数据才真正被删除
  • 相对于普通数据,有规律的时间序列数据在合并的过程当中能够极大的提升压缩比。

热点话题

存储

单机存储

若是只是存储起来,直接写成日志就行。但由于后续还要快速的查询,因此须要考虑存储的结构。
传统数据库存储采用的都是B tree,这是因为其在查询和顺序插入时有利于减小寻道次数的组织形式。咱们知道磁盘寻道时间是很是慢的,通常在10ms左右。磁盘的随机读写慢就慢在寻道上面。对于随机写入B tree会消耗大量的时间在磁盘寻道上,致使速度很慢。咱们知道SSD具备更快的寻道时间,但并无从根本上解决这个问题。
对于90%以上场景都是写入的时序数据库,B tree很明显是不合适的。
业界主流都是采用LSM tree替换B tree,好比Hbase, Cassandra等nosql中。这里咱们详细介绍一下。

LSM tree

LSM tree 包括内存里的数据结构和磁盘上的文件两部分,分别对应Hbase里的MemStore和HLog;对应Cassandra里的MemTable和sstable
LSM tree操做流程以下:

  1. 数据写入和更新时首先写入位于内存里的数据结构。为了不数据丢失也会先写到WAL文件中。

  2. 内存里的数据结构会定时或者达到固定大小会刷到磁盘。这些磁盘上的文件不会被修改。

  3. 随着磁盘上积累的文件愈来愈多,会定时的进行合并操做,消除冗余数据,减小文件数量。

 

分布式存储

分布式存储首先要考虑的是如何将数据分布到多台机器上面,也就是 分片(sharding)问题

时序数据库的分片方法和其余分布式系统是相通的。

  • 哈希分片:这种方法实现简单,均衡性较好,可是集群不易扩展。

  • 一致性哈希:这种方案均衡性好,集群扩展容易,只是实现复杂。表明有Amazon的DynamoDB和开源的Cassandra。

  • 范围划分:一般配合全局有序,复杂度在于合并和分裂。表明有Hbase。

  • 结合时序数据库的特色,根据metric+tags分片是比较好的一种方式,由于每每会按照一个时间范围查询,这样相同metric和tags的数据会分配到一台机器上连续存放,顺序的磁盘读取是很快的。

  • 考虑时序数据时间范围很长的状况,须要根据时间范围再分红几段,分别存储到不一样的机器上,这样对于大范围时序数据就能够支持并发查询,优化查询速度。

以下图,第一行和第三行都是一样的tag(sensor=95D8-7913;city=上海),因此分配到一样的分片,而第五行虽然也是一样的tag,可是根据时间范围再分段,被分到了不一样的分片。

 

 

InfluxDB的单机存储

在单机上InfluxDB采起相似于LSM tree的存储结构TSM;而分片的方案InfluxDB先经过<database>+<timestamp>(事实上还要加上retentionPolicy)肯定ShardGroup,再经过<metric>+<tags>的hash code肯定到具体的Shard。

低延迟

时间序列数据库主要是用来分析的,因此提升响应速度对于诊断生产环境的问题是十分重要的。

把全部数据都放在内存

Facebook 写了叫 Gorilla 的纯内存时间序列数据库发表在 VLDB 上,如今已经开源,更名为 Beringei(都是猩猩…)

提早聚合

由于查询中常常须要对一个很长的时间区间取一些粗粒度的值,好比6月到8月天天的平均CPU使用率。 这些聚合值(均值,最大,最小) 均可以在存储数据的时候计算出来。BtrDB 和 Akumuli都在内部节点中存储聚合值,这样在不少查询中底层的节点不须要被访问就能够获得结果。

处理旧数据

  • 不少时间序列数据都没有多大用处,特别是当系统长时间正常运行时,完整的历史数据意义并不大。
  • 因此有些数据库好比 RDDTool 和 Graphite 会自动删除高精度的数据,只保留低精度的。
  • 可是对于不少新的时间序列数据库,在聚合和删除大量旧数据的同时保证系统正常运行并不像删除一个本地文件那样简单。
  • 若是监控系统比被监控系统还不稳定就比较尴尬了。

元数据索引

  • 时间序列的标识符是时间序列数据库里主要的元数据。
  • Heroic 使用 Elasticsearch 来存储元数据, 查询首先经过 Elasticsearch 来取得符合要求的序列标识符,以后从 Cassandra 根据标识符来读取对应的数据。
  • 可是维护一个完整的搜索引擎带来的运维压力和增长的通讯时间都是不能忽视的。
  • 所以 InfluxDB 和 Prometheus 就本身写了倒排索引来索引元数据。

Tracing

  • InfluxDB 的人写了一篇博客 Metrics are dead, 原由是在一个关于监控的会议 Monitorama 上有人说单纯的监控数据已经不能知足他们复杂的微服务架构了。
  • 因而 InfluxDB 的人反驳说并非全部人都在使用大规模的分布式系统,对于不少简单的应用单纯的监控数据已经彻底够用了。
  • 个人见解是时间序列数据库是能够用来存 Trace 的。
  • Trace 是更加复杂的时间序列数据,把单纯的数值变成一个包含更多信息的对象,它就是一个 Trace。
  • 而且不少流行的 Tracer 的存储也是使用 Cassandra, 好比 Zipkin, Uber 的 Jaeger
  • InfluxDB 如今已经支持存储 Trace 了

Ref:
https://zhuanlan.zhihu.com/p/29367404
https://github.com/xephonhq/awesome-time-series-database
https://blog.csdn.net/qq_33326449/article/details/79568014
https://zhuanlan.zhihu.com/p/32709932

相关文章
相关标签/搜索