从一到无穷大 #13 How does Lindorm TSDB solve the high cardinality problem?

news2024/11/25 15:50:33

在这里插入图片描述本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。

文章目录

  • 引言
  • 优势
  • 挑战
  • 系统架构
  • 细节/优化
    • 存储引擎
    • 索引
    • 写入
    • 查询
  • 经验
  • Ablation Study
  • 总结

引言

云原生时序数据库目前来看还是一个没有行业标准架构特殊数据库分支,各大云厂商都有自己的集群化实现,从谷歌的Monarch,阿里的Lindorm,腾讯的CTSDB,到垂直领域的InfluxDB IOX,TDengine,IotDB,都是各有的特点和适合的领域。终究不存在银弹,强如各大头部厂商也只是在做Trade off…

优势

  1. 大量活跃时间线下高写入吞吐和低延迟读取
  2. 允许用户使用SQL直接进行异常检测和时间序列预测算法
  3. 在节点扩展的过程中也能保证稳定的性能

挑战

  1. 海量时间线下的写入,Lindorm认为挑战在于海量时间线导致forward index过大,占用空间大,导致查询写入过程中造成大量的内存交换。
  2. 海量时间线查询的高延迟,Lindorm认为挑战在于从索引中通过tags获取时间线的后的聚合过程,以及计算的过程无法很好的并行化
  3. 认为基于规则的度量数据分析通常无法准确识别性能问题,所以需要引入机器学习分析时序数据
  4. 认为现有存储与计算没有分离的TSDB存在扩容时的性能问题

系统架构

Lindorm Tsdb包含四个主要组件,其中TSProxy和TSCore允许水平扩容:

  1. TSProxy
  2. TSCore
  3. Lindorm ML
  4. Lindorm DFS
    在这里插入图片描述
    路由策略非常简洁,TSProxy负责路由请求,通过时间和serieskey两个维度路由请求,对于一个请求先基于时间判断shard group的归属,其次在一个shard group内部基于series key hash做分片。

一个用户的读写请求会拆分到多个shard上,每个TsCore管理多个shard,这可以使得一段时间内一个serieskey的所有数据位于同一个shard。在单独的shard上,数据以及其对应的索引数据首先存储在内存中,随后持久化到所有TsCore共享的DFS中。

其次TsCore扩容时可以选择创建一个新的shard group,不改变历史数据的物理分布,这样在扩容时无需迁移数据,不影响线上服务质量。当然时序的分裂要做成类似于kv的分裂也很困难,因为数据的组织格式是series key+field级别的列存,路由方式是serieskey hash,而查询的维度是time+tags,在分裂期间很难在一个引擎中支持两个哈希区间的查询,其次迁移期间索引和数据都需要拆分。

在这里插入图片描述
可以看到这个架构融合了shared-nothingshared-storage的设计,计算与存储分离。

  1. TsCore/TsProxy层面 shared-nothing,可水平扩展提升读写性能。
  2. DFS层面 shared-storage,负责提供高可用。

可以看到TsCore层面没有选择一致性算法提供高可用,而是依赖于共享存储;我个人觉得这样的做法并不是最优,因为当一个TsCore故障时立马补充一个TsCore,需要先重放没有落DFS的WAL后才能提供服务。而一致性算法中副本可以是一个状态机,切主后立即提供服务。

值得一提的是路由信息,也就是TsCoreshards的映射关系存储在ZooKeeper中,这让我有理由怀疑Lindorm集群的路由推送效率,其次ZooKeeper作为控制面也无法完成一些高级的调度策略(比如基于集群的各种指标判断是否分裂和配置项下发)。

细节/优化

存储引擎

  1. TSD文件和索引携带TTL,在后台压缩期间判断是否删除
  2. DFS中可以根据TSD的时间戳判断是否要存入更便宜的介质中(DFS由ESSD cloud diskObject Storage Service构成)
  3. 无锁压缩用于内存数据,以提高内存利用率;WAL日志采用字典批量压缩,以减少IO;TSD中采用Delta-of-delta, XOR, ZigZag, RLE等常规算法压缩

索引

  1. 由于大量短时间序列的存在(容器的创建销毁,会议号,视频ID等),很多序列会迅速失效,所以在一个shard内部需要继续基于时间划分time partitions,每个time partitions内部包含独立的索引。
  2. time partitions过多时,启动采用lazy loading,优先加载最新分区,异步加载历史分区。
  3. forward indexinverted index在memtable中写入,触发刷新时memtable中的两个索引分别生成FwdIdxInvIdx文件
  4. 为了加速索引的查找速度,后台合并减少文件数,其次每个文件中添加bloom filter[1],最后使用Block Cache缓存部分文件内容
  5. forward index访问频率远大于inverted index,写入过程中需要判断是否存在某个serieskey,查询时需要获取tsid对应的serieskey;所以引入seriescache,Block cache缓存文件数据,而seriescache缓存ID到serieskey之间的映射,采用LRU淘汰,因为serieskey较大,选择MD5替换serieskey。
  6. 根据不同的Tag在倒排索引中获取ID List,利用RoaringBitmap做列表合并
  7. 考虑到历史时间序列处于非活跃状态,采用时间分区来提高内存利用率,历史shard的常驻内存适当减少

