IoTDB 是一款时序数据库,相关竞品有 KairosdbInfluxDBTimescaleDB等,主要使用场景是在物联网相关行业,如:车联网、风力发电、地铁、飞机监控等等,具体应用案例及公司详情可以查看:IoTDB在实际公司中的使用信息收集

IoTDB 模块主要分为ClientJDBCServerTsFileGrafanaDistribution 以及各种生态的连接器。整个系列的文章会从行业背景开始讲起,了解一个行业具体的使用场景,然后介绍 TsFile 是以什么样的格式来保存数据的,再介绍 Server 里怎样完成一次查询,最后在介绍一条完 整的 SQL是怎样从 Client 使用 JDBC 到 Server 直至返回具体结果。如果有能力的话再介绍一下集群的一些内容和工作方式。

打一波广告本人专注车联网领域多年,现任四维智联架构师。目前正在参与 IoTDB 社区,有志同道合的同伴欢迎加微信:liutaohua001

欢迎大家访问 IoTDB 仓库,求一波 Star 。

这一章主要想聊一聊:

  1. 为什么重复造轮子,从物联网行业的数据特点到 IoTDB 的发展过程
  2. 这个轮子造的怎么样,IoTDB 和竞品测试对比

时序数据

我个人理解时序数据是基于时间维度的同一个物体或概念的值构成的一个序列数据。在传统关系型数据库中,例如 MySQL,我们通常会放置一个自增的 Id 列作为主键标识,如下:

Id 人名 体温 测量时间
1 张三 36.5 2020-02-06 9:00:00
2 李四 36.9 2020-02-06 9:00:00
3 王五 36.7 2020-02-06 9:00:00
4 张三 36.3 2020-02-06 9:30:00
5 张三 36.9 2020-02-06 11:00:00

上面的表结构就是一个时序数据,将表结构做个变形更容易理解:

时间戳 人名 体温
1580950800 张三 36.5
1580950800 李四 36.9
1580950800 王五 36.7
1580952600 张三 36.3
1580958000 张三 36.9

如果把时间作为一个唯一键对齐展示,能够更像时序数据一些,这也是 IoTDB 中查询结果的展示方式:

时间戳 张三 李四 王五
1580950800 36.5 36.9 36.7
1580952600 36.3 NULL NULL
1580958000 36.9 NULL NULL

这里可能会存在疑问就是假如人数是逐渐增加的,那么是动态创建列呢?还是提前创建足够多的列?这个问题等后面文章有机会继续介绍

物联网

物联网的特点是都会存在一个或多个设备,他们以各种各样的形式组织到一起,用来观测或记录同一时间里相同环境所产生的数据。下面的介绍中,使用由简单到复杂的数据逐步介绍在物联网行业中,通用的一些问题和方向。

1.基本存储

假如我是一个公司,对外播报北京、天津、上海三地的温度数据,从而实现盈利。

时间戳 北京 天津 上海
1580950800 20.5 22.9 21.7
1580952600 20.5 NULL 22.9
1580958000 20.5 21.7 22.9

2.保证数据质量

数据保证的质量是多方面的,一步一步介绍。

2.1 更多设备

首先可以看到上面数据是存在 NULL 值的,这个 NULL 值有可能是因为当时设备所在的区域停电了,所以并没有办法上报当时的情况,这样客户如果想获取1580952600 这个时间戳对应的天津的数据的时候,肯定是拿不到了,所以传统思维上,我们应该增加一个容灾设备,保证一个设备在坏掉、停电、人为损坏等等的情况的时候,依然能够有数据上报回来。

基于这样的思想,以上的表结构就会变成:

时间戳 北京 1 北京 2 天津1 天津2 上海1 上海2
1580950800 20.5 20.9 21.7 20.9 20.7 21.7
1580952600 21.5 21.0 NULL 21.7 21.7 21.7
1580958000 22.5 22.7 22.9 22.7 NULL NULL

2.2 更高采样频率

这时候依然存在问题, 1580958000 这一刻两个设备都没有数据,有可能是放置设备的区域同时出现了断网或者断电,这种情况下,我们可以采用提高采集数据的频率或者补传数据来解决(补传暂不讨论)。

我们将每天数据分为3组,每组采样3次,间隔为1个小时,假如时间分布为:上午(7、8、9)、中午(12、13、14)、下午(18、19、20)。当增加了采样频率之后,即便某一刻出现了 NULL 数据,我们也可以采用临近时间做为补充。为了方便对应,下表数据中增加时间点列辅助查看。

时间点 时间戳 北京 1 北京 2 天津1 天津2 上海1 上海2
7点 1580943600 20.5 20.9 21.7 20.9 20.7 21.7
8点 1580947200 21.5 21.0 NULL 21.7 21.7 21.7
9点 1580950800 22.5 22.7 22.9 22.7 NULL NULL
12点 1580961600 20.5 20.9 21.7 20.9 20.7 21.7
13点 1580965200 21.5 21.0 NULL 21.7 21.7 21.7
14点 1580968800 22.5 22.7 22.9 22.7 NULL NULL
18点 1580983200 20.5 20.9 21.7 20.9 20.7 21.7
19点 1580986800 21.5 21.0 NULL 21.7 21.7 21.7
20点 1580990400 22.5 22.7 22.9 22.7 NULL NULL

