从一到无穷大 #16 ByteSeries,思考内存时序数据库的必要性

2023-09-16 16:20:20

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

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

引言

在[3]中我基于Gorilla讨论了时序数据库设置cache的可行性,最后得出结论:RAM去换实时查询的高效,显著增加成本的同时增加系统复杂性。

但是如果换个思路,缓存即为内存时序数据库,长久存储为为其他(分布式文件系统,对象存储,基于磁盘的时序数据库),这个选择又变得合理起来,因为不少研究对于使用内存加速数据写入和实时查询做了广泛的研究[4][5][6],这意味着内存时序数据库相比基于磁盘的时序数据库(写入过程可能存在多次IO操作,查询会触发多次IO操作)有着得天独厚的优势。

此时的权衡点回到了上篇文章中讨论的重点,是否存在Gorilla中提到的“26H”呢,如果线上负载存在的话此类假设,cache的存在是一个杀器,不但加速写入(批量写入后端磁盘存储),实时查询的速率也极其优秀(可以达到10ms级别)。

另外如果使用基于磁盘的时序数据库作为远端存储,对于历史数据的查询也会很快。但是缺陷就是宕机恢复流程会相对复杂,所以如果存在一个副本和主一样应用状态机问题就不是很大,缺陷是如果多副本宕机启动会非常慢。但是问题在于基于磁盘的时序数据库一般对于内存要求较高,无论是compaction,shard的forward index/inverted index的缓存,TSM的缓存,查询期间的内存消耗都不小,这导致如果要在基于磁盘的时序数据库内存中做cache的话要么提升机器内存规格(问题是请求进入引擎以及apply了raft log,在引擎内部做cache意味着需要在raft log外再维护一个log,用于宕机时内存数据恢复,好处是实时写入和实时查询性能提升),要么再加一层(类似于ByteSeries,Gorilla)。

结论:线上负载要求写入和实时查询高性能,时序数据库+缓存(内存时序数据库)可行。

ByteSeries的文章只是阐述了内存存储引擎,对分布式实现(数据如何分片,分布式查询聚合如何实现,难道真的只有一个节点?)和如何沉降冷数据没有提及。

内存布局

Active Segment

在这里插入图片描述

数据首先写入Active Segment,且这个关键路径不做复杂的数据转换和压缩,写入根据SeriesKey的哈希值决定写入哪个Segment ShardSegment Shard由一个追加写入的数组和动态的倒排索引组成。

分片的原因有两个:

  1. 并行数据写入
  2. 将数据从Active Segment转入Static Segment需要暂停写入,并重新分配新的segment,在分片的情况下转换可以是segment级别的,不需要执行整个缓冲区级别的内存分配。

Static Segment

线上100亿时间线的数据在元数据上可以看做10万个tag以及每个tag下数万个tag值。

Static Segment分为两个部分,Static SegmentCompressed Segment,SS数据累计到一定量时转换为CS,这里的目的主要是为了分批进行压缩,均摊昂贵的压缩开销。

在这里插入图片描述

新添加的数据直接添加到数组中,倒排索引中存储数组的偏移量,然后多个Temporary Static Segment合并成一个Static Segment,显然此时属于一个series key的数据还分布在数组的各处,并没有存储在连续空间内,也会导致索引中存储大量的下标值,而且数据点本身也没有办法压缩。

所以Static Segment会进一步转换为Compressed Segment,CS中属于一个Series key的数据都属连续存储的,这样可以减小数据的大小,索引中也只需要存储一个偏移。注意,这里其实存储结构其实是:

  1. 使用tire存储series key,指向compressed list的下标,compressed list内部指向此series key的Compressed data string
  2. Compressed data string指向压缩的数据点

文章最精髓的地方其实在于倒排索引的压缩:
在这里插入图片描述

构建倒排的步骤如下:

  1. 对所有的tagkv构建倒排索颖。即tagkv -> series keys 的偏移
  2. tagkey:使用前缀树压缩,这个思路没什么问题,不但可以极致的压缩tagkey,还允许范围查询。cedar[1]实现,个人认为redis的Redix tree也很适合这里的存储。
  3. tagvalue:把所有的series key list按顺序写入total inverted index array数组,这其中可以存在重复,因为不同的tagkey可以指向同样的serieskey,inverted index offset存储每个tagkv在total inverted index array数组的起始值,这意味这可以迅速找到tagkv对应的serieskey list。使用p4nzenc64来压缩这两个数组

其实可以看到,本质上和基于磁盘的invert index+TSM没有区别,无非去除了forward index,改为数组的下标。这带来的劣势时必须看作这个Compressed Segment已经封闭,且无法修改,不然整个结构全部都要变化。

Data Conversion Scheduler(DCS)

有三个上面提到的功能:

  1. AS转换为TSS
  2. 多个TSS与SS合并
  3. SS转换转换为CSS

值得关注的是这里需要考虑AS的写入吞吐和AS转换为TSS的速率是否匹配,否则可能导致压缩为TSS成为瓶颈,进而导致写入受限。

具体细节没什么好说的,DCS运行在一个单独的线程,执行一系列提前预设好的规则执行调度,其实就是基于维度,大小等条件判断。

评估

文章中把ByteSeries与 tsdc, Prometheus and Gorilla三个数据库从三个维度做了评估,分别为:

  1. 每个维度使用的字节数
  2. 写入速率
  3. single group bydouble group by查询速率

可以预想的,在高维度的场景下ByteSeries原数据所使用的内存非常少,这也很好理解,因为tagkey本身被极致压缩,元数据还只需要指向一个index。写入速率受转换的原因不如Gorilla。

