饿了么 Influxdb 实践之路

向作者提问
基于saltstack的开发配置管理系统,服务于饿了么上万台机器管理 基于golang、influxdb、grafana开发监控系统,服务于饿了么上万台机器以及基础设施
查看本场Chat

前言

Influxdb是一个基于golang编写,没有额外依赖的开源时序数据库,用于记录metrics、events,进行数据分析。这篇文章谈论的influxdb版本在1.2.0以上。这篇文章只谈论influxdb在监控中的数据存储应用,不会谈论influxdb提供的整套监控方案。本文主要谈论五个方面:时序数据库选型、influxdb基本概念、存储引擎、实践、数据聚合。

选型

Influxdb vs Prometheus

  1. influxdb集成已有的概念,比如查询语法类似sql,引擎从LSM优化而来,学习成本相对低。

  2. influxdb支持的类型有float,integers,strings,booleans,prometheus目前只支持float。

  3. influxdb的时间精度是纳秒,prometheus的则是毫秒。

  4. influxdb仅仅是个数据库,而prometheus提供的是整套监控解决方案,当然influxdb也提供了整套监控解决方案。

  5. influxdb支持的math function比较少,prometheus相对来说更多,influxdb就目前使用上已经满足功能。

  6. 2015年prometheus还在开发阶段,相对来说influxdb更加稳定。

  7. influxdb支持event log,prometheus不支持。

  8. 更详细的对比请参考:对比

我们其实仅仅需要的是一个数据库,其他组件都是自己开发的,而且存储的数据类型不仅仅是数字,因此选择了influxdb。希望上面的比较对大家有帮助。

Influxdb基本概念

Database

数据库是个逻辑容器,包含了measurement、retention policies、continuous queries、time series data,类似于mysql的database。

Measurement

描述了相关数据的存储结构,类似于mysql的table,但是不需要创建,写入数据的时候自动创建。关于schema的设计建议参考:设计建议

Line Protocol

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

weather,location=us,server=host1 temperature=82 1465839830100400200
  |    -------------------- --------------  |
  |             |             |             |
  |             |             |             |
+-----------+--------+-+---------+-+---------+
|measurement_name|,tag_set| |field_set| |timestamp|
+-----------+--------+-+---------+-+---------+

Tag

上面的location和server就是tag key,us和host1是tag value,tag是可选的。不过写入数据时最好加上tag,因为它可以被索引。tag的类型只能是字符串。

Field

上面的temperature是field key,82是field value。field value会用于展示,value支持的类型有floats,integers,strings,booleans。

Timestamp

格式是:RFC3339 UTC。默认精确到纳秒,可选。

Series

measurement, tag set, retention policy相同的数据集合算做一个 series。理解这个概念至关重要,因为这些数据存储在内存中,如果series太多,会导致OOM。

Retention Policy

保留策略包括设置数据保存的时间以及在集群中的副本个数。默认配置是:RP是autogen,保留时间是永久,副本为1。这些配置在创建数据库时可以修改。

Continuous Query

CQ是预先配置好的一些查询命令,定期自动执行这些命令并将查询结果写入指定的measurement中,这个功能主要用于数据聚合。具体参考:CQ

Shard

存储一定时间间隔的数据,每个目录对应一个shard,目录的名字就是shard id。每一个shard都有自己的cache、wal、tsm file以及compactor,目的就是通过时间来快速定位到要查询数据的相关资源,加速查询的过程,并且也让之后的批量删除数据的操作变得非常简单且高效。

存储引擎

概述

TSM Tree是在LSM Tree的基础上稍作修改优化而来。它主要包含四个部分:cache、wal、tsm file、compactor。

Cache

插入数据时,先往wal中写再同步到cache中,可以认为cache是wal文件中的数据在内存中的缓存。

WAL

预写日志,对比mysql的binlog。其作用就是为了持久化数据,当系统崩溃后可以通过wal文件恢复cache。

TSM File

每个tsm文件的大小上限是2GB。当达到cache-snapshot-memory-size,cache-max-memory-size的限制时会触发将cache写入tsm文件。

Compactor

主要进行两种操作,一种是cache数据达到阀值后,进行快照,生成一个新的tsm文件。另外一种就是合并当前的tsm文件,将多个小的tsm文件合并成一个,减少文件的数量,并且进行一些数据删除操作。 这些操作都在后台自动完成。

目录结构

InfluxDB的数据存储有三个目录,分别是meta、wal、data。meta用于存储数据库的一些元数据,meta目录下有一个meta.db文件。wal目录存放预写日志文件,以.wal结尾。data目录存放实际存储的数据文件,以.tsm结尾。基本结构如下:


-- wal
   -- test
       -- autogen
         -- 1
            -- _00001.wal
         -- 2
            -- _00002.wal
-- data
   -- test
      -- autogen
         -- 1
            -- 000000001-000000001.tsm
         -- 2
            -- 000000001-000000010.tsm
-- meta
     -- meta.db