可以看到经过各种各样的需求之后,上传的数据是成倍增长的,不难想象如果这个温度数据希望精准的获取到每个县城的温度,那么中国有 2854 个县城 * 2 个温度设备 * 9 条数据 = 1 天产生的数据总量 = 51372 条,那么一个月就是 1541160 条。

数据实时性及总量

假如上面的数据我们继续提高频率到每1分钟每个设备上报一次,那么数据量就会成为 2854 * 2 * 60 * 24 = 246585600 条/天。

在这样的数据量下,实时插入实时做一些聚合计算,应该传统数据库就有些处理不过来了。

IoTDB 的前身

某公司在实际业务中,20 万设备保存了 3 年的数据,TB级别的数据使得 Oracle 被拖的根本吃不消。关键的问题点还不仅仅是存量数据大,新增数据依然以非常快的速度在增长。后来公司联系到了 IoTDB 的第一批开发者,但是当时的方案还是基于 Cassandra 来做设计,当时规划了 5 台机器的集群,性能刚满足,但随着时间推移设备总量在增加,业务系统的查询请求量在增加。Cassandra 在经过大量的努力之后,最后发现如果再改可能就需要大面积的重构 Cassandra 数据的代码了,最终决定重新设计一个存储方式,来解决物联网场景下的时序数据高效写入、低延迟读取、高压缩比持久化。

PS: 以上都是黄向东 (IoTDB PPMC) ,在 meetup 中讲到的,我只是在脑中存留了一部分,具体的细节大家可以到 IoTDB 社区交流。

性能对比

测试工具使用的是由清华大学大数据实验室开发的iotdb-benchmark

1.写入性能对比

数据集2 客户端 存储组 设备 变量 batchsize LOOP 数据量 写入速度(point/s) 硬盘数据大小
IoTDB 10 10 10 10 1000 1000000 1E+11 24750321.93 38306092
InfluxDB 10 10 10 10 1000 1000000 1E+11   304682932
TimescaleDB 10 10 10 10 1000 1000000 1E+11 737689.22 1610219064
数据集1 客户端 存储组 设备 变量 batchsize LOOP 数据量 写入速度(point/s) 硬盘数据大小
IoTDB 10 10 10 10 1000 100000 10000000000 20706345.15 3599732
InfluxDB 10 10 10 10 1000 100000 10000000000 1729907.81 30546560
TimescaleDB 10 10 10 10 1000 100000 10000000000 715857 161026468
KairosDB 10 10 10 10 10000 10000 10000000000 24924.97 76263380

上面一组数据可以看出写入性能高于同款数据库10倍有余,单机写入速度高达到每秒2千万。且硬盘占用是最小的,这在数据比较大的线上业务中,可能每个月会差出来 1 到 2 块硬盘。

2. 查询性能对比

原始数据查询

  客户端 存储组 设备 序列-数据量 变量 查询点数 LOOP 速度(point/s) AVG MIN
IoTDB 10 10 10 1.00E+09 1 1000000 100 12942984.85 740.27 457.04
InfluxDB 10 10 10 1.00E+09 1 1000000 100 1779606.4 5591 4666.39
TimescaleDB 10 10 10 1.00E+09 1 1000000 100 3781467.52 2345.69 1193.78

聚合数据查询

  客户端 存储组 设备 序列-数据量 变量 LOOP 范围 速度(point/s) AVG MIN
IoTDB-1 10 10 10 1.00E+09 1 100 0.0001 49.75 27.87 18.03
IoTDB-2 10 10 10 1.00E+09 1 100 0.001 49.75 49.14 19.87
IoTDB-3 10 10 10 1.00E+09 1 100 0.01 49.76 48.69 22.32
IoTDB-4 10 10 10 1.00E+09 1 100 0.1 48.68 99.14 25.56
IoTDB-5 10 10 10 1.00E+09 1 100 1 14 595.61 45.54
InfluxDB-1 10 10 10 1.00E+09 1 100 0.0001 234.32 40.28 21.63
InfluxDB-2 10 10 10 1.00E+09 1 100 0.001 28.88 341.9 238.1
InfluxDB-3 10 10 10 1.00E+09 1 100 0.01 3.07 3226.87 2664.86
TimescaleDB-1 10 10 10 1.00E+09 1 100 0.0001 42.39 220.57 120.5
TimescaleDB-2 10 10 10 1.00E+09 1 100 0.001 5.8 1502.9 754.15
TimescaleDB-3 10 10 10 1.00E+09 1 100 0.01 1.02 9711.55 7148.69

3. 对比图

