想要实现在时序场景下“远超”通用数据库,需要做到哪几点?

简介: 近年来,随着物联网技术和市场的快速发展、企业业务的加速扩张,时序数据的处理难题也越来越受到行业和企业的重视,时序场景下通用型数据库步履维艰,各种时序数据库产品应运而起。但是,做一个优质的时序数据库真的很容易吗?本篇文章将从数据库开发者的角度,解剖时序场景下的数据处理需求、分析时序数据库设计思路,给到读者一些硬核技术思考。

1 如何实现时序场景下对通用数据库的“远超”?

做一个 Prototype 或者 Demo 很简单,但做出一个真正好的时序数据库产品却很难。

之所以说做 Prototype 简单,是因为时序数据库天生就不擅长处理一些数据,比如带事务的交易数据。基于此,我们可以大刀阔斧地砍掉一些在通用型数据库中很重要的特性,例如事务、MVCC、ACID(在 Facebook 的 Gorilla 中甚至提出不需要保证 Duration)。某些时序数据库的存储引擎,甚至不能处理乱序数据,在无乱序的前提下,存储引擎几乎可以退化为带 Index 的 Log。所以,从这个角度来看,时序数据库可以做得很简单。

但是,从另一方面来说,做一个好的时序数据库产品又很难。试想一下,在时序数据库的设计上,我们大刀阔斧地砍掉了比如事务、ACID 等特性之后,如果依然不能使其在时序场景下的表现远超通用型数据库,那做一个专门的时序数据库就毫无意义了。这样的话,还不如不做,就直接用通用型数据库好了。

所谓“在时序场景下的远超”,应该是全方位的,比如写入的延迟与吞吐量、查询性能、处理的实时性、甚至包括集群方案的运维成本等,都应该有一个跨越式的提升。另一方面,从时序数据量大、价值偏低等特点出发,压缩率就显得比较重要了,而通用型数据库却很少强调压缩率,由此可见,压缩率是在时序场景下真实生长出来的需求。

高压缩率的实现没有什么黑科技,也不需要自己重新发明压缩算法——无非就是列存并对各个类型使用其最好的压缩算法;更多是工程实现的问题——好好写代码,认真做优化,平衡好写入性能与压缩比之间的关系。

此外,在时序数据场景下的“远超”是建立在时序数据的写入与查询分布特点极其明显的基础上,当数据本身 key 的特征分布十分明显时,自然可以充分利用其特征来打造截然不同的存储引擎与索引结构。

先说写入。时序数据库的吞吐量远超一般的通用型数据库,尤其是 IoT 设备,其设备规模可能达到千万甚至上亿,数据均为自动生成,假设 1s 采样一次,那每秒就能产生千万、亿级别的数据写入,这并不是普通数据库能承受的,在这样大的吞吐量的情况下,数据如何分区分片、如何实时地构建索引,都是具有挑战性的问题。在写入链路上,时序数据库在时序场景下替代的是 OLTP 数据库的位置,而后者在事务与强一致的模型下产生的读写延迟很难支撑时序数据库的高吞吐量写入。

再说查询。在大写入吞吐量的情况下,数据对实时性的要求也很高。例如,我们将时序数据的统计量关联做监控、报警,能容忍的延迟可能在秒级。查询的模式通常是聚合查询,例如某时间段内的统计值,而不是精确的单条记录。总的来说,时序数据库的查询模式通常是交互式分析,这不同于 T+1 的离线数仓,也区别于经常运行数小时的 OLAP 查询,交互式分析查询的响应时间通常是秒级、亚秒级。

以上,在明确了写入与查询需求的同时,下面我们以存储引擎为例,来看一看一个时序数据库的某一个部分应该如何设计。

2 存储引擎想做到极致,还得自研

