饿了么 Influxdb 实践之路

饿了么 Influxdb 实践之路


前言

Influxdbhttps://github.com/influxdata/influxdb)是一个基于 golang 编写,没有额外依赖的开源时序数据库,用于记录 metrics、events,进行数据分析。这篇文章谈论的 influxdb 版本在1.2.0以上。mysql

这篇文章只谈论 influxdb 在监控中的数据存储应用,不会谈论 influxdb 提供的整套监控方案。本文主要谈论五个方面:时序数据库选型、influxdb 基本概念、存储引擎、实践、数据聚合。git

选型

Influxdb vs Prometheus

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

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

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

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

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

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

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

  8. 更详细的对比请参考:对比(https://db-engines.com/en/system/Graphite%3BInfluxDB%3BPrometheus)。架构

咱们其实仅仅须要的是一个数据库,其余组件都是本身开发的,并且存储的数据类型不只仅是数字,所以选择了 influxdb。但愿上面的比较对你们有帮助。

Influxdb 基本概念

Database

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

Measurement

描述了相关数据的存储结构,相似于 mysql 的 table,可是不须要建立,写入数据的时候自动建立。关于 schema 的设计建议参考:设计建议https://docs.influxdata.com/influxdb/v1.2/concepts/schema_and_data_layout/)。

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(https://docs.influxdata.com/influxdb/v1.2/query_language/continuous_queries/)。

Shard

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

存储引擎

概述

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

Cache

插入数据时,先往 cache 中写入再写入 wal 中,能够认为 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 存储引擎解析(http://blog.fatedier.com/2016/08/05/detailed-in-influxdb-tsm-storage-engine-one/

实践

项目介绍

gateway(https://github.com/pingliu/influxdb-gateway)用于检测和压缩influxdb的数据,用于跨机房传输,采用udp接受数据。

influxdb-relay(https://github.com/influxdata/influxdb-relay)是官方提供的高可用方案,可是它只提供简单的写入功能。

influxdb-proxy(https://github.com/shell909090/influx-proxy)是用于替代 influxdb-relay 的高可用方案。

前期架构图

blob.png

使用问题

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。能够将这个时间设置成大点。

优化后的架构图

blob.png

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

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

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

  3. 限制部分查询命令和所有删除操做。

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

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

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

数据聚合

CQ

influxdb 提供数据聚合的功能,就是上面基本概念里提到的 Continuous Query。预先定义好cq,就能够按期根据不一样的tag进行聚合数据。目前它有个设计问题:cq 是顺序执行的,cq 越多,数据延迟越高,通常延迟在几分钟内。若是须要更实时的聚合,cq 不能知足,须要引入其余工具,好比spark。关于 cq 的语法请参考:语法(https://docs.influxdata.com/influxdb/v1.2/query_language/continuous_queries/)。

Spark

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

blob.png

总结

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

相关文章
相关标签/搜索