写入

  1. SQL引擎采用Apache Calcite,写入采用insert语句,但是写路径通过引擎性能较差,所以实现了一个简易的写入解析器,bypass SQL引擎
  2. SQL prepare可以用于客户端的批量写入优化

查询

请添加图片描述

  1. TSProxyTsCore均实现的pipelined execution engine,支持计算下推,允许多个TsCore之间并行计算,此外一个TsCore的多个partition,一个partition的多个shard之间都可以并行计算。行迭代器驱动整个流水线引擎执行,可以在流水线中自定义时间线维度的算子,数据会流经pipeline中所有的算子,完成后释放这部分内存
  2. 引擎中的算子基于是否downsampling被划分为两类;
    a. downsampling : aggregation (DSAgg) , interpolation (Filling)
    b. non-downsampling : rate of change (Rate) , obtaining the difference (Delta).
  3. 预降采样,为了减小预将采样对于写入的影响,只有在memtable被下刷到共享存储和压缩时才会执行预降采样
  4. 实现了跨time-series的算子(series_max?)

经验

  1. 节点故障很常见,新TSCore在接管故障TSCore时需要重放完WAL才能提供服务,这可能造成服务中断,所以设计了WAL异步载入,先允许写,重放完成后允许读
  2. 采用图表化多字段模型,并支持SQL不但有助于用户理解,而且方便DBA解决问题
  3. 启动预降采样可以用8%的存储空间换取80%的查询延迟,DFS中存储分层,允许历史数据存储在对象存储,且于实时查询和连续查询相比资源消耗极低
  4. 没有流水线执行引擎必须一次读出所有数据,导致内存耗尽
  5. first/last使用频繁,这需要高qps和低延迟,为此Lindorm专门设计了一种缓存,在查询时,每个时间序列的最新值都会被缓存起来,并在该时间序列写入新数据点时进行更新,实施这种缓存后查询响应时间缩短了 85%

Ablation Study

Lindorm认为性能的关键在于两点:

  1. push-down optimization in the pipeline streaming execution engine
  2. seriescache for the forward index.

对照实验结果如下:
在这里插入图片描述
很好理解,没有计算下推的情况TsProxy需要计算全部的数据,第一数据传输量大,第二没有节点级别并行化

在这里插入图片描述
效果非常明显,写吞吐提升在23.8%到232%,而且对于where time > now() -2h group by * , time(5m)的查询时延也降低了15.3到32.2%

总结

文章中可以看出不少地方存在改进空间,但是不得不承认Lindorm TSDB可学习的地方很多,感谢Lindorm团队的无私奉献。

参考:

  1. 比 Bloom Filter 节省25%空间!Ribbon Filter 在 Lindorm中的应用

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

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

相关文章

我的创作纪念日:一个特别的纪念日

一个特别的纪念日 机缘收获日常成就憧憬 💡一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C、Linux、中间件、数据库、云…

【C++学习笔记】7、常量

文章目录 【 1、常量的分类 】1.1 整型常量1.2 浮点常量1.3 字符常量1.4 字符串常量1.5 布尔常量 【 2、常量的定义 】2.1 #define 预处理器2.2 const 关键字 常量 是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数…

网络安全合规-DSMM

DSMM(Data Security Management Model)是一种数据安全管理模型。该模型以数据为中心,从数据的生命周期入手,从数据发布、使用、共享、存储、删除等几个方面来管理数据安全。 DSMM提供了一些有效的数据安全管理原则和策略&#xf…

ArcGIS Engine10.2 Setup 报错

00 问题重述 当我尝试安装ArcGIS Engine时弹出错误:ArcGIs 10,2 Engine cannot be installed on your machine.ArcGIs 10,2 Engine requires Microsoft ,NET Framework 3.5sp1, Which has not been found on your system, If you want to download and install Mic…

Ubuntu18.04系统下通过moveit控制kinova真实机械臂,并用python脚本到达固定点

测试工作空间:test_ws Kinova机械臂型号:m1n6s300 双臂模型中的左臂 测试功能包为kinova-ros官方包 一、读取kinova机械臂末端执行器位姿及tf小知识 1. tf小知识之获取两个连杆坐标系的位姿关系,非常有用,非常有用,非…

Unity中Shader的变体shader_feature(青莲地心火 o.o )

文章目录 前言一、变体的类型1、multi_compile —— 无论如何都会被编译的变体2、shader_feature —— 通过材质的使用情况来决定是否编译的变体 二、使用 shader_feature 来控制 shader 效果的变化1、首先在属性面板暴露一个开关属性,用于配合shader_feature来控制…

