前言

数据,海量或千亿级是整体的量,是一个笼统的概念,我们可 分而治之 。也就是所谓的集群的方式来实现。海量监控数据的真正的挑战,笔者认为有一下几点:

  • 实时性。目前笔者负责的是公司的监控业务,虽然笔者对这块啥都不知道,除了知道几个开源名称之外,啥也不懂。但是监控指标数据的实时性是很重要的,这个笔者还是很清楚的。
  • 分集群后,单个业务的流量大小,标签集多少会决定查询的效率。如何去做这个查询的优化时很关键的事情(公司目前遇到的难题)
  • 针对监控数据多写少读,成本低敏的特点,如何去设计高效的存储引擎。既能充分发挥硬件性能,又能在高效压缩存储的同时保障查询效率。

简介

InfluxDB 是一个用于存储和分析时间序列数据的开源数据库(集群模式的不对外开源)。适合处理和分析资源监控数据这种时序相关的数据。自带的各种特殊函数(标准差,随机取样,统计数据变化比)等,使得数据分析变得十分方便。

使用场景

物联网设备监控

Influxdb 最初是因为物联网的兴起的数据库。天生就具备 IOT 的特性;

InfluxDB支持高性能的时序数据写入与分析,适用于物联网设备监控场景,通过IoT平台采集用户物联网设备的监控指标,将原始数据全量写入到InfluxDB中,通过其丰富的分析函数可快速分析物联网设备生成的时序数据,并输出到监控系统进行可视化监控。

互联网业务性能监控

除了物联网场景外,InfluxDB同时还可以用于日志数据存储与分析,各种服务、软件以及系统监控数据采集、分析与报警,金融数据采集与分析等。

互联网服务的即时性和稳定性是服务能力的关键指标,InfluxDB适用于此类数据的存储和分析,将业务服务日志、系统监控指标写入Kafka,通过Flink 进行业务规则的实时计算之后将计算结果存储到InfluxDB,业务监控系统访问InfluxDB数据库进行系统分析与数据展示。

使用场景小结

总之,只要符合 写多读少无事务要求海量高并发持续写入基于时间区间聚合分析 以及 基于时间区间快速查询 的数据都可以使用InfluxDB。

设计的初衷

  • 同一时间点多次写入同样的数据被认为是重复写入
  • 极少出现删除数据的情况,删除数据基本都是清理过期数据
  • 极少更新已有数据且不会出现有争议的更新,时间序列数据总是新数据
  • 绝大多数写入是针对最新时间戳的数据,并且数据按时间升序添加
  • 数据的规模会非常大,必须能够处理大量的读写操作
  • 能够写入和查询数据会比强一致性更重要
  • 很多time series非常短暂的存在,所以time series 数量比较大
  • 没有那个 point 是过于重要的

名词解释

与传统的数据库对比

InfluxDB 传统数据库
database 数据库
measurement 数据表
point 表中的一行数据

influxdb不需要像传统数据库一样创建各种表,其表的创建主要是通过第一次数据插入时自动创建.
point的数据结构由时间戳(time)、标签(tags)、数据(fields)三部分组成,具体含义如下:

Point 属性 含义
time 数据记录时间,是主索引(自动生成)
tags 各种有索引的属性
fields 各种 value 的值(没有索引的属性)

特有的概念

  • series(一般由:retention policy, measurement, tagset共同组成): measurement, tag set, retention policy 相同的数据集合算做一个 series。

  • Line Protocol 行协议格式 Line Protocol 定义了 influxdb 的数据写入格式,如下:

1
2
cpu_load_short,host=server02,region=us-west value=0.55 1422568543702900257
cpu_load_short,direction=in,host=server01,region=us-west value=2.0 1422568543702900257
  • Tag:维度列,代表数据的归属、属性,表明是哪个设备/模块产生的,一般不随着时间变化,供查询使用。上面的host,region 就是tag key,server02,us-west 就是tag value,tag会建立索引,tag类型只能是字符串
  • Field :指标列,代表数据的测量值,随时间平滑波动。上述行协议中value 就是filedname, 0.55是filed value,value用于数据展示,value支持类型包括:floats,integers,strings,booleans
  • TimeStamp:格式是:RFC3339 UTC。默认精确到纳秒,可选
  • Retention Policy 保留策略:保留策略包括设置数据保存的时间以及在集群中的副本个数。默认配置为:RP 是 autogen,保留时间是永久,副本为1。InfluxDB会定期清除过期的数据。

InfluxDB 特点

  • 为时间序列数据专门编写的自定义高性能数据存储引擎(TSM)。
  • Golang编写,没有其它的依赖。
  • 提供简单、高性能的写入、查询 http api。
  • 插件支持其它数据写入协议,例如 graphite、collectd、OpenTSDB。
  • 支持类sql查询语句。
  • tags可以索引序列化,提供快速有效的查询。
  • Retention policies自动处理过期数据。
  • 低成本存储,采样时序数据,压缩存储。
  • Continuous queries自动聚合,提高查询效率。

