influxdb数据写入

时间:2024-04-06 13:14:32

1、influxDB写入总体框架

数据写入很多时候是批量写入,很少只是写入少量的一个数据的情况,当然写一个数据的过程其实和批量写入过程是类似的,这里讲解一下批量写入的过程
influxdb数据写入
批量数据进入到influxDB之后总体会经过三个步骤的处理:
(1)批量时序数据shard路由:influxDB首先会将这些数据根据shard的不同分成不同的分组,每个分组的时序数据会发送到对应的shard。
(2)倒排索引引擎构建倒排索引:InfluxDB中shard由两个LSM引擎构成-倒排索引引擎和TSM引擎。时序数据首先会经过倒排索引引擎构建倒排索引。
(3)TSM引擎持久化时序数据:倒排索引构建成功之后时序数据会进入TSM Engine。TSM Engine处理流程:先将写入请求追加写入WAL日志,再写入cache,满足特定条件就将cache中的时序数据执行flush操作落盘形成TSM File

2、批量时序数据shard路由

influxdb sharding策略实际上有两层:Range Sharding和Hash Sharding。在influxdb里面有shard group和shard的概念,具体的讲真正按照时间分片的是shard Group,对于单节点的influxdb,一个shard group下面只有一个shard,对于集群类型的,一个shard group下面会有多个shard,在映射到shard group的层级,使用的是Range sharding,就是时间映射,然后在集群中,再通过hash(series)映射到对应的shard,这个就是hash sharding。相同shard group,同一个series的数据一定在同一个shard里面,

3、倒排索引引擎构建倒排索引

倒排索引的作用是为了在给定某个或者某几个tag的情况下,数据库可以快速搜索到对应的key(masurement + tags + field key)。倒排索引引擎使用的也是LSM引擎(LSM写性能友好的特点适用于influxdb写多读少的特性,所以无论是倒排索引引擎还是数据引擎都使用lsm引擎自然无可厚非),所以工作机制自然就是:首先将数据追加写入WAL再写入Cache就可以返回给用户写入成功,WAL可以保证即使发生异常宕机也可以恢复出cache中丢失的数据。一旦满足特定条件系统会将cache中的时序数据执行flush操作落盘形成文件。文件数量超过一定阈值系统会将这些文件合并形成一个大文件。具体的倒排索引流程比较复杂,先不做细致讨论。

4、时序数据写入流程

(1)WAL追加写入:经过两步,第一步把数据格式化为WAL单个条目对象的格式,第二部经过snappy压缩持久化到wal文件
单个条目文件结构参见:http://leanote.com/blog/post/5afe6e9fab64410945000d99
(2)写入cache
第一步:数据格式化。格式化为一个Map<key,List<timeStamp|value>>
第二步:时序数据点写入cache。influxDb中cache是一个crude hash ring,这里的ring是由256个partition构成,每个partition负责存储一部分时序数据Key对应的值,写入数据的时候首先会根据key hash一次,hash到对应的partition。为什么这么处理,个人认为有点像Java中ConcurrentHashMap的思路,将一个大HashMap切分成多个小HashMap,每个HashMap内部在写的时候需要加锁。这样处理可以减小锁粒度,提高写性能。

(3)flush to tmsFile
触发时机:Cache执行flush有两个触发条件,一是当cache大小超过一定阈值,可以通过参数’cache-snapshot-memory-size’配置,默认是25M大小;二是超过一定时间阈值没有数据写入WAL也会触发flush,默认时间阈值是10分钟,可以通过参数’cache-snapshot-write-cold-duration’配置


基本流程:其实TSM file我们知道基本结构分为四个部分–header、block、index、footer,对于header数据是很好设置的,footer数据存放的是index的起始位置,那么先要搞定index才行。所以我们关键要做的是对block和index的赋值

  • 构建Series Data Block: 首先会在内存中构建series data block:顺序遍历内存Map中的时序数据,分别对时序数据的时间列和数值列进行相应的编码,按照Series Data Block的格式进行组织,当Block大小超过一定阈值就构建成功,并记录这个Block内时间列的最小时间MinTime以及最大时间MaxTime构建好之后写入文件,返回Block在文件中的偏移量Offset以及总大小Size
  • 构建文件级别B+索引:在内存中利用上面返回的Offset、Size、MinTime、MaxTime构建一个IndexEntry对象,写入到内存中的Series Index Block对象

这样,每构建一个Series Data Block并写入文件之后都会在内存中顺序构建一个Index Entry,写入内存Series Index Block对象。一旦一个key对应的所有时序数据都持久化完成,一个Series Index Block就构建完成,构建完成之后填充Index Block Meta信息,接着新建一个新的Series Index Block开始构建下一个Key对应的数据索引信息

对于Block Index,为了快速定位到对应key在哪一个Block Index,influxdb还引入了间接索引offsets,offsets是一个数组,存放了对应key在index表中的位置,这些元素是按照key进行字典排序的,所以给出一个key的时候,可以通过二分查找,快速找到block index的位置,在block index里面,每一个index entry可以根据时间戳进行第二次二分查找,最后就可以找到对应block的位置

数据压缩

数据写入到wal和tsm文件之后,会按照一定的编码进行compaction,具体压缩细节这里不做讨论