目前,数据库的存储引擎可以粗略分为两大类:一类是基于 B-Tree 的,另一类是基于 LSM-Tree 的。前者常见于传统 OLTP 数据库,比如 MySQL、PQ 这类的默认引擎,更适用于读多写少的场景;如 HBase、LevelDB、RocksDB 一类数据库使用的是 LSM-Tree,在写多读少的场景下比较适合。实际上,现代数据库的存储引擎,基本都会在某种程度下对这两者融合。LSM Tree 上怎么就不可以建 B-Tree Index 了?(HBase 在 region 上也有 B-Tree Index)B-Tree 怎么就一定要直写硬盘,不能先写 WAL 和走内存 Cache 呢?

对于存储引擎,时序数据库的先行者 InfluxDB 曾经做过很多尝试,在各个存储引擎(LevelDB、RocksDB、BoltDB 等)之间反复横跳,遇到过的问题也有很多,比如 BoltDB 中 mmap+BTree 模型中随机 IO 导致的吞吐量低、RocksDB 这类纯 LSM Tree 存储引擎没办法很优雅快速地按时间分区删除、多个 LevelDB + 划分时间分区的方法又会产生大量句柄……踩了这一系列的坑后,最终 InfluxDB 换成了自研的存储引擎 TSM。可见对时序数据库来说,一个好的存储引擎有多么重要,又是多么难得,要想做到极致,还得自己研发。

不同于 InfluxDB,TDengine 的存储引擎从一开始就是自研的——从 LSM Tree 中汲取了 WAL、先写内存的 skip list 等等技术,但把 LSM Tree 的树层级结构去掉了,而只是按时间段分区、按表分块的 log 块。

读到这里,细心的读者可能会发现,按表分块的设计和 OpenTSDB 的行聚合有些相似。OpenTSDB 的行聚合是把相同 tag 以一小时为时间范围,将这些数据都放到一行中存储,这样大大减少了聚合查询要扫描的数据量。不过不同的是,TDengine 是多列模型,而 OpenTSDB 是单列模型,单列模型下是多行的聚合,多列模型下聚合会自然形成数据块。

而熟悉 LSM Tree 的 KV 分离设计的朋友应该也能够从 TDengine 的存储引擎设计中看到一些熟悉的影子。如果把数据块作为存储引擎的 value,那么 key 就应该是块的起止时间 ,把 key 提出来自然就得到了 TDengine 的 BRIN 索引。从这种视角来看,TDengine 的 .head 文件就是 key,而 .data 和 .last 文件就是 value,而 key 自身又可以结合时序数据的特征组合成有序文件。在时序场景下,有了 BRIN 索引,也就可以不需要 bloom filter,这样一看,TDengine 的存储引擎设计就很清晰了。

此外,TDengine 会将 tag 数据和时序数据分离开来,这样就能够大大减少 tag 数据占用的存储空间,在数据量大的情况下尤其显著。

TDengine 的 tag 与时序数据的划分,和数仓的维度建模里面维度表与事实表的划分有些类似,tag 数据类似维度表,而时序数据类似事实表。但又有所不同,因为 TDengine 中表的数目是和设备数目相同的,上亿设备就是上亿张表(在正在开发的 TDengine 3.0 中,我们要支持 100 亿张表),这样频繁创建、又极其庞大的表,并不容易处理,主要的麻烦是其产生了大量的元数据,超过了单点的处理能力,这就要求 TDengine 能将这部分元数据也进行分片存储。

当数据与元数据进行分片、多副本操作时,就自然涉及到一致性与可用性的问题。在时序数据库中,时序数据通常是最终一致同步的,因为最终一致算法的吞吐量高延迟低、可用性也比强一致算法好,比如 InfluxDB 的集群版会用 Dynamo 这种无主风格的数据同步。但元数据(也就是我们上面提到的标签和表数据)需要强一致,强一致通常会用 Raft、Paxos 这类算法来保证正确性。

