TSM存储引擎
TSM存储引擎概念
TSM存储引擎主要由几个部分组成:Cache、WAL、TSM File、Compactor。
各大组件
Cache
存储位于内存。插入数据时将数据先存入Cache,待Cache中数据到达一定数量时就将数据写入TSM File
中。在每次启动InfluxDB时会先遍历所有的WAL文件,重新构造Cache,这样即使出现故障,也不会导致数据丢失。
Cache中的数据并不是无限增长的,有一个maxSize参数用于控制当Cache中的数据占用多少内存后就会将数据写入TSM File
中。
maxSize默认大小为25MB,每当Cache达到阈值后,会将当前的Cache进行一次快照,之后清空当前Cache中的内容,再创建一个新的WAL文件用于写入,剩下的WAL文件最后会被删除,快照中的数据会经过排序后写入一个新的TSM File
中。
目前Cache设计存在一个问题。当一个快照正在被写入一个新的TSM File文件时,当前的Cache由于大量数据写入,又达到了阈值,此时前一个快照还未完全写入磁盘,InfluxDB的做法是让后续的写入操作失败,用户需要自己处理,等待恢复后继续写入数据。
WAL
WAL文件结构并不是InfluxDB或者TSM存储引擎特有的,对于常见的关系型数据库的InnoDB存储引擎也包含WAL文件结构。WAL主要是防止写入内存还未写入磁盘的数据丢失备份所用。
在插入数据时,实际流程都是同时往Cache(关系型数据库是内存内)和WAL写入数据,当服务器突然关停等问题出现可以通过WAL来恢复临时插入内存的数据。通常在启动InfluxDB或者其他关系型数据库时都会先遍历一遍WAL文件来恢复内存中还未写入磁盘的文件
TSM File
主要由四个部分组成:Header、Blocks、Index、Footer。文件格式如下:
Header | Datablock | Indexes | Footer |
---|---|---|---|
5 bytes | N bytes | N bytes | 8 bytes |
Header
Magic Number | Version |
---|---|
4 bytes | 1 byte |
Magic Number(4 bytes):表示何种存储引擎TSM存储引擎代号就是0x16d116d1 ;
Version(1byte):表示存储引擎版本号,目前TSM1,版本号为1。
Footer
Indexes offset |
---|
8 bytes |
标明了Indexes部分的起始位置的offset,便于定位Indexes。
Blocks & Index
数据都是以Block为最小读取单元存储在文件中。
文件数据块都有相应的类B+树索引,而且数据块和索引结构存储在同一个文件中。
TSM File最核心的由Series Data Section和Series Index Section两大部分组成,Series Data Section表示存储时序数据
的Block,而Series Index Section存储文件级别B+树索引
Block,用于在文件中快速查询时间序列数据块。
Datablock
Series Data Block由四部分构成:Type
、Length
、Timestamps
和Values
。
Type:表示Values中的数据类型,数值数据类型通常为int、long、float以及double等。不同的数据类型对应不同的编码方式。
Length:len(Timestamps),用于读取Timestamps区域数据,解析Block。
Timestamps:时间值
存储在一起形成的数据集,通常来说,时间序列中时间值的间隔都是比较固定的,比如每隔一秒钟采集一次的时间值间隔都是1s,这种具有固定间隔值的时间序列压缩非常高效,TSM采用了Facebook开源的Geringei系统中对时序时间的压缩算法:delta-delta编码。
Values:指标值
存储在一起形成的数据集,同一种Key对应的指标值数据类型都是相同的,由Type字段表征,相同类型的数据值可以很好的压缩,而且时序数据的特点决定了这些相邻时间序列的数据值基本都相差不大,因此也可以非常高效的压缩。需要注意的是,不同数据类型对应不同的编码算法。
Indexes
Series Index Block由Index Block Meta以及一系列Index Entry
构成。
Index Block Meta:最核心的字段是Key,表示这个索引Block内所有IndexEntry所索引的时序数据块都是该Key对应的时序数据。
keyLength:Key的长度
Key:表示该Index Block索引的Data Block的Key
Type:Data Block的Type
count:Index Entry的数量
Index Entry:表示一个索引字段
,指向对应的Series Data Block。指向的Data Block由Offset唯一确定,Offset表示该Data Block在文件中的偏移量,Size表示指向的Data Block大小。Min Time和Max Time表示指向的Data Block中时序数据集合的最小时间以及最大时间,用户在根据时间范围查找时可以根据这两个字段进行过滤。
Compactor
Compactor组件在后台持续运行,每隔一秒会检查一次是否需要压缩合并
的数据。
主要进行两种操作。
一种是Cacahe中的数据大小达到阈值后,进行快照,之后转存到一个TSM File中。
另一种是合并当前的TSM File,将多个小的TSM File合并成一个,使每一个文件尽量达到单个文件的最大大小,减少文件的数量,并且一些数据的删除也是在这个时候完成的。
读 & 写
读流程
首先根据Key找到对应的SeriesIndex Block,因为Key是有序的,所以可以使用二分查找来具体实现;
找到Series Index Block之后再根据查找的时间范围,使用[MinTime, MaxTime]索引定位到可能的Series Data Block列表;
将满足条件的Series Data Block加载到内存中解压进一步使用二分查找算法查找即可找到。
写流程
httpd 服务解析出要插入的所有 Points,以及数据库,存储策略等内容,之后调用 PointsWriter 的 WritePoints 方法插入数据;
WritePoints 函数会根据 Point 的时间戳判断出其属于哪一个 Shard,之后调用 writeToShard 函数批量将 Points 分别写入到不同的 Shard 中。
参考文献
InfluxDB TSM存储引擎之TSMFile.
influxDB系列(四)TSM引擎(存储原理).
TSM文件格式及实例解析(一).