TDengine 企业级功能:存储引擎对多表低频场景优化工作分享

news2024/11/24 7:51:10

在去年 8 月份发布的 3.1.0.0 版本中,TDengine 进行了一系列重要的企业级功能更新,其中包括对多表低频场景写入性能的大幅优化。这一优化工作为有此需求的用户提供了更大的便捷性和易用性。在本文中,TDengine 的资深研发将对此次优化工作进行深入分析介绍,并从实践层面剖析本次功能升级的具体作用。

三种时序场景分析

以 TDengine 的客户群体作为分析样本,我们发现,企业的时序场景大概可以分为以下三种类型:

  • 少表高频
    • 表的数量小,一般少于 100 万张表。
    • 数据采集频率高,多为秒级甚至毫秒级。
    • 在存储引擎看来,大量写入的数据中,同一张表的数据被多次写入,且时间戳递增,或有极少数的乱序。
    • 当内存中的数据积攒到一定的量需要落盘时,同一张表的数据大量存在,可以生成多个数据块。
  • 多表低频(High Cardinality)
    • 表的数量大,一般多于 100 万张表,达到千万、亿级别。
    • 表的采集频率很低,多为分钟级采集,也有小时级和天级的采集频率。
    • 在存储引擎看来,大量写入的数据中,同一张表只有几条甚至一条数据的写入。
    • 数据落盘时,每张表只有一条或几条记录,无法生成一个完整的数据块。
  • 无限热点表
    • 每张表只在一段时间内数据频繁更新写入,成为写入热点,其后很少或根本不再有数据的写入。
    • 在不同的时间段内,写入热点表一直改变,且持续创建新的表。
    • 如果以 TDengine 的数据模型建表,表数将达到无限。
    • 在存储看来,该场景兼具多表低频和少表高频的特点。
    • 在一段时间内,某些表写入数据非常多。落盘时,同一张表的数据可能会产生多个数据块,表现出高频的特性。而大部分表不写入数据。
    • 随着时间的推移,表的数量会非常庞大,表现出多表的特性。

对于少表低频的场景来说,由于数据量不大,用任何方案都可以解决。而多表高频的场景,在有限的硬件资源下会转变为多表低频场景,在无限的硬件资源下,则会转变为少表高频场景。

在 TDengine 的用户群体中,部分多表低频的用户也可以通过增加节点,即增加 vnode 个数,使用更多的硬件资源将多表低频场景转化为了少表高频场景,从而较为高效地利用 TDengine 在少表高频场景下的高性能,但增加硬件资源本身和 TDengine 的初衷(为用户节省硬件资源)相违背。以北京燃气举例,在 300万+ 燃气表、每个燃气表每天采集一条记录的场景下,用 TDengine 3.0 处理,通过增大 vnode 个数将之转化为少表高频的场景后,相比用户以前用 Oracle 时成本并未节省多少。

对于无限热点表场景来说,如果用 TDengine 来处理该场景,随着时间的推移,表的数量会越来越多,效率会越来越低,成本会越来越高直至不可用。不过,TDengine 3.0 提供了表的 TTL(Time-To-Live)功能,用户可以通过该功能设置过期表自动删除,从而控制表的数目不至于达到无限。但该场景最终也退化成了多表高频场景。

有人说这三种场景可以统一为一种模型处理,即 InfluxDB 的模型:对一个时间线指定 tag,数据为采集数据。鉴于 InfluxDB 以该数据模型设计的存储模型的表现,个人认为,InfluxDB 的数据模型除了能帮助大家很好地理解时序数据这个优点之外,对于解决上述多表低频和无限热点表场景没有任何实际价值。且 InfluxDB 本身对于 tag 取值范围大的场景(High Cardinality)处理非常差,以致于被竞品攻击。

从以上角度出发,随着 TDengine 3.0 版本的逐步更新,我们开始针对多表低频场景写入性能开展优化工作。

TDengine 存储引擎设计概述

从根本上来说,TDengine 的设计和实现来自于对时序数据十大特点的总结和一个数据模型的确定。

  • 时序数据十大特点:

  • TDengine 数据模型:一个采集点一张表

TDengine 采用一个采集点一张表的数据模型,主要是要利用时序这一特点。

TDengine 存储引擎整体采用了 LSM 的存储架构。其结构如下图所示:

TDengine 的文件系统如下:

文件组的结构如下:

存储引擎优化工作的具体展开

明确优化要解决的问题

  • 解决在多表场景下写放大问题

在少表高频的场景下,TDengine 充分利用了有序这个特点,在该场景下的写入性能相比同类型数据库高出一个甚至几个数量级,达到最优 O(N) 的时间复杂度。在存储格式上,我们假设落盘时一张表的数据大量存在,从而设计了硬盘上一个数据块只包含一张表的数据这样一种结构。

但是在多表场景下,从存储引擎的角度来讲,上述的很多特性会发生改变。由于存储引擎可以利用的内存资源有限,在内存可缓存的数据里,属于同一张表的数据只有很少的几条,甚至一条。在这种情况下,有序这个特点几乎无用,我们针对有序做的优化在多表场景下趋于无效,甚至会导致写放大问题。

