首页 > 编程知识 正文

数据库的基本特点,开源时序数据库对比

时间:2023-05-04 03:38:27 阅读:174045 作者:1682

2017年的时间序列数据库突然着火了。 年2月Facebook开放源代码化了beringei时间序列数据库; 4月基于PostgreSQL架构的时序数据库TimeScaleDB也实现开源,2016年7月,百度云在其天工物联网平台上发布国内首款多租户分布式时序数据库产品TSDB 成为智慧城市等产业领域的核心产品,同时也成为百度战略发展产业物联网的标志性事件。 时间序列数据库作为物联网发展方向是一项非常重要的服务,业界的频繁呼声表明,各企业都在焦急等待物联网时代的到来。

本文从时序数据库的基本概念、使用场景、解决的问题逐一展开,最后从如何解决时序数据存储这一技术问题进行深入分析。

1.背景

百度无人车在运行时需要监测坐标、速度、方向、温度、湿度等各种状态,还需要记录下每时每刻监测到的数据,用于大数据分析。 一辆车每天收集近8T的数据。 如果只是保存的话,不查询也没关系,但是如果需要“今天下午2点在后厂村大街,速度超过60km/h的无人车有什么”这样的多纬度组聚合查询的话,时间序列数据库比较合适。

2.什么是时序数据库

首先介绍什么是时间序列数据。 时间序列数据是基于时间的一系列数据。 用有时间的坐标连接这些数据点,过去看可以生成多纬度报告,揭示其倾向性、规律性、异常性; 面向未来可以实现大数据分析、机器学习、预测和预警。

时序数据库是存储时序数据的数据库,需要支持时序数据的高速写入、持久化、多纬度聚合查询等基本功能。

与传统数据库相比,只记录了数据的当前值,时序数据库记录了所有的历史数据。 同时,时序数据的查询也总是有时间作为过滤条件。

时序数据示例

p1-北上广三地2015年气温变化图

p2-北上广三地当前温度实时显现

这里介绍了时间序列数据库的一些基本概念。 不同的时间序列数据库的称谓略有不同。

metric:度量相当于关系数据库中的表。

data point:数据点相当于关系数据库中的行。

时间标记:时间戳。 表示生成数据点的时间。

field:度量下的不同字段。 例如,位置测量有经度和纬度两个字段。 一般保存着随时间戳变化的数据。

tag:标签或其他信息。 一般存储不随时间戳变化的属性信息。 如果在timestamp中加入所有的tags,则可以认为是table的主密钥。

如下图所示,测量值为Wind,每个数据点有timestamp、两个field:direction和speed、两个tag:sensor、city。 其第一行和第三行存储着sensor号码为95D8-7913的设备,属性城市为上海。 随着时间的变化,风向和风速发生变化,风向从23.4变为23.2; 风速从3.4变成了3.3。

p3-时间序列数据库的基本概念图

3.时序数据库的场景

有时间序列数据的生成,需要显示其历史趋势、周期规律、异常性的东西,进一步预测分析未来都是适合时间序列数据库的场景。

在工业物联网环境监测的方向上,百度天工的客户面临着这样的难题,根据工业要求,需要保存案例数据。 客户每个工厂有20000个监控点,500毫秒一个收集周期,共有20个工厂。 这样计算的话,一年中将会产生惊人的26万亿个据点。 假设每点50字节,数据总量达到1P。 如果一台服务器是10T硬盘,则总共需要100台以上的服务器。 这些数据不仅可实时生成并写入存储,还可支持快速咨询,提供可视化展示,帮助管理员分析决策,进行大数据分析,发现深层次的问题,为企业节能减排最终客户采用了百度天工的时序数据库方案,帮助他解决了难题。

在互联网场景中,也产生了大量的时间序列数据。 百度内部有很多服务使用天工物联网平台的时序数据库。 举个例子,百度内部服务为了保障用户的使用体验,将用户每次的网络卡顿、网络延迟记录在百度天工的时序数据库中。 直接从时序数据库生成报告分析技术产品,尽早发现和解决问题,保证用户的使用体验。

4.时序数据库遇到的挑战

许多人可能认为,在传统关系数据库中添加时间戳列可以用作时间序列数据库。 数据量少的时候也确实没有问题,但是少量的数据显示的纬度有限,细节少,不可靠,不能用于更大的数据分析。 显然,时序数据库是为了解决大量的数据场景而设计的。

可以看到时序数据库需要解决以下几个问题

时序数据写入:如何支持每秒写入数千万个数据点。 时序数据读取:如何支持在秒级别分组和聚合数以亿计的数据的运算。 成本敏感:海量数据存储带来的是成本问题。 以更低的成本存储这些数据是时序数据库要解决的关键。 这些问题不是一篇文章所能涵盖的,同时所有的问题

题都可以从多个角度去优化解决。在这里只从数据存储这个角度来尝试回答如何解决大数据量的写入和读取。

5.数据的存储

数据的存储可以分为两个问题,单机上存储和分布式存储。

单机存储

如果只是存储起来,直接写成日志就行。但因为后续还要快速的查询,所以需要考虑存储的结构。

