27.2k star,开源时序数据库里全球排名第一,InfluxDB何以做到?
wptr33 2025-05-21 16:55 4 浏览
一 什么是时序数据库
时序数据库,全称时间序列数据库(Time Series Database,TSDB),用于存储大量基于时间的数据,时序数据(Time Series Data)指的是一系列基于时间的数据,例如 CPU 利用率,北京的房价变化趋势,某一地区的温度变化等。
时序数据库支持时序数据的快速写入、持久化,多维度查询、聚合等操作,同时可以记录所有的历史数据,查询时将时间作为数据的过滤条件。
二 初识InfluxDB
InfluxDB 是时序数据库中应用比较广泛的一种,在 DB-Engines TSDB rank 中位居首位,可见 InfluxDB 在互联网的受欢迎程度是非常高的。
三 InfluxDB 的存储引擎演进
- 版本0.9.0之前
**基于 LevelDB的LSMTree方案** - 版本0.9.0~0.9.4
**基于BoltDB的mmap COW B+tree方案** - 版本0.9.5~1.2
**基于自研的 WAL + TSMFile 方案**(TSMFile方案是0.9.6版本正式启用,0.9.5只是提供了原型) - 版本1.3~至今
**基于自研的 WAL + TSMFile + TSIFile 方案**
InfluxDB的存储引擎先后尝试过包括LevelDB, BoltDB在内的多种方案。但是对于InfluxDB的下述诉求终不能完美地支持:
- 时序数据在降采样后会存在大批量的数据删除 => *LevelDB的LSMTree删除代价过高*
- 单机环境存放大量数据时不能占用过多文件句柄 => *LevelDB会随着时间增长产生大量小文件*
- 数据存储需要热备份 => *LevelDB只能冷备*
- 大数据场景下写吞吐量要跟得上 => *BoltDB的B+tree写操作吞吐量成瓶颈*
- 存储需具备良好的压缩性能 => *BoltDB不支持压缩*
此外,出于技术栈的一致性以及部署的简易性考虑(面向容器部署),InfluxDB团队希望存储引擎与其上层的TSDB引擎一样都是用GO编写,因此潜在的RocksDB选项被排除
基于上述痛点,InfluxDB团队决定自己做一个存储引擎的实现。
四 InfluxDB的使用场景
时序数据的使用场景广泛,包括 DevOps 监控,应用程序指标,IoT 传感器数据,实时动态数据分析等场景。
InfluxDB是一种时序数据库,时序数据库常用于监控场景,比如运维和IOT(物联网)领域,此类数据库旨在存储时序数据和实时计算。
如:将服务器上的CPU的使用情况每隔5秒向InfluxDB中写入一条数据,在图形界面中写一个查询过去每10分钟CPU的平均使用情况,再将该查询开发一个定时任务,每10秒钟执行一次并配置一条规则:查询执行结果 > xxx,就立即触发告警。
上述就是一个监控指标的场景,在IOT领域中也有大量的指标需要监控,比如:机械设备的传感器频率、农田湿度温度等等。
时序数据库相对关系型数据库而言,时序数据库专注的是写入性能,时序数据库不关心事务、不关注更新操作(只写不改)。通常指标数据都是关心最近某段时间的数据,之后的数据基本不会再用。时序数据库的设计特点是冷热差别明显,对最近的数据时序数据库会优先加载到内存中。
五 InfluxDB的组件
时序数据库一般用于在监控场景,大体上,数据的应用可以分四部分:数据采集、存储、查询&聚合及告警
对应InfluxDB 1.x开始也推出了TICK生态全套的解决方案:
- T:Telegraf 数据采集组件
- I:InfluxDB 数据存储组件
- C:Chronograf 用户UI数据管理功能
- K:Kapacitor 后台处理报警信息
在InfluxDB 2.x后已经把C、K合并到了I中了,这是两个版本在生态上的差别,在2.x上易用性也随之提高了一个等级:我们只需要安装InfluxDB就得到一个管理UI界面并且附带了定时任务和告警功能。
T是一个单独的插件,专注于收集各种外部中间件的数据写入到InfluxDB中,这个需要单独研究该插件的使用。
安装下载地址:
https://portal.influxdata.com/downloads/
下面是在web界面中新增Telegraf的配置文件,它已经给支持了非常多的中间件产品,就按照它的示例去给Telegraf机器上设置环境变量和启动即可使用。
时序数据库与我们熟悉的关系型数据库有所不同,首先需要了解一下 InfluxDB 中字段的含义,如下图所示:
六 InfluxDB的特点
● 数据写入:
①.高并发高吞吐,可持续的数据写入。
②.写多读少,时序数据 95% 以上都是写操作,例如在监控系统数据的时候,监控数据特别多,但是通常只会关注几个关键指标。
③.数据实时写入,不支持数据更新,但是可以人为更新修改。
● 数据分析与查询:
①.数据查询是按照时间段读取,例如 1 小时,1 分钟,给出具体时间范围。
②.最近的数据读取率高,越旧的数据读取率越低。
③.多种精度查询和多种维度分析。
● 数据存储:
①.存储数据规模大的数据,监控数据的数据大多数情况下都是 TB 或者 PB 级。
②.数据存放具有时效性,InfluxDB 提供了保存策略,可以认为是数据的保质期,超过周期范围,就可以认为数据失效,需要回收。节约存储成本,清理低价值的数据。
七 InfluxDB数据结构
Telegraf的内部数据结构叫做InfluxDB行协议。如下图所示:
Telegraf本身是InfluxData公司专门为InfluxDB开发的数据采集器。上面这种数据格式是InfluxDB数据库使用的,只要数据符合上面这种格式,就能通过InfluxDB的API将数据导入数据库。所以,自家的插件当然支持自家的生态了,InfluxDB。
与 CSV 相似,在 InfluxDB 行协议中,一条数据和另一条数据之间使用换行符分隔, 所以一行就是一条数据。另外,在时序数据库领域,一行数据一行数据由下面 4 种元素构成。
- measurement(测量名称)
- Tag Set(标签集)
- Field Set(字段集)
- Timestamp(时间戳)
协议中的数据类型及其格式
- Float(浮点数):IEEE-754标准的64位浮点数。这是默认的数据类型。
- Integer(整数):有符号64位整数。需要在数字的尾部加上一个小写数字 i 。
- UInteger(无符号整数):无符号64位整数。需要在数字的尾部加上一个小写数字 u 。
- String(字符串):普通文本字符串,长度不能超过64KB
- Boolean(布尔值):true或者false
- Unix Timestamp(Unix 时间戳):myMeasurementName fieldKey="fieldValue"1556813561098000000
- 注释:以井号 # 开头的一行会被当做注释。
基本数据结构
points的数据结构介绍
八 InfluxDB存储原理
InfluxDB 的存储结构树是时间结构合并树(Time-Structured Merge Tree,TSM),它是由日志结构化合并树(Log-Structured Merge Tree,LSM),根据实际需求变化而来的。
①.LSM 树
LSM 树包含三部分:Memtable,Immutable 和 SSTable。MemTable 是内存中的数据结构,用于保存最近产生的数据,并按照 Key 有序地组织数据。内存并不是可靠存储,若断电就会丢失数据,因此通常会使用预写式日志 (Write-ahead logging,WAL) 的方式来保证数据的可靠性。
②.TSM 存储引擎
TSM 存储引擎主要包括四部分:Cache,WAL,TSM File,Compactor。下图中 shard 与 TSM 引擎主要部分放在一起,但其实 shard 在是 TSM 存储引擎之上的一个概念。在 InfluxDB 中按照数据产生的时间范围,会创建不同的 shard 分组,每个 shard 都有本身的 cache、wal、tsm file 以及 compactor。
InfluxDB文件目录结构
九 InfluxDB的写入
InfluxDB写入时序数据时为了确保数据完整性和可用性,与大部分数据库产品一样,都是会先写WAL,再写入缓存,最后刷盘。对于InfluxDB而言,写入时序数据的主要流程如同下图所示:
InfluxDB提供了多种接口协议供外部应用写入,比如可以使用collected采集数据上传,可以使用opentsdb作为输入,也可以使用http协议以及udp协议批量写入数据。批量数据进入到InfluxDB之后总体会经过三个步骤的处理,如下图所示:
- 批量时序数据shard路由:InfluxDB首先会将这些数据根据shard的不同分成不同的分组,每个分组的时序数据会发送到对应的shard。每个shard相当于HBase中region的概念,是InfluxDB中处理用户读写请求的单机引擎。
- 倒排索引引擎构建倒排索引:InfluxDB中shard由两个LSM引擎构成 – 倒排索引引擎和TSM引擎。时序数据首先会经过倒排索引引擎构建倒排索引,倒排索引用来实现InfluxDB的多维查询。
- TSM引擎持久化时序数据:倒排索引构建成功之后时序数据会进入TSM Engine处理。TMS Engine处理流程和通用LSM Engine基本一样,先将写入请求追加写入WAL日志,再写入cache,一旦满足特定条件会将cache中的时序数据执行flush操作落盘形成TSM File。
十 InfluxDB的读取
InfluxDB支持类SQL查询,称为InfluxQL。InfluxQL支持基本的DDL操作和DML操作语句,详见InfluxQL_Spec,比如Select语句:
select_stmt = "SELECT" fields from_clause [ into_clause ] [ where_clause ]
[ group_by_clause ] [ order_by_clause ] [ limit_clause ]
[ offset_clause ] [ slimit_clause ] [ soffset_clause ] .
读取流程大体如下:
整个读取流程从宏观上分为四个部分:
1. Query:InfluxQL允许用户使用类SQL语句执行查询分析聚合,InfluxQL语法详见:
https://docs.influxdata.com/influxdb/v1.0/query_language/spec/
2. QueryParser:InfluxQL进入系统之后,系统首先会对InfluxQL执行切词并解析为抽象语法树(AST),抽象树中标示出了数据源、查询条件、查询列以及聚合函数等等,分别对应上图中Source、Condition以及Aggration。
3. BuildIterators:InfluxQL语句转换为Query实体对象之后,就进入读取流程中最重要最核心的一个环节 – 构建Iterator体系。构建Iterator体系是一个非常复杂的逻辑过程,其中细节非常繁复,笔者尽可能化繁为简,将其中的主线抽出来。为了方便理解,笔者将Iterator体系分为三个子体系:顶层Iterator子体系、中间层Iterator子体系以及底层Iterator子体系。
4. Emitter.Emit:Iterator体系构建完成之后就完成了查询聚合前的准备工作,接下来就开始干活了。干活逻辑简单来讲是遍历所有FieldIterator,对每个FieldIterator执行一次Next函数,就会返回每个查询列的结果值,组装到一起就是一行数据。FieldIterator执行Next()函数会传递到最底层的TagsetIterator,TagsetIterator执行Next函数实际返回真实的时序数据。
TSDB存储引擎(实际上就是一个Shard)根据用户的查询请求执行原始数据的查询就是上文中提到的底层Iterator子体系的构建。查询过程分为两个部分:倒排索引查询过滤以及TSM数据层查询,前者通过Query中的where条件结合倒排索引过滤掉不满足条件的SeriesKey;后者根据留下的SeriesKey以及where条件中时间段信息(TimeRange)在TSMFile中以及内存中查出最终满足条件的数值列。TSDB存储引擎会将查询到的所有满足条件的原始数值列返回给上层,上层根据聚合函数对原始数据进行聚合并将聚合结果返回给用户。整个过程如下图所示:
上图需要从底部向上浏览,整个流程可以整理为如下:
1. 根据where condition以及所有倒排索引文件查处所有满足条件的SeriesKey
2. 将满足条件的SeriesKey根据GroupBy维度列进行分组,不同分组后续的所有操作都可以独立并发执行,因此可以多线程处理
3. 针对某个分组的SeriesKey集合以及待查询列,根据指定查询时间段(TimeRange)在所有TSMFile中根据B+树索引构建查询iterator
4. 将满足条件的原始数据返回给上层进行聚合运算,并将聚合运算的结果返回给用户
实际执行的过程可能比较抽象,为了更好的理解,笔者在下半部分举了一个示例。没有理解上面的逻辑没关系,可以先看下面的示例,看完之后再看上面的理论逻辑相信会更加容易理解。
十一 InfluxDB的删除
一般LSM引擎处理删除通常都采用Tag标记的方式,即删除操作和写入操作流程基本一致,只是数据上会多一个Tag标记 – deleted,表示该值已经被deleted。这种处理方案可以最小化删除代价,但万物有得必有失,减小了写入代价必然会增加读取代价,Tag标签方案在读取的时候需要对标记有deleted的数值进行特殊处理,这个代价还是很大的。HBase中删除操作就是采用Tag标记方案。
InfluxDB比较奇葩,对于删除操作处理的比较异类,通常InfluxDB不会删除一条记录,而是会删除某段时间内或者某个维度下的所有记录,甚至一张表的所有记录,这和通常的数据库有所不同。比如:
DROP SERIES FROM h2o_feet WHERE location = ‘santa_monica'
DELETE FROM "cpu" DELETE FROM "cpu" WHERE time < '2000-01-01T00:00:00Z' DELETE WHERE time < '2000-01-01T00:00:00Z'
InfluxDB中一个shard有两个LSM引擎,一个是倒排索引引擎(存储维度列到SeriesKey的映射关系,方便多维查找),一个是TSM Engine,用来存储实际的时序数据。如果是删除一条记录,通常只需要TSM Engine执行删除就可以,倒排索引引擎是不需要执行删除的。而如果是Drop Measurement这样的操作,那么两个LSM引擎都需要执行相应的删除。问题是,这两个引擎的删除策略完全不同,TSM Engine采用了一种同步删除策略,Inverted Index Engine采用了标记删除策略。如下图所示:
1. TSM Engine同步删除策略,整个删除流程可以分为如下四步:
(1)删除所有TSM File中满足条件的series,系统会遍历当前shard中所有TSM File,检查该File中是否存在满足删除条件的File,如果有会执行如下两个操作:
- TSM File Index相关处理:在内存中删除满足条件的Index Entry,通常删除会带有Time Range以及Key Range,而且TSM File Index会在引擎启动之后加载到内存。因此删除操作会将满足条件的Index Entry从内存中删除。
- 生成tombstoner文件:tombstoner文件会记录当前TSM File中所有被删除的时序数据,时序数据用[key, min, max]三个字段表示,其中key即SeriesKey+FieldKey,[min, max]表示要删除的时间段。如下图所示:
(2)删除Cache中满足条件的series
(3)在WAL中生成一条删除series的记录并持久化到硬盘
2. Inverted Index Engine 标记Tag删除策略,标记Tag删除非常简单,和一次写入流程基本相同:
(1)在WAL中生成一条flag为deleted的LogEntry并持久化到硬盘
(2)将要删除的维度信息写入Cache,需要标记deleted(设置type=deleted)
(3)当WAL大小超过阈值之后标记为deleted的维度信息会随Cache Flush到倒排索引文件
(4)和HBase一样,Inverted Index Engine中索引信息真正被删除发生在compact阶段
十二 参考资料
[1] InfluxDB文件结构解析:
https://blog.csdn.net/u012794915/article/details/100061367
[2] InfluxDB入门操作:
https://blog.csdn.net/qq_44766883/article/details/131511821
[3] InfluxDB 的存储机制解析:
https://zhuanlan.zhihu.com/p/604131607
[4] InfluxDB TSM存储引擎之数据读取:
http://hbasefly.com/2018/05/02/timeseries-database-7/
[5] InfluxDB TSM存储引擎之数据写入:
http://hbasefly.com/2018/03/27/timeseries-database-6/
[6] InfluxDB源码:
https://github.com/influxdata/influxdb
[7] InfluxDB 2.x概述和数据存储原理:
https://www.caodegao.com/archives/influxdb2x-gai-shu-he-shu-ju-yuan-li
[8] influxdb集成:
https://www.influxdata.com/products/integrations/
相关推荐
- 针对 MySQL 数据库的 HikariCP 数据库连接池 配置详解
-
HikariCP是当前性能最优异的数据库连接池之一,尤其适用于高并发场景。以下是针对MySQL数据库的HikariCP配置详解,包含常用参数及其优化建议。HikariCP是当前性能最优异的...
- MySQL 数据同步神器 - Canal 入门篇
-
前言想必做过商品服务都是将商品相关的信息和价格保存在数据库中,例如...
- MySQL之慢查询日志分析
-
一、慢查询设置与测试1、慢查询介绍MySQL的慢查询,全名是慢查询日志,是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阈值的语句。...
- 「MySQL学习」MySQL的变量
-
MySQL的变量分为四种:局部变量、用户变量、会话变量和全局变量,其中局部变量只存在于函数和存储过程,这里不多了解。其中会话变量和全局变量在MySQL中统称为系统变量用户...
- MySQL日志篇
-
今天我们介绍一下MySQL中特别重要的一项内容——日志!MySQL中日志有很多,我们前文提到的redolog、undolog、以及今天要提到的binlog。...
- MySQL--视图
-
介绍视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所...
- MySQL中like会不会走索引?
-
先说结论:like"%关键字":不会;like"%关键字%":不会like"关键字%":会说明:...
- MySQL正则 rlike(regexp)
-
在MySQL中,like、rlike和regexp都不区分大小写,如果需要区分,可以在WHERE后添加关键字段binary1.LIKE可以使用以下两个通配符:%...
- 开源文档预览项目 kkFileView (9.9k star) ,快速入门
-
kkFileView是一款文件文档在线预览解决方案,采用流行的SpringBoot框架构建,易于上手和部署。该项目基本支持主流办公文档的在线预览,包括但不限于doc、docx、xls、xls...
- 帮你打造一个私有化的在线个人文档系统
-
前言最近开发的过程中总是需要找寻一些资料,但是某些资料或者是某段可用的代码,已经忘记放在了哪个文档中了,看着电脑上搜索出来的几百个txt文件,我陷入了一阵无力感中,于是我想能不能搞个在线文档,就像“语...
- Container 命令ctr、crictl 命令使用说明
-
一、ctr命令使用Container命令ctr,crictl的用法版本:ctrcontainerd.io1.4.3containerd相比于docker,多了...
- Docker常用命令(2)
-
目录Docker重启策略配置容器环境变量...
- 快速搭建自己的镜像仓库
-
搭建docker镜像仓库1.准备找一台机器为镜像仓库的主机.创建好存放镜像数据文件的目录.例如...
- 整合 kkfile 实现文件预览
-
一、简介...
- 隐私计算FATE-核心概念与单机部署
-
一、说明Fate是一个工业级联邦学习框架,所谓联邦学习指的就是可以联合多方的数据,共同构建一个模型;...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
git 执行pull错误如何撤销 git pull fail
-
面试官:git pull是哪两个指令的组合?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git pull 之后本地代码被覆盖 解决方案
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)