在存储引擎看来,多表低频场景下的数据写入是纯乱序的。从理论上来讲,该场景下数据写入的最优处理复杂度为 O(NlogN)。

  • 在多表低频场景下,stt_trigger 配置大以后写入周期性出现卡顿的问题

TDengine 后台有一个专门用来落盘的线程池,负责将 imem 中的数据持久化到硬盘文件上。这个文件可能是 stt 文件,也有可能是 data 文件中。如果生成了 stt 文件,并且 stt 个数达到了 stt_trigger,commit 线程则会将 imem 和 多个 stt 文件中的数据合并,写入 data 文件或者生成新的 stt 文件。这个合并可能涉及非常多的数据的读和写,从而使得落盘时间非常久,久到新的 mem 被写满,会阻塞写入进程一段时间,直至合并完成。

  • compact、retention 功能阻塞写入的问题

由于 compact、retention、commit 均需对文件进行操作,且这些操作可能动相同的文件,因此这三个操作只能串行操做,从而导致 compact 或 retention 阻塞 commit,出现阻塞写入进程的问题。

存储数据调整

  • stt 文件中一个数据块中可以包含多张表的数据(3.0 发布时已完成)

从上面的分析可以看到,一个数据块只有一张表的数据,在多表低频场景下,会导致数据写放大严重,且不利于压缩,读取时效率也非常低。因此,在优化中,我们将 stt 中属于同一个超级表的数据合并在一个数据块中,该数据块可能含有多个表的数据,这样就使得 stt 文件中的数据块数量减少了至少 3 个数量级。

  • stt 文件中添加统计信息

为了提升 TDengine 查询引擎对于 stt 的处理效率,我们在新的 stt 文件中增加了每张表的统计信息。

  • 删除数据(Tombstone Data)分布到各个文件组

在老的存储中删除文件是单独存在的。为了避免 commit 与其他操作处理同一个文件,我们决定将删除数据分布到不同的文件组中,并增加 tomb 文件。删除数据可能存在于 tomb 文件中或者 stt 文件中。

LSM 实现完善

在新的优化中,我们补齐了 LSM 的另一环,即后台的 merge。后台的 merge 线程将多个 stt 文件合并到 data 文件中或者生成新的 stt 文件。

commit 只负责生成新的 stt 文件,不再负责向 data 中写入。这样就可以将 commit 操作的文件和 compact、retetion 以及 merge 操作的文件隔离开,从而实现并行进行,避免 commit 被阻塞而出现写入阻塞的情况。

为了尽量减少多表低频场景下数据被多次 merge,我们还为 stt 文件引入了分层的概念。

头文件列存

头文件列存的优化动力来源于国家地震局台网中心的用户场景。该用户的场景属于少表高频,表的数据量不大,但是采集频率是毫秒级的,因此数据量非常大,一天就有 3000 亿条记录写入。由于数据写入量非常大,导致数据块非常多,这也导致头文件非常大。由于头文件在每次落盘时都可能重写,就导致读写放大都十分严重。

因此,在本次优化中,我们将头文件改为列存,并对每一列配以压缩,从而使得头文件缩小到原来的 1/10。改造后的头文件格式如下:

优化结果反馈

此次优化一方面是为了提高多表低频写入的性能,另一方面是为了解决各种问题。整体来讲,本次优化的结果是:在少表高频场景下,写入性能不降;多表低频场景写入性能提升,并且写入速度稳定。此次优化在用户实践角度也反馈出良好效果——在北京燃气 300 万智能电表项目中,3 个 vnode 即可满足写入需求,且写入速度稳定;在河南智能电表项目中,用一台较好的机器,如 64 核 128GB 内存,就可以解决以前需要几十台机器才能满足的写入、查询需求。

同时,这种优化方式对于数据的乱序更新也带来了显著的好处。在一些无法在落盘时进行排序或合并的更新数据情况下,通过后台的 merge 操作,为乱序数据提供了额外的处理机会。这样,乱序数据可以被重新排序,未合并的更新数据也可以得到更新。这种优化机制有效地提高了数据的整体处理效率和准确性。

结语

总而言之,通过此次优化,TDengine 进一步提升了在低频场景下的写入性能,使用户能够更高效地存储和管理数据。这对于需要进行大规模数据处理的能源企业来说,将带来更加卓越的数据处理能力和用户体验。如果你也有此场景需求,可以添加小T vx:tdengine 进行咨询交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1394127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是线程(多线程),Python多线程的好处

几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每一个运行中的程序就是一个进程。当一个程序运行时,内部可能包含多个顺序执行流,每一个顺序执行流就是一个线程。 线程和进程 几乎所有的操作系统都支持进…

【Dynamo学习笔记】Dynamo for Revit建模基础