由于元数据量的巨大需要分片,而当时序数据与元数据都做分片(甚至时序数据和其关联的元数据应该在同一分片),但又有截然不同的一致性要求,这就导致 TDengine 的副本复制并不是简单地使用 Raft 这类算法就能够驾驭得了的,除非牺牲时序数据的写入吞吐和可用性,也做强一致复制。这就是 TDengine 使用自研复制算法的根本原因。当然,这些算法在复杂的分布式环境下的一致性保证又是另外的问题了,也是我们要着重解决的挑战。

3 写在最后

一个好的时序数据库,起源于对时序数据领域的数据特征的洞察,成长于大量真实场景的考验与用户的反馈,又在数据库领域的最先进技术中吸取经验得以完善。只有这样,最终才能做到在时序场景下“远超”通用型数据库,成为此场景下的优选数据库。而要做到这一步,其实并不容易。

最后预告一下我们正在开发的 TDengine 3.0。在 3.0 版本中,我们对现在的 2.x 版本存在的一些待解问题做了重新设计与彻底重构,敬请期待。另外关于在 3.0 开发中踩过的坑,以后有机会再和大家慢慢道来。

目录
相关文章
|
4月前
|
安全 关系型数据库 MySQL
MySQL数据库高效秘籍:10个小技巧,让你轻松应对各种场景!
【8月更文挑战第25天】本文介绍了十个提升MySQL数据库效率与安全性的实用技巧。涵盖查询性能分析、索引优化、慢查询日志利用、图形化工具如MySQL Workbench的应用、性能分析工具、主从复制实现、备份与恢复策略、数据库迁移方法及安全性保障等多个方面。通过具体的示例代码展示每个技巧的实际操作方式,帮助读者深入理解并有效运用MySQL数据库。
239 0
|
2月前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
192 64
|
1月前
|
架构师 数据库
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
数据库乐观锁是必知必会的技术栈,也是大厂面试高频,十分重要,本文解析数据库乐观锁。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
|
2月前
|
供应链 数据库
数据库事务安全性控制有什么应用场景吗
【10月更文挑战第15天】数据库事务安全性控制有什么应用场景吗
|
3月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
508 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
3月前
|
JavaScript 前端开发 数据库
数据库测试场景实践总结
本文介绍了数据库超时和应用锁表SSDB测试场景的验证方法,通过锁定数据表模拟写入失败情况,并利用SSDB进行重试。测试需开发人员配合验证功能。同时,提供了SSDB服务器登录、查询队列数量及重启服务等常用命令。适用于验证和解决数据库写入问题。
39 7
|
4月前
|
存储 Serverless API
Serverless 架构实现弹幕场景问题之在initializer方法中初始化数据库实例如何解决
Serverless 架构实现弹幕场景问题之在initializer方法中初始化数据库实例如何解决
33 0
|
4月前
|
SQL 关系型数据库 MySQL
(十六)MySQL调优篇:单机数据库如何在高并发场景下健步如飞?
在当前的IT开发行业中,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代中一个炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题。而MySQL作为整个系统的后方大本营,由于是基于磁盘的原因,性能瓶颈往往也会随着流量增大而凸显出来。
611 0
|
5月前
|
人工智能 关系型数据库 MySQL
探索和体验云原生数据库PolarDB MySQL版在AI场景中的应用
探索和体验云原生数据库PolarDB MySQL版在AI场景中的应用
186 0
|
5月前
|
关系型数据库 MySQL 分布式数据库
PolarDB MySQL场景评测:阿里云数据库服务的新高度
随着企业数字化转型的加速,对数据库的稳定性和性能提出了更高要求。阿里云的PolarDB MySQL应运而生,作为一款高度兼容MySQL协议的云原生数据库,它在性能、扩展性和安全性方面展现出了卓越的能力。本文将基于阿里云PolarDB MySQL的官方评测,深入探讨其在实际应用场景中的表现,以及为用户带来的价值。
171 0
下一篇
DataWorks