前段时间有朋友留言要我写一篇时序数据库的文章。我之前讨论的数据库大多是RDBMS,其他数据库的讨论不多。说实话,对于时序数据库,我只是一个小学生。我的客户使用时序数据库只是一个应用系统中的一小部分功能。大多数应用系统的主要数据仍然使用关系数据库。随着工业互联网的发展,以及物联网技术和应用的发展,时序数据库越来越受欢迎。时序数据库是专门为处理时序数据而优化的特殊数据库管理系统,每条记录都带有时间戳。时间序列数据可能由物联网中的传感器、智能电表或RFID产生,或由电网运行中的各种采集点产生,或来自股票交易记录。时间序列数据的处理不同于关系数据库的处理。时序数据库旨在有效地收集、存储和查询高频产生的各种时序数据。并且在数据库存储、批量查询、时序数据分析、过期数据自动处理等方面有独特的方法。虽然传统的关系型数据库或者key-value数据库都可以用来管理时序数据。它的特点是写入大批量带时间戳的数据,每秒可能高达数百万甚至数千万。同时,数据一次写入后不会被修改,会被多次读取使用。这些数据要么用于实时分析,要么用于验尸研究。通常,应用软件会按照一定的规则和时间间隔加载一批数据,或者通过内置的统计功能对这些数据进行分析。此类应用程序通常不太关心单点数据或几个数据之间的关系。由于一些数据量较小的时序数据库应用可以存储在关系型数据库、HBASE、REDIS等KV数据库中,因此纯时序数据库在日常应用中使用的比较少。因此,时序数据库的发展多年来一直不温不火。从DB-ENGINES来看,纯时序数据库的人气分数并不高。以第一模式为时序数据库类型的数据库排名来看,排名最高的InfluxDB仅为29.15分,在数据库流行度排名中非常靠后。如果我们把主要的数据库模式加到其他类型上,把第二种模式加到时序数据库模式的数据库上,我们看到的是完全不同的情况。这里看到了一些大佬,尤其是现在很火的MongDB。MongoDB作为一个文档数据库,其实是一个多模式的数据库,同时也支持时序数据。在国内,MongoDB只是作为文档数据库使用,只存储一些目录和日志信息。但是MongoDB是一个非常通用的数据库产品,支持强一致性事务,甚至在时序数据库模式下也是非常强大的。西门子、博世等世界500强企业使用MongoDB处理时间序列数据。就目前的XC替代而言,MongoDB其实是很难被替代的,尤其是真正使用MongDB的事务和时序特性的话。没有任何其他数据库产品具有MongoDB如此强大的功能。但MongoDB从商业利益角度出发,将开源协议转为SSPL后,开始收割云服务商。这份接近商业协议的开源协议极易受到美国政府出口管制措施的影响。所以,对于有XC需求的企业来说,还是要非常小心。令人惊喜的是,Redis这种我们经常用来做缓冲的非常简单的内存KV数据库,也是多模的,支持时序数据。Redis支持SortedSets数据结构,支持按权重存储数据,支持按权重区间查询。如果使用时间戳作为权重值,key存储具体的度量维度,那么Redis就可以支持时序数据。但是这种模式过于简单粗暴,内存消耗大,并发写入性能不好,所以只适合最简单的模式。从Redis5.0开始,Redis开始支持消息队列Stream,流式数据也是时序数据处理中常见的场景。真正使Redis成为真正的流式数据库能力的是RedisTimeSeries扩展模块的引入。正是在这个列表中,我们还看到了最近流行的ClickHose。Clickhouse是俄罗斯Yandex公司于2016年开源的列式数据库管理系统,近年来在OLAP等有时序处理需求的场景中迅速收割用户,成为一匹黑马。其矢量化引擎SIMD极大地释放了一些简单的大数据分析和查询的性能。只是ClickHose简单粗暴的向量引擎限制了应用的并发,但是在OLAP场景下,高并发并不总是刚需。在时序数据库的大部分应用场景中,时序数据库可以独立存储和访问,而应用中比较复杂的业务数据可以放在关系数据库中。时序数据的读写场景比较简单,所以时序数据库在数据库领域不太受欢迎。一些关系数据库用户一开始在关系数据库中存储时序数据,但由于时序数据量太大。它会导致关系数据库的容量变得超大。之前做过一个优化项目,业务数据库的存储容量高达数百TB。其实里面的关系业务数据也就几百GB,而且大部分都是写的。只读时间序列数据。后来我建议他们把时序数据分开,这样数据库的备份和运维会简单很多。将超大规模的时序数据写入关系型数据库,很可能会达到关系型数据库的天花板,导致数据库的性能跟不上。如果将这种数据存储在纯时序数据库中,很容易利用其分布式的特点很好地横向扩展。时序数据库存储这些数据时,占用的空间较小,而且很容易实现数据的自动压缩。另外,使用专用的API访问时间对数据进行复杂的汇总统计比SQL接口快很多。因此,不少企业相继将时序数据从传统的关系型数据库中分离出来,存储在专业的时序数据库中。不过还有另外一种思路,就是在关系型数据库中加入时序数据库的能力。最典型的是TimeScaleDB。当时序数据量不是太大时,部分用户会选择将时序数据存储在关系型数据库中。在PostgreSQL数据库中安装TimeScaleDB插件,创建时间序列表,用于存储时间序列数据。同事使用PG的SQL引擎来访问和处理这些时序数据。利用TimeScaleDB的自动历史数据压缩功能对历史数据进行压缩,可以大大降低海量历史数据的存储容量。我们的D-SMART需要采集大量的数据库监控数据,大概2分钟一次,每次上千个实例,每个实例有上百条记录。在这种情况下,对于一个管理2000个数据库的D-SMART来说,每两分钟就会有100万条数据写入TimeScaleDB,这些数据需要按照时间间隔通过SQL查询出来进行分析处理。从这些年的使用来看,TimeScaleDB可以轻松应对这样的场景,每条SQL查询都可以在几十毫秒内完成。我们最初使用PG普通表来存储这些监控数据。改用TimeScaleDB后,写入性能和查询性能都有了数倍的提升。我们最喜欢的是历史数据的自动压缩功能。作为运维自动化系统,很少访问7天前的监控数据。因此我们设置了7天数据自动压缩,大大节省了存储资源。使用TimeScaleDB最大的好处就是保留了我们团队在SQL方面的所有研发经验。只要不乱写SQL,大部分SQL不需要特别优化和重写就可以满足性能需求。这种开发自由度的实现来自TimeScaleDB的优秀设计。由于时间问题,我们将在这里讨论。如果是千万级到亿级的时序数据处理,使用TimeScaleDB毫无压力。国内也有很多时序数据库产品。目前摩天轮上有32个国内时序数据库,几乎和DB-ENGINES上35个纯时序数据库的列表一样长。其中,淘思数据的TDengine和知搜科技的DolphinDB名列前茅。在DB-ENGINES时序数据库的排名中,这两个时序数据库的排名也比较靠前。国内也有一些基于openTSDB,或者与之兼容的时序数据库。时序数据库和时序应用的发展呈现出三种模式,大家在争论哪种模式更好。第一种模式是放弃关系数据库,转向时序数据库,或者用时序数据库模式的多模式数据库代替关系数据库。利用原生的分布式架构和具有向量处理能力的数据库引擎,支持特别大数据量写入和大数据量输出的场景。这些人认为NOSQL是时序数据处理的终极解决方案。第二种模式正好相反。他们从NoSQL时序数据库转向具有时序数据处理能力的关系型数据库,充分利用SQL的能力解决应用问题。最典型的就是我今天介绍的D-SMART中使用的TimeScaleDB。对于更大的数据量需求,可以使用CrateDB、TDengine等分布式数据库。第三种模式是使用HBASE等KV数据库来存储时序数据,而不是专门使用时序数据库。对于只需要找个地方存放海量时序数据以满足大并发写入和高吞吐量输出需求的场景,足以满足应用处理大量数据的需求,所以有这种用法没问题。其实不用争论,因为不同的应用场景会选择不同的模式。你选择什么样的时序数据库方案往往取决于以下几个因素:1)你的时序数据量级是多少,几万、几十万,还是几百万、几千万每秒;2)你的时序数据是怎么用的,每次读取多少批次;3)是否需要数据库内置的功能来处理和分析时序数据,或者是否有自己的数据分析应用模块;4)您如何处理过期5)您历史数据的访问方式;6)你查询的并发QPS是多少;……。我想你已经考虑清楚了这些问题,然后根据目前主流的时序数据库或者具有时序功能的多模式数据库的特点进行搜索,那么不难做出一个相对靠谱的选择。