目录 前言1 Revit模型的结构2 图元的操作2.1 图元的选择2.2 图元参数的读取和写入2.3 图元的创建2.3.2 创建轴网2.3.2 创建结构柱2.3.3 创建结构框架2.3.4 创建墙体 3 自定义节点 参考资料: (1) 罗嘉祥,宋姗,田宏钧. 《…

组态王软件安装教程6.51/6.53/5.55/6.60/7.5SP2版本组态软件

组态王软件是一款功能强大的工业自动化软件,以下是各个版本的主要特点: 组态王6.51:该版本是亚控科技在组态王6.0x系列版本成功应用后,广泛征询数千家用户的需求和使用经验,采取先进软件开发模式和流程,由…

c语言字符串追加

系列文章目录 c语言字符串追加 c语言字符串追加 系列文章目录c语言字符串追加 c语言字符串追加 int main() {char arr1[] "hello";char arr2[] "world";char arrbuf[100] { 0 };//全部初始化\0int index 0;while (arr1[index]! \0){//1、将非\0的字符添…

基于springboot+vue的网上订餐系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

机器视觉检测设备在连接器外观缺陷检测中的应用

作为传输电流或信号连接两个有源器件的器件,连接器被广泛应用于各个行业,从手机、平板、电脑,到冰箱、空调、洗衣机,再到汽车、国防、航空,处处是它的所在。每个电子产品少了连接器将无法运作,因此&#xf…

JRT和springboot比较测试

想要战胜他,必先理解他。这两天系统的学习Maven和跑springboot工程,从以前只是看着复杂到亲手体验一下,亲自实践的才是更可靠的了解。 第一就是首先Maven侵入代码结构,代码一般要按约定搞src/main/java。如果是能严格执行测试的项…

竞赛保研 大数据房价预测分析与可视

0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 大数据房价预测分析与可视 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:4分 该项目较为新颖,适合…

如何保证HUAWEI交换机成功使用ssh登录?

1)telnet 部分配置4行 telnet server enable telnet server-source all-interface local-user admin service-type telnet ssh stelnet server enable 2)ssh local-user admin service-type telnet ssh ssh server-source all-interface ssh server c…

Windows pip install -r requirements.txt 太慢

目录 解决方案一: 解决方案二: 下载单个包时切换源: 解决方案一: 1、在虚拟环境中切换下载的源: pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 2、当出现有pip.txt文件写入时&…

解决springboot启动报Failed to start bean ‘subProtocolWebSocketHandler‘;

解决springboot启动报 Failed to start bean subProtocolWebSocketHandler; nested exception is java.lang.IllegalArgumentException: No handlers 问题发现问题解决 问题发现 使用springboot整合websocket,启动时报错,示例代码: EnableW…

XSS漏洞:xss.haozi.me靶场通关

xss系列往期文章: 初识XSS漏洞-CSDN博客 利用XSS漏洞打cookie-CSDN博客 XSS漏洞:xss-labs靶场通关-CSDN博客 XSS漏洞:prompt.mi靶场通关-CSDN博客 目录 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C…

QT第六天

要求&#xff1a;使用QT绘图&#xff0c;完成仪表盘绘制&#xff0c;如下图。 素材 运行效果&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPainter> #include <QPen>QT_BEGIN_NAMESPACE name…

克魔助手工具详解、数据包抓取分析、使用教程

目录 摘要 引言 克魔助手界面 克魔助手查看数据捕获列表 数据包解析窗口 数据包数据窗口 克魔助手过滤器表达式的规则 抓包过滤器实例 总结 参考资料 摘要 本文介绍了克魔助手工具的界面和功能&#xff0c;包括数据包的捕获和分析&#xff0c;以及抓包过滤器的使用方…

Docker之安装Nginx

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Docker之Dockerfile构建镜像》。&#x1f3af;&…

软件测试|深入了解Python中的super()函数用法

简介 Python中的super()函数是一种强大的工具&#xff0c;用于在子类中调用父类的方法。它在面向对象编程中非常有用&#xff0c;可以让你轻松地扩展和重用现有的类。本文将详细介绍super()函数的用法&#xff0c;并提供一些示例来帮助你更好地理解它的功能。 什么是super()函…

C#中的文件操作

为什么要对文件进行操作&#xff1f; 在计算机当中&#xff0c;数据是二进制的形式存在的&#xff0c;文件则是用于存储这些数据的单位&#xff0c;因此在需要操作计算机中的数据时&#xff0c;需要对文件进行操作。 在程序开发过程中&#xff0c;操作变量和常量的时候&#…

Kotlin学习最快速的方式

引言: 前段时间在一个技术交流群看到一句话:"在我面试的过程中,遇到一位面试者,做ios开发的,Swift 语言出来4-5年了,30多岁的人,连这个都不会";今天再次回想了这句话,说的不正我这样的人吗?一个之前做Anroid应用开发的,现在连Kotlin都不会;做技术的,还是要紧跟时代…

基于YOLOv8深度学习的智能肺炎诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

数组中第K个最大元素(算法村第十关白银挑战)

215. 数组中的第K个最大元素 - 力扣&#xff08;LeetCode&#xff09; 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 **k** 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现…