InfluxDB的性能对比:https://zhuanlan.zhihu.com/p/80062750

  • InfluxDB的写性能是OpenTSDB的5倍,存储效率是OpenTSDB的16.5倍,查询效率是OpenTSDB的3.65倍。
  • InfluxDB的写性能是MongoDB的2.4倍,存储效率是MongoDB的20倍,查询效率是MongoDB的5.7倍。
  • InfluxDB的写性能是Graphite的12倍,存储效率是Graphite的6.3倍,查询效率是Graphite的9倍。
  • InfluxDB的写性能是Cassandra的4.5倍,存储效率是Cassandra的2.1倍,查询效率是Cassandra的45倍。

InfluxDB 核心概念

http://hbasefly.com/2017/11/19/timeseries-database-2/

文章《时序数据库体系技术 – 时序数据存储模型设计》中提到时间线的概念,时序数据的时间线就是一个数据源采集的一个指标随着时间的流逝而源源不断地吐出数据,这样形成的一条数据线称之为时间线。如下图所示:

上图中有两个数据源,每个数据源会采集两种指标:butterflier和honeybees。InfluxDB中使用Series表示数据源,Series由Measurement和Tags组合而成,Tags组合用来唯一标识Measurement。Series是InfluxDB中最重要的概念,在接下来的内核分析中会经常用到。

InfluxDB 存储引擎

存储引擎将多个组件结合在一起,并提供用于存储和查询 series 数据的外部接口。他有许多组件组成,每个组件有特定的功能:

In-MemoryInde

内存中的索引是分片上的共享索引,可以快速访问measurement,tag和series。 引擎使用该索引,但不是特指存储引擎本身。

WAL

WAL是一种写优化的存储格式,允许写入持久化,但不容易查询。 对WAL的写入就是append到固定大小的段中

Cache

Cache是存储在WAL中的数据的内存中的表示。 它在运行时可以被查询,并与TSM文件中存储的数据进行合并

TSM Files

TSM Files中保存着柱状格式的压缩过的series数据

FileStore

FileStore可以访问磁盘上的所有TSM文件。 它可以确保在现有的TSM文件被替换时以及删除不再使用的TSM文件时,创建TSM文件是原子性的

Compactor

Compactor负责将不够优化的Cache和TSM数据转换为读取更为优化的格式。 它通过压缩series,去除已经删除的数据,优化索引并将较小的文件组合成较大的文件来实现

Compaction Planner

Compaction Planner决定哪个TSM文件已准备好进行压缩,并确保多个并发压缩不会彼此干扰

Compression

Compression由各种编码器和解码器对特定数据类型作处理。一些编码器是静态的,总是以相同的方式编码相同的类型; 还有一些可以根据数据的类型切换其压缩策略

Writers/Readers

每个文件类型(WAL段,TSM文件,tombstones等)都有相应格式的Writers和Readers

写入协议

行协议

InfluxDB的行协议是一种写入数据点到InfluxDB的文本格式。必须要是这样的格式的数据点才能被Influxdb解析和写入成功,当然除非你使用一些其他服务插件。

1
<measurement>[,<tag_key>=<tag_value>[,<tag_key>=<tag_value>]] <field_key>=<field_value>[,<field_key>=<field_value>] [<timestamp>]

语法描述

行协议告诉TSDB For InfluxDB®数据的measurement、tag set、field set和时间戳。

元素(element) 可选/必需 描述 类型(请查看数据类型获得更多信息)
measurement 必需 measurement的名字。TSDB For InfluxDB®中每个数据点接受一个measurement。 字符串
tag set 可选 一个数据点上全部的tag key-value pairs。 tag key和tag value都是字符串。
field set 必需。数据点必须至少有一个field。 一个数据点上全部的field key-value pairs。 field key是字符串,field value可以是浮点数、整数或者布尔值。
时间戳 可选。如果没有指定数据点的时间戳,那么TSDB For InfluxDB®使用服务器本地的纳秒级时间戳(UTC格式)作为数据点的时间戳。 数据点的时间戳。TSDB For InfluxDB®中每个数据点接受一个时间戳。 Unix纳秒级时间戳。使用HTTP API指定除纳秒之外其它精度的时间戳。

性能和设置提示:

  • 在将数据点发送到数据库之前,将tag按tag key进行排序。排序结果应该与Go bytes.Compare function的结果匹配。
  • 时间戳尽量使用最粗的精度,因为这可以显著提高压缩效果。
  • 使用网络时间协议(Network Time Protocol,NTP)来同步主机(host)之间的时间。TSDB For InfluxDB使用主机的本地UTC时间为数据分配时间戳;如果主机的时钟与NTP不同步,写入TSDB For InfluxDB的数据的时间戳可能会不准确。

注意

  1. 性能

对于超过10万样本数据的查询操作而言,我们通过索引(即influxdb中的tag)查询将能够节省机器性能,大大降低查询时间。查询操作往往耗死机器的根本原因是:OOM(Out Of Memory)

那么在配置CQ时,应该:

  • 尽可能使用tag;
  • 应该拿写好的CQ充分模拟线上环境的测试,证明性能没问题后再上线。
  1. retention policy

配置数据的留存策略好处是数据持久化,但数据量较大时劣势也非常明显,会占用很大的CPU,造成读写数据异常。所以配置RP时我们必须注意:

  • 尽量在读写并发量较小的时刻去操作;
  • 可以在influxdb slave库中反复设置RP实践出最佳方式再上线。

参考

阿里云InfluxDB®高可用设计

阿里云InfluxDB® Raft HybridStorage实现方案