Flask狼书笔记 | 05_数据库

文章目录 5 数据库5.1 数据库的分类5.2 ORM5.3 使用Flask_SQLAlchemy5.4 数据库操作5.5 定义关系5.6 更新数据库表5.7 数据库进阶小结 5 数据库 这一章学习如何在Python中使用DBMS(数据库管理系统),来对数据库进行管理和操作。本书使用SQLit…

02JVM_垃圾回收GC

二、垃圾回收GC 在堆里面存放着java的所有对象实例,当对象为“死去”,也就是不再使用的对象,就会进行垃圾回收GC 1.如何判断对象可以回收 1.1引用计数器 介绍 在对象中添加一个引用计数器,当一个对象被其他变量引用时这个对象…

软件架构之前后端分离架构服务器端高并发演进之路

软件架构之前后端分离架构&服务器端高并发演进之路 前后端分离架构服务器端关于不同并发量的演进之路1. 单体架构2. 第一次演进:应用服务器和数据库服务器分开部署3. 第二次演进:引入本地缓存和分部署缓存4. 第三次演进:引入反向代理和负…

SQL语句如何生成PDM文件

首先我们先了解一下什么是PDM 物理数据模型(PDM)是数据库设计和管理过程中的重要组成部分,具有以下好处: 可视化数据库结构: PDM提供了一个直观的方式来可视化数据库的结构,包括表、列、索引、关系等。这使…

数据结构与算法学习(day4)——解决实际问题

前言 在本章的学习此前,需要复习前三章的内容,每个算法都动手敲一遍解题。宁愿学慢一点,也要对每个算法掌握基本的理解! 前面我们学习了简化版桶排序、冒泡排序和快速排序三种算法,今天我们来实践一下前面的三种算法。…

QT连接OpenCV库完成人脸识别

1.相关的配置 1> 该项目所用环境:qt-opensource-windows-x86-mingw491_opengl-5.4.0 2> 配置opencv库路径: 1、在D盘下创建一个opencv的文件夹,用于存放所需材料 2、在opencv的文件夹下创建一个名为:opencv3.4-qt-intall 文…

Android Glide in RecyclerView,only load visible item when page return,Kotlin

Android Glide in RecyclerView,only load visible item when page return,Kotlin base on this article: Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin_zhangphil的博客…

L1和L2正则

L1和L2正则 L1正则常被用来进行特征选择,主要原因在于L1正则化会使得较多的参数为0,从而产生稀疏解,我们可以将0对应的特征遗弃,进而用来选择特征。一定程度上L1正则也可以防止模型过拟合。 L2正则: L1损失函数相比于…

口袋参谋:淘宝卖家如何对订单实现批量标旗?

​插旗在淘宝店铺里是经常能使用到的,如果淘宝卖家订单量太大,一个一个的标旗太过于繁琐,而且容易出错。 那么使用批量插旗工具,则可以大大节省卖家时间,提高工作效率! 【批量插旗】功能: 一键…

基于blockqueue的生产和消费模型

线程篇下讲的是基于阻塞队列的生产者消费者模型。在学习这个之前我们先了解一些其他概念: 同步:在保证数据安全的条件下,让线程按某种特定的顺序依次访问临界资源。 通过上一节的代码我们实现了一个多线程抢票的程序,但结果显示…

Pytorch学习:卷积神经网络—nn.Conv2d、nn.MaxPool2d、nn.ReLU、nn.Linear和nn.Dropout

文章目录 1. torch.nn.Conv2d2. torch.nn.MaxPool2d3. torch.nn.ReLU4. torch.nn.Linear5. torch.nn.Dropout 卷积神经网络详解:csdn链接 其中包括对卷积操作中卷积核的计算、填充、步幅以及最大值池化的操作。 1. torch.nn.Conv2d 对由多个输入平面组成的输入信号…

ChatGPT AIGC 完成超炫酷的大屏可视化

大屏可视化一直各大企业进行数据决策的重要可视化方式,接下来我们先来看一下ChatGPT,AIGC人工智能帮我们实现的综合案例大屏可视化效果: 像这样的大屏可视化使用HTML,JS,Echarts就可以来完成,给ChatGPT,AIGC发送指令的同时可以将数据一起发送给ChatGPT。 第一段指令加数…

Direct3D绘制旋转立方体例程

初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp #include <windows.h> #include "d3dUtility.h" #include <d3dx9math.h>IDirect3DDevice9* Device NULL; IDirect3DVertexBuffer9* VB NULL; IDirect3…

【C语言】入门——结构体

目录 结构体 为什么有结构体&#xff1f; 1.结构体的声明 1.2结构体变量的访问和初始化 2.结构体成员的访问 结构体 struct 结构体类型 {//相关属性; }结构体变量; 结构体和数组不同&#xff0c;同一类型的数据的集合是数组&#xff1b; 结构体是多种类型的数据的集合&…