整体来看 IoTDB 无论在写入、原始数据查询还是聚合查询,都几乎是10倍的性能于竞品数据库,而且硬盘占用又小于同款数据库10倍,那么 IoTDB 是怎样完成如此高的压缩比、如此恐怖的写入速度、如此高效的查询呢?欢迎继续关注。。。

时序数据库 Apache-IoTDB 源码解析之前言(一)的更多相关文章

  1. Ocelot简易教程(七)之配置文件数据库存储插件源码解析

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9852711.html 上篇文章给大家分享了如何集成我写的一个Ocelot扩展插件把Ocelot的配置存储 ...

  2. 时序数据库 Apache-IoTDB 源码解析之系统架构(二)

    上一章聊到时序数据是什么样,物联网行业中的时序数据的特点:存量数据大.新增数据多(采集频率高.设备量多).详情请见: 时序数据库 Apache-IoTDB 源码解析之前言(一) 打一波广告,欢迎大家访 ...

  3. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  4. [源码解析] 从TimeoutException看Flink的心跳机制

    [源码解析] 从TimeoutException看Flink的心跳机制 目录 [源码解析] 从TimeoutException看Flink的心跳机制 0x00 摘要 0x01 缘由 0x02 背景概念 ...

  5. [源码解析] Flink的Slot究竟是什么?(1)

    [源码解析] Flink的Slot究竟是什么?(1) 目录 [源码解析] Flink的Slot究竟是什么?(1) 0x00 摘要 0x01 概述 & 问题 1.1 Fllink工作原理 1.2 ...

  6. [源码解析] Flink的Slot究竟是什么?(2)

    [源码解析] Flink 的slot究竟是什么?(2) 目录 [源码解析] Flink 的slot究竟是什么?(2) 0x00 摘要 0x01 前文回顾 0x02 注册/更新Slot 2.1 Task ...

  7. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  8. RxJava2源码解析(二)

    title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...

  9. 时序数据库 Apache-IoTDB 源码解析之文件数据块(四)

    上一章聊到行式存储.列式存储的基本概念,并介绍了 TsFile 是如何存储数据以及基本概念.详情请见: 时序数据库 Apache-IoTDB 源码解析之文件格式简介(三) 打一波广告,欢迎大家访问Io ...

随机推荐

  1. $SP703\ Mobile\ Service\ DP$

    洛谷 Sol 首先状态是已经完成的请求数量 这题只有三个员工跑来跑去,只有三个.... 一般像这种人数特别少的DP题就会把它们都放到状态里去 于是:f[i][x][y][z]表示现在已经完成了i个请求 ...

  2. Python3 pip换源

    pip安装源 介绍 """ 1.采用国内源,加速下载模块的速度 2.常用pip源: -- 豆瓣:https://pypi.douban.com/simple -- 阿里: ...

  3. [03]java中的方法以及控制语句

    00 Java中的语句块 语句块(有时叫做复合语句),是用花括号扩起的任意数量的简单Java语句.块确定了局部变量的作用域.块中的程序代码,作为一个整体,是要被一起执行的.块可以被嵌套在另一个块中,但 ...

  4. 基于 Blazui 的 Markdown 编辑器 Blazui.Markdown 尝鲜

    想做一个文档平台用来存放和展示 Blazui 的文档,然后基于 Markdown 写文档,但缺一个好用的 Blazor Markdown 编辑器,所以就顺便写一个了,功能上基本抄的 https://p ...

  5. array_diff 大bug

    $aa = array("手机号", "first","keyword1","keyword2","keywo ...

  6. docker命令总结(二)

    上次只是给大家把命令的作用以及简单使用列出来了(大家可以查看:docker命令总结(一)),那这篇文章会详细介绍每条命令的参数,命令比较多建议大家使用搜索,进行查看 search docker sea ...

  7. Deepin Linux 实体机安装

    Deepin Linux 实体机安装 1.下载ISO镜像并刻录到U盘上 系统ISO镜像下载 深度技术 刻录工具下载 深度技术(下方有深度启动盘制作工具下载) 这两个都下载好之后,打开刻录工具,选择镜像 ...

  8. JavaScript-EventLoop-事件循环

    2020-01-11 EventLoop-事件循环 一.学习事件循环之前,先学习几个英语词组 EventLoop 事件循环 Event Queue 事件队列 Event Table 事件表macro- ...

  9. Go和Java的性能对比,真的如此吗?

    前两天我看到了一篇文章,测试Java和Go和Python的性能,其测试内容是一个排序,排序一亿次,然后看那个语言耗时最短,我先贴一下这个文章的测试结果,Java竟然比Go快了一倍不止,Go不是号称接近 ...

  10. ubuntu下打开html页面

    相信遇到这个问题的各位都是闲人,所以肯定是有时间的,网上打开html教程很多,但是就不吐槽了emmm... 详细信息不在此篇幅,网络资源,我就不重复了,看着很烦的,见附录 下面进入正题 这个配置玩过的 ...