传统数据库存储采用的都是B tree,这是由于其在查询和顺序插入时有利于减少寻道次数的组织形式。我们知道磁盘寻道时间是非常慢的,一般在10ms左右。磁盘的随机读写慢就慢在寻道上面。对于随机写入B tree会消耗大量的时间在磁盘寻道上,导致速度很慢。我们知道SSD具有更快的寻道时间,但并没有从根本上解决这个问题。

对于90%以上场景都是写入的时序数据库,B tree很明显是不合适的。

业界主流都是采用LSM tree替换B tree,比如Hbase, Cassandra等nosql中。这里我们详细介绍一下。

LSM tree包括内存里的数据结构和磁盘上的文件两部分。分别对应Hbase里的MemStore和HLog;对应Cassandra里的MemTable和sstable。

LSM tree操作流程如下:

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

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

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

p4-Hbase LSM tree结构介绍(注1)

可以看到LSM tree核心思想就是通过内存写和后续磁盘的顺序写入获得更高的写入性能,避免了随机写入。但同时也牺牲了读取性能,因为同一个key的值可能存在于多个HFile中。为了获取更好的读取性能,可以通过bloom filter和compaction得到,这里限于篇幅就不详细展开。

分布式存储

时序数据库面向的是海量数据的写入存储读取,单机是无法解决问题的。所以需要采用多机存储,也就是分布式存储。

分布式存储首先要考虑的是如何将数据分布到多台机器上面,也就是 分片(sharding)问题。下面我们就时序数据库分片问题展开介绍。分片问题由分片方法的选择和分片的设计组成。

分片方法

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

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

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

范围划分:通常配合全局有序,复杂度在于合并和分裂。代表有Hbase。

分片设计

分片设计简单来说就是以什么做分片,这是非常有技巧的,会直接影响写入读取的性能。

结合时序数据库的特点,根据metric+tags分片是比较好的一种方式,因为往往会按照一个时间范围查询,这样相同metric和tags的数据会分配到一台机器上连续存放,顺序的磁盘读取是很快的。再结合上面讲到的单机存储内容,可以做到快速查询。

进一步我们考虑时序数据时间范围很长的情况,需要根据时间范围再将分成几段,分别存储到不同的机器上,这样对于大范围时序数据就可以支持并发查询,优化查询速度。

如下图,第一行和第三行都是同样的tag(sensor=95D8-7913;city=上海),所以分配到同样的分片,而第五行虽然也是同样的tag,但是根据时间范围再分段,被分到了不同的分片。第二、四、六行属于同样的tag(sensor=F3CC-20F3;city=北京)也是一样的道理。

p5-时序数据分片说明

6.真实案例

下面我以一批开源时序数据库作为说明。

InfluxDB:

非常优秀的时序数据库,但只有单机版是免费开源的,集群版本是要收费的。从单机版本中可以一窥其存储方案:在单机上InfluxDB采取类似于LSM tree的存储结构TSM;而分片的方案InfluxDB先通过+(事实上还要加上retentionPolicy)确定ShardGroup,再通过+的hash code确定到具体的Shard。

这里timestamp默认情况下是7天对齐,也就是说7天的时序数据会在一个Shard中。

p6-Influxdb TSM结构图(注2)

Kairosdb:

底层使用Cassandra作为分布式存储引擎,如上文提到单机上采用的是LSM tree。
Cassandra有两级索引:partition key和clustering key。其中partition key是其分片ID,使用的是一致性哈希;而clustering key在一个partition key中保证有序。

Kairosdb利用Cassandra的特性,将 ++<数据类型>+作为partition key,数据点时间在timestamp上的偏移作为clustering key,其有序性方便做基于时间范围的查询。

partition key中的timestamp是3周对齐的,也就是说21天的时序数据会在一个clustering key下。3周的毫秒数是18亿正好小于Cassandra每行列数20亿的限制。

OpenTsdb:

底层使用Hbase作为其分布式存储引擎,采用的也是LSM tree。

Hbase采用范围划分的分片方式。使用row key做分片,保证其全局有序。每个row key下可以有多个column family。每个column family下可以有多个column。

上图是OpenTsdb的row key组织方式。不同于别的时序数据库,由于Hbase的row key全局有序,所以增加了可选的salt以达到更好的数据分布,避免热点产生。再由与timestamp间的偏移和数据类型组成column qualifier。

他的timestamp是小时对齐的,也就是说一个row key下最多存储一个小时的数据。并且需要将构成row key的metric和tags都转成对应的uid来减少存储空间,避免Hfile索引太大。下图是真实的row key示例。

p7-open tsdb的row key示例(注3)

7.结束语

可以看到各分布式时序数据库虽然存储方案都略有不同,但本质上是一致的,由于时序数据写多读少的场景,在单机上采用更加适合大吞吐量写入的单机存储结构,而在分布式方案上根据时序数据的特点来精心设计,目标就是设计的分片方案能方便时序数据的写入和读取,同时使数据分布更加均匀,尽量避免热点的产生。

数据存储是时序数据库设计中很小的一块内容,但也能管中窥豹,看到时序数据库从设计之初就要考虑时序数据的特点。后续我们会从其他的角度进行讨论。

作者:百度云时序数据库资深工程师

注1:来源 http://tristartom.github.io/research.html
注2:来源 http://blog.fatedier.com/2016/08/05/detailed-in-influxdb-tsm-storage-engine-one/
注3:来源 http://opentsdb.net/docs/build/html/user_guide/backends/hbase.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。