总结

很优秀的内存压缩元数据思路,事实上可以认为这种方法是解决维度爆炸场景下写入和实时查询性能的一种可行方式。

引用:

  1. cedar - C++ implementation of efficiently-updatable double-array trie
  2. TurboPFor-Integer-Compression
  3. 从一到无穷大 #15 Gorilla,论黄金26H与时序数据库缓存系统的可行性
  4. Btrdb: Optimizing storage system design for timeseries processing FAST 2016
  5. Akumuli Numeric B+tree
  6. RTSI: An Index Structure for Multi-Modal Real-Time Search on Live Audio Streaming Services ICDE 2018
更多推荐

Qt扩展-KDDockWidgets 简介及配置

Qt扩展-KDDockWidgets简介及配置]一、概述二、编译KDDockWidgets库1.CmakeGui中选择源文件和编译后的路径2.点击Config,配置好编译器3.点击Generate4.在存放编译的文件夹输入如下命令开始编译三、qmake配置一、概述kdockwidgets是一个由KDAB组织编写的qtd

【Azure上云项目实战】 合规性的身份验证与访问控制:在 Azure 中实现符合 PCI DSS 要求的架构设计

文章目录一、开篇写在前面二、项目背景及介绍三、AzurePCIDSS项目架构及组件四、身份验证、访问控制4.1三层防御控制4.2三层部署结构五、跳板机六、与PCIDSS要求的关系七、该篇总结(重要)写在文末一、开篇写在前面各位博客阅读者们以及对云计算感兴趣的小伙伴们,微软Azure云的基础部分更新已经接近了尾声,从上周

prize_p1

文章目录解题过程代码审计思路问题解决数组绕过preg_match__destruct的触发修改phar文件以及签名phar://支持的后缀(其他方法)题解方法一(数组绕过)方法二(gzip绕过)解题过程源代码<METAhttp-equiv="Content-Type"content="text/html;charset

【UE 粒子练习】02——使用一些常用的模块来创建粒子

目录效果步骤一、创建材质二、创建粒子2.1必需模块2.2初始大小模块2.3初始位置模块2.4初始速度模块2.5生命周期模块2.6加速-》恒加速度模块2.7生成模块2.8生命内颜色模块2.9尺寸-》大小随速度模块2.10碰撞-》Actor碰撞模块2.11光源-》光照模块效果步骤一、创建材质1.新建一个材质,这里命名为“M

如何使用WOFOST和PCSE这两个农业生产模型进行作物生长模拟??

WOFOST(WorldFoodStudies)和PCSE(PythonCropSimulationEnvironment)是两个用于农业生产模拟的模型:WOFOST是一个经过多年开发和验证的模型,被广泛用于全球的农业生产模拟和农业政策分析;采用了模块化的结构,可以对不同的农作物和环境条件进行参数化和适应;WOFOST

五个很实用的IDEA使用技巧

日常开发中,相信广大Java开发者都使用过IntelliJIDEA作为开发工具,IntelliJIDEA是一款优秀的Java集成开发环境,它提供了许多强大的功能和快捷键,可以帮助开发者提高编码效率和质量。除了一些常见的技巧,如自动导包、智能补全、重构工具等。IntelliJIDEA还有一些不为人知的技巧,可能很多开发者

基于 kubernetes+docker构建高可用、高性能的 web 、CICD集群

文章目录一、项目架构图二、项目描述三、项目环境四、环境准备1、IP地址规划2、关闭selinux和firewall3、配置静态ip地址4、修改主机名5、升级系统(可做可不做)6、添加hosts解析五、项目步骤1、设计整个集群的架构,规划好服务器的IP地址,搭建集群2、部署ansible完成相关软件的自动化运维工作,部署

TCP协议

TCP收发数据流程TCP如何收发数据分段发送可靠传输在TCP协议中,任何时候、任何一方都可以主动发送数据给另一方为了解决数据报丢失、数据报错乱等问题,TCP协议要求:接收方收到数据报后,必须对数据报进行确认!seq:表示这次数据报的序号ACK:表示这次数据报是一个确认数据报ack:表示期望下一次接收的数据报序号发送方如

NLP技术如何为搜索引擎赋能

目录1.NLP关键词提取与匹配在搜索引擎中的应用1.关键词提取例子2.关键词匹配例子Python实现2.NLP语义搜索在搜索引擎中的应用1.语义搜索的定义例子2.语义搜索的重要性例子Python/PyTorch实现3.NLP个性化搜索建议在搜索引擎中的应用1.个性化搜索建议的定义例子2.个性化搜索建议的重要性例子Pyt

【计算机辅助蛋白质结构分析、分子对接、片段药物设计技术与应用】

第一天上午生物分子互作基础1.生物分子相互作用研究方法1.1蛋白-小分子、蛋白-蛋白相互作用原理1.2分子对接研究生物分子相互作用1.3蛋白蛋白对接研究分子相互作用蛋白数据库1.PDB数据库介绍1.1PDB蛋白数据库功能1.2PDB蛋白数据可获取资源1.3PDB蛋白数据库对药物研发的重要性2.PDB数据库的使用2.1靶

mysql 注入之权限

SQL注入之高权限注入在数据库中区分有数据库系统用户与数据库普通用户,二者的划分主要体现在对一些高级函数与资源表的访问权限上。直白一些就是高权限系统用户拥有整个数据库的操作权限,而普通用户只拥有部分已配置的权限。网站在创建的时候会调用数据库链接,会区分系统用户链接与普通用户链接;当多个网站存在一个数据库的时候,root

热文推荐