前言

Influxdb是目前最流行的时序性数据库之一,由Go语言编写,无需特殊的环境依赖,简单方便,非常适合作为监控系统的后端存储。在容器相关领域的场景中,经常和telegraf、grafana、prometheus等开源系统相集成。从这篇文章开始,我们会从源码深入探讨Influxdb的设计思路。本系列文章基于Influxdbv1.5的源码,需要读者具备influxdb的基本使用经验。

Influxdb架构总览

首先我们先从上帝视角鸟瞰一下Influxdb的整体结构,在后续的文章中我们会深入到每一个组件进行解析。

iotdb influx协议 influxdb架构_数据库


从整体的架构分层上来讲可以分为数据持久层、内部组件层、对外服务层,我们先从最下层向上层进行分析。在存储上,Influxdb分为两种储存,一种是META存储,一种是数据存储,首先我们先从磁盘上的目录结构进行查看。

├── data
│   ├── _internal
│   │   └── monitor
│   │       ├── 100
│   │           └── 000000006-000000003.tsm
│   └── k8s
│       └── default
│           ├── 10
│               └── 000000030-000000003.tsm
├── meta
│   └── meta.db
└── wal
    ├── _internal
    │   └── monitor
    │       ├── 100
    │           └── _00024.wal
    └── k8s
        └── default
            ├── 10
                └── _00208.wal

META存储会在数据目录下生成meta.db的文件,主要存储Influxdb的meta信息,例如创建的database的名字、database的retention policy等等。数据存储主要分为两种,一种是持久化数据一种是预写的日志,对于存储系统比较熟悉的同学对于这种同步预写异步刷盘的方式并不陌生,这种方式可以很好的解决分布式数据存储同步以及写入可靠性的问题。data与wal目录下的数据都是通过TSM Engine存储而来的,二级目录的名称是数据库的名称,三级目录的名称是retention policy的名字,四级目录是Shard的id,再下一级则是实际存储的数据文件。此外细心的同学会发现wal的目录结构和data的目录结构是一模一样的,包括文件的名称,这是因为在TSM Engine最小的逻辑存储单元实体是Shard,而Shard会根据自身的配置来构建data和wal,因此他们具备相同的目录结构。

内部组件层是Influxdb中对于底层组件的封装,例如所有需要操作meta信息的场景会引用MetaClient,需要写入数据的场景会默认引用PointsWritter,需要进行数据查询的场景会引用QueryExecutor等等,这些内部组件会被上层的Service引用,因此我们不会过多的赘述这些内部组件。

对外服务层是Influxdb对外的包装,可以分为三种,一种是内部服务,通常是一些定时任务,例如PrecreatorService是一个定时创建Shard的服务,会根据时间戳进行计算,动态创建Shard所需的目录结构。RetetionPolicyService会定时的清理不同的数据库的retention policy对应的数据是否需要清理,如果需要清理则会异步进行清理。一种是外部数据服务,通常是配置数据来源的方式,可以配置为定期拉取的方式,也可以配置为UDP等等不同的方式,支持Graphite、OpenTSDB、Collectd等等。还有一种是API Service,Influxdb将自身的能力通过多种不同的API Service进行暴露,其中ContinuousQueryService是将连续查询这种特殊的数据压缩查询方式独立暴露为API;HTTPDService将平时常用的Influxdb数据库的管理、数据的查询等操作通过HTTP的方式进行暴露;SnapshotterService将Influxdb关于数据的在线备份恢复等操作暴露为API;StorageService将TSM Engine的能力通过grpc协议暴露为服务。

最后

从整体来看Influxdb的设计还是很简单的,主要就是通过各种方式将TSM Engine的能力进行封装,并在上层进行逻辑操作的封装,在下一篇文章中会从代码的角度帮大家将整体的结构进行梳理,并逐渐深入到每个模块中进行进一步的分析。