其中 test是数据库名称,autogen是存储策略名称,再下一层目录中的以数字命名的目录是 shard 的 ID 值,比如 autogen存储策略下有两个 shard,ID 分别为 1 和 2,shard存储了某一个时间段范围内的数据。再下一级的目录则为具体的文件,分别是 .wal.tsm结尾的文件。

更详细的参考

InfluxDB详解之TSM存储引擎解析

实践

项目介绍

gateway用于检测和压缩influxdb的数据,用于跨机房传输,采用udp接受数据。

influxdb-relay是官方提供的高可用方案,但是它只提供简单的写入功能。

influxdb-proxy是用于替代influxdb-relay的高可用方案。

前期架构图

enter image description here

使用问题

influxdb-relay是官方提供的高可用方案,但是它只提供简单的写入功能。在初期使用时,并没有多大的问题,随着influxdb在公司的推广,接入方越来越多,意味着查询方越来越多,这就带来了以下问题:

  1. grafana需要配置很多个数据源。

  2. 用户不能根据measurement来订阅数据。

  3. 数据库挂掉,就需要修改grafana的数据源。

  4. 维护困难,比如需要新增数据库,用户需要配置多个数据源,不能统一接入点。

  5. 用户查询直连数据库,用户select *数据库直接OOM,数据库会重启。

  6. relay提供的重写功能,数据是保留在内存中,一旦influxdb挂掉,就会导致relay机器内存疯涨。

踩过的坑

  1. max-row-limit不为0,会导致influxdb OOM。目前这个问题已经修复,但是grafana展示时会存在问题,配置时请设置为0。

  2. 配置查询限制参数时,会导致一些奇怪的问题,官方是不限制,请保留默认配置。

  3. 没有制定schema规范,接入方把field写成tag了,导致内存疯涨,最后OOM。理解series的概念很重要。

  4. 写入超时时间默认是10s,有时候数据写入了但返回500。可以将这个时间设置成大点。

优化后的架构图

enter image description here

influxdb-proxy是为了解决上面的使用问题而开发出来的。具有以下功能:

  1. 同时支持写和查询功能,统一接入点,类似cluster。

  2. 支持重写功能,写入失败时写入文件,后端恢复时再写入。

  3. 限制部分查询命令和全部删除操作。

  4. 以measurement为粒度区分数据,支持按需订阅。

  5. measurement优先精确匹配,然后前缀匹配。

  6. 提供数据统计,比如qps,耗时等等。

数据聚合

CQ

influxdb提供数据聚合的功能,就是上面基本概念里提到的Continuous Query。预先定义好cq,就可以定期根据不同的tag进行聚合数据。目前它有个设计问题:cq是顺序执行的,cq越多,数据延迟越高,一般延迟在几分钟内。如果需要更实时的聚合,cq不能满足,需要引入其他工具,比如spark。关于cq的语法请参考:语法

Spark

经过内部调研,发现spark+kafka是个更好的聚合方案。spark支持流式处理且支持sql功能,我们只需要将cq改成sql就行。目前这个处于尝试阶段,已经上线部分功能。目前的处理流程如下:

enter image description here

总结

上文讲的整套架构已经支撑起饿了么2万台机器的监控,目前每秒写入的点数是300k。后端influxdb的机器数量是20台左右,维护成本基本趋于零。我们的焦点目前已经从influxdb转移到数据聚合和分析上。


本文首发于GitChat,未经授权不得转载,转载需与GitChat联系。

barryz
刘老师棒棒的, 关注
arun: 刘老师,张老师棒棒的,关注
敬艺
influxdb-proxy是官方提供的吗?还是自己写的?
郭大爷: 上github搜索,shell909090,有一个仓库influxdb-proxy,就是刘师傅和shell909090写的
请问饿了么用Influxdb记录一些什么数据,设计Measurement字段的时候有一些什么需要考虑?
lwh
wal文件作为内存的缓存,会不会导致性能上的问题?
梨落
根据我之前的了解 这个是做不到measurement的迁移的。请问 如果一台机器快写满了,怎么做到数据的迁移呢?
Μг.Sυη
刘老师,关于influxdb大量数据读写的时候,性能飙升的问题您是如何处理的?我在使用influxdb实践中,大量读写中,cpu等性能参数居高不下,很困惑,您能给出些好的建议吗?
刘平: 大量读写,cpu肯定高啊,大量写我是明白的,大量读是什么场景?能否看看优化查询? 因为influxdb用于监控,查询是很少的,因为谁没事去看监控啊
1
你好,对于 > 插入数据时,先往cache中写入再写入wal中,可以认为cache是wal文件中的数据在内存中的缓存。 这一观点我觉得您的说法和官方文档有些出入,官方文档中说的是先写入wal文件再写入内存,而不是先写入内存。 官方文档: https://docs.influxdata.com/influxdb/v1.2/concepts/storage_engine/#write-ahead-log-wal
刘平: 谢谢更正
微信扫描登录