精简版
0
0
0
云栖社区>博客>正文
rchang 2019-09-09 21:17:19 浏览 300
监控
数据库
数据采集
时序
展开阅读全文
随着移动互联网和物联网的广泛应用, 90% 以上的数据是和时间相关的, 而越来越多的数据应用场景与时间信息密不可分. 时间维度的数据 (我们称之为时序数据) 是一种高维数据, 需要更为高效的数据处理方式来处理. 在实际应用场景上例如传感器网络, 移动互联网, 射频识别, 电网系统等设备时刻输出时间数据, 数据量增长非常迅速, 这对存储和管理时序数据带来了挑战.
而普通的关系型数据库主要针对事务处理, 从底层存储机制到对外 API 功能, 并不适合处理时序数据. 因此, 专门的时序数据库应运而生. 若干年中, 市面上出现了很多种不同的时序数据库, 他们或数据模型不同, 或生态不同, 或存储架构不同. 经过数年的发展, InfluxDB 一枝独秀, 在 DB-Engines 的时序数据库排行榜中, InfluxDB 高居榜首, 遥遥领先其他的时序数据库, 成为最流行的时序数据库产品.
DB-Engines 2019 年 9 月的时序数据库排行榜
阿里云 InfluxDB 基于开源 InfluxDB, 提供和开源 InfluxDB 完全相同的 API 和使用生态, 并进一步对开源 InfluxDB 在内存使用等方面做了优化提升, 增强了服务的稳定性.
阿里云 InfluxDB 还基于开源 Telegraf 提供了智能化的数据采集端, 覆盖 Telegraf 原有的所有功能, 并大幅提升了使用的便捷性. 用户可以在阿里云控制台通过点击鼠标动态调整采集策略, 而无需学习和编辑复杂的 Telegraf 配置文件.
阿里云 InfluxDB 的控制台对服务的各项主要指标也进行了监控和直观的图形化展示, 方便用户预见问题, 发现问题, 了解服务当前和历史状态.
下面我们将对阿里云 InfluxDB 的这些特点进行详细解读.
1. 阿里云 InfluxDB 的内存优化
1.1 问题背景
我们从一些技术论坛和部分重度使用开源 InfluxDB 的企业客户了解到, 他们在使用过程中遇到了 InfluxDB 进程发生 OOM 而导致进程退出, 服务不可用的情况. 那么, 开源 InfluxDB 的 OOM 问题究竟是如何发生的? 我们就先来看看这个问题的来龙去脉.
1.1.1 开源 InfluxDB 写入过程中的内存问题
首先我们介绍一下 InfluxDB 的数据存储层次架构:
如上图所示, InfluxDB 首先可以创建若干个 Databases 且没有数量限制. 用户权限的赋予就是以 Database 为单位的. 这和 MySQL 等常见的关系型数据库很类似.
Database 下面可以划分若干 Retention Policy(RP), 也就是保留策略, 每个 RP 定义了各自保留数据的时长. 创建 Database 后会自动同时创建一个默认的无限期保留数据的 RP, 用户可以继续创建不限数量的 RP, 也可以选择任意 RP 为默认的保留策略.
RP 再往下分, 是按时间段划分 ShardGroup,ShardGroup 再按 series 做 hash 分为 Shard. 但是在开源的代码中, ShardGroup 实际上没起到作用, 因为每个 ShardGroup 都固定只有一个 Shard. 所以在图中我们就略过了 ShardGroup 的定义和解释, 可以认为紧挨 RP 的下一层就是按时间段划分的 Shard.
初始的默认 RP 的每个 Shard 将负责一个自然周的数据存储与管理, 就如图中所示的数据起止日期. 较短时长的 RP 一般对应较短时长的 Shard.
Shard 的内部结构大致是这个样子的:
从图中可以看到, 每个 Shard 其实就是一个典型的 LSM Tree 体系, 有 WAL 保证数据持久性, 有 Cache 承接最新的写入数据, 有 TSM 文件作为 Cache 执行 snapshot 后刷盘的结果(Cache 中的数据是未排序, 未去重, 未压缩的, 刷入 TSM 文件后的数据时排序, 去重, 压缩的).
显而易见, 对于每个 Shard, 最消耗内存的就是 Cache 了. 开源 InfluxDB 倒是提供了控制 Cache 大小的两个参数:
- . cache-max-memory-size
- . cache-snapshot-memory-size
前者是 Cache 最大容纳的数据量, 后者是 Cache 开始做 snapshot 刷盘的数据量门限. 它们应该协同调大或调小.
这么说起来, 是不是对于内存大的机器, 将两个参数设置大一些; 对于内存小的机器, 将两个参数调小一些, 就万事大吉了呢? 问题显然没有那么简单. 回顾上面我们讲的 InfluxDB 数据管理层次, 一个 Database 可以有多个 RP, 一个 RP 又有多个 Shard, 所以一个服务一共会有多少个 Shard Cache 是很难确定的, 将会随着 Database 和 RP 的增加或减少而变化, 甚至如果发生补写老数据的情况, 一个 RP 下承担写入的 Cache 也会不止一个.
所以虽然前述两个参数设置的并不大, 但当 Cache 数量较多时, 服务可能仍然会吃光内存, 最终发生 OOM.
那是不是把 Cache 设置的特别小就没问题了呢? 也没那么简单.
首先 Cache 很小, 会导致查询时更容易发生 cache miss, 降低查询效率, 但这还不是主要的问题.
更严重的问题是, Cache 特别小, 就会发生频繁的 snapshot 和刷盘, 按照 LSM Tree 的存储机制, 后台的 compaction 将会承担更大的压力, 系统的 IO 更容易达到瓶颈. 而且, 如果 series 较多且其字符串较长, 那么一个 snapshot 中的 meta 数据将占据过高的比例, 导致每次刷盘的数据中, 实际 points 所占比例较低, 引起 "写放大" 效应, 最终恶化系统性能.
所以这两个 Cache 参数实际使用时设置恰当的难度很大, 稍有不当, 或写入数据的特性发生变化, 就容易影响系统性能, 甚至发生 OOM 等问题.
1.1.2 开源 InfluxDB 查询过程中的内存问题
我们再看看 InfluxDB 在查询过程中的内存使用.
对于一个典型的按照约束条件查询数据的 Query,InfluxDB 首先根据倒排索引确定相关的 series, 然后对每个 series 的数据分段从 TSM 文件中取出压缩块进行 decode 形成 iterator, 供上层迭代获取数据, 并最终由上层返回给客户端. 所以如果查询的数据量特别大, 那么消耗的内存也就很大.
对于查询, InfluxDB 同样给出了一些参数供用户进行设置和约束, 主要是以下 3 个:
- . max-select-point(表示单次 Query 最多可查询的点数)
- . max-select-series(表示单次 Query 最多可查询的 series 数)
- . max-concurrent-queries(表示最大并发 Query 个数)
以上参数如果不做任何限制, 大量并发的大查询可能会引起服务的 OOM 等问题.
如果单独设置很小的 max-concurrent-queries, 当用户使用大量并发的小查询时, 虽然系统完全可以承受, 但却被该参数约束而拒绝服务, 这显然不合适.
如果单独设置很小的 max-select-point 和 max-select-series, 当用户只有非并发的大查询时, 虽然系统完全可以承受, 但却被该参数约束而拒绝服务, 这显然也不合适.
而且, 从内部实现上来说, max-select-point 约束实际起效往往是滞后的. 另外, InfluxDB 的一些设计问题会导致 "查放大", 也就是虽然你只查询了较少的数据, 但内部却遍历并临时存储了较多的数据, 最终使用了更多的内存.
1.2 阿里云 InfluxDB 的全局 Cache 管理机制
一个实际 InfluxDB 的实时 Cache 情况可能如下图所示:
如图, 系统中的实际 Cache 可能会有很多, 且实时的大小各不相同, 所以我们增加了对全局所有 Cache 的统计与管理. 简要的架构如下图所示:
开源 InfluxDB 中原有的针对每个 Cache 的独立 snapshot 门限监测和执行逻辑保持不变. 冷 Cache 无论 size 大小都执行 snapshot 的逻辑也保持不变(前面没有提到, InfluxDB 还有一个参数 cache-snapshot-write-cold-duration, 控制 Cache 变冷后, 也就是无数据写入后多久就一定会做 snapshot, 该参数与主题关系不密切).
但我们在外层新增了一个整体管控的模块, 当整个服务的所有 Cache 的总 size 达到设定门限时, 则会对其中较大的那些 Cache 执行 snapshot 逻辑, 以便及时刷盘, 释放内存.
这样以来, 无论 Cache 多少, 每个 Cache 的实时 size 有多大, 只要总计的大小系统能够承受, 我们尽可能让 Cache 承载更多的数据, 避免写放大, 也提高最近数据的查询效率.
1.3 阿里云 InfluxDB 的 Load Shedding 机制
对查询的内存耗用问题, 我们从系统整体角度出发, 资源充足时, 不做任何限制; 资源不足时, 再进行限制和处理.
下面我们看看主要的处理逻辑.
1.3.1 Load Shedding 机制的主流程
阿里云 InfluxDB 引入了一套 Load Shedding 机制, 该机制在内存充足时总是满足用户客户端发来的请求, 在内存不足时保护性地终止部分响应. 这样既保证了硬件资源的利用率, 又保护了服务的持续可用性. 算法的整体流程如下图所示:
如图, 我们会额外增加一个协程, 周期性地获取进程的 HeapAlloc 信息. 当 HeapAlloc 不超过危险阈值时, 不会 kill 任何用户查询; 当超过危险阈值时, 则会酌情 kill 较晚开始执行的资源消耗较大的查询. 但不管 kill 掉多少查询, 始终会确保最早开始执行的查询可以继续执行下去, 以保证系统仍然对查询请求有一定的处理能力.
1.3.2 过负载时的新查询拒绝
另外, 超过限制后, 还会设置 OverLoad 标识, 它在收到新写入请求和新查询请求的流程中也都会被用到. 查询请求预先检查 OverLoad 标识的流程如下图所示:
从上图可以看到, 如果系统已经设置了 OverLoad 标识, 则新的查询请求也会被拒绝. 直到被 kill 的查询及其它执行的查询完成后释放了足够的内存, 让 HeapAlloc 重新下降到阈值以下后, OverLoad 标识才会被 unset, 系统才会重新接受新的查询请求.
1.3.3 未过负载时对写请求的服务保证
开源 InfluxDB 本身的流程中, 是没有上图中是否 OverLoad 的判断的. 所以只要写入请求对应 shard 的 cache 大小超过了限制参数, 写入请求就一定会失败. 但我们从上图可以看到, 如果服务整体没有 OverLoad, 即使写负载比较大, 导致短时间写入请求对应 shard 的 cache 超出了设定限制, 仍然会接受 write 请求, 因为此时系统整体上其实是安全的.
这里还要提一下 InfluxDB 的写 cache 有两个关联的参数 cache-snapshot-memory-size 和 cache-max-memory-size, 前者是启动 shard 的写 cache 启动 snapshot 的门限, 后者是开始拒绝写入的门限. 如果我们选定了一个适当的 cache-max-memory-size, 则 cache-snapshot-memory-size 就必须显著小于 cache-max-memory-size, 否则若二者接近, 很容易发生系统还没反应过来, 就已经达到 cache-max-memory-size, 导致写入失败. 而当 cache-snapshot-memory-size 显著小于 cache-max-memory-size 时, cache-max-memory-size 参数的价值就降低了(shard 的 cache 大小几乎没有机会接近该值就早已 snapshot 了). 这种相互关系产生了上述微妙的矛盾.
而有了上面流程图额外的条件判断, 就可以避免这种情况, 让二者较为接近也不会造成写入失败.
1.4 阿里云 InfluxDB 内存优化总结
阿里云 InfluxDB 基于开源 InfluxDB 做了很多提升与强化. 本文介绍的全局 Cache 管控和 Load Shedding 机制就是其中重要的两个方面. 它们一定程度上化解了开源 InfluxDB 的配置参数缺乏整体性和自适应性的缺陷, 既保护了实例, 又充分利用了硬件资源.
未来阿里云 InfluxDB 还将在内存管理方面继续探索和优化, 给用户提供最佳的服务和体验.
2. 阿里云 InfluxDB 智能数据采集
开源的数据采集工具, 如 Telegraf,Logstash 和 TCollector 等, 可以支持多种数据类型的采集, 但是用户需要自行寻找恰当的安装包, 然后编写复杂配置文件后才可以收集数据. 并且用户难以直观地监测数据采集的运行状况, 更无法对采集端进行统一的管控. 特别是有众多采集源时, 维护工作将非常繁杂且容易出错.
为了简化时序数据采集的繁琐操作, 阿里云 InfluxDB 新推出智能数据采集功能, 实现数据从采集到存储的自动化管理, 用户只需简单配置即可使用, 无需编写任何代码.
下面我们将详解阿里云 InfluxDB 的智能数据采集方案.
2.1 方案架构详解
上图展示了数据采集功能的框架, 用户可分别创建多个采集配置和采集源, 各个采集源之间相互独立, 同样地, 各个采集源之间也相互独立. 一个采集配置可被多个采集源使用, 但是一个采集源只能使用一个采集配置; 当采集配置中的参数变化时, 所有使用该采集配置的采集源的配置也会发生变化.
用户通过控制台对采集配置和采集源所进行的操作, 都会同步到阿里云 InfluxDB; 数据采集工具直接与阿里云 InfluxDB 进行通信, 获取采集源的最新信息, 自动实现数据的采集和发送.
下面, 我们将详细介绍以上框架中的各个组件.
2.1.1 阿里云 InfluxDB 控制台
阿里云 InfluxDB 控制台是用户与数据采集服务进行交互的接口, 用户对采集配置和采集源进行管理需要通过控制台. 用户在控制台进行的操作, 实际上是向阿里云 InfluxDB 发送相应的请求.
2.1.1.1 采集配置管理
阿里云 InfluxDB 提供创建, 修改, 删除和查看采集配置的 API. 在阿里云 InfluxDB 中, 有专门的模块管理采集配置, 所有采集配置的信息都会存储在阿里云 InfluxDB 中, 并持久化到磁盘, 防止信息丢失. 图中绿色箭头表示用户通过控制台对采集配置进行的操作.
1. 创建采集配置. 一个采集配置包含该配置的名称, 采集数据类型, 有关采集数据的配置(如果有的话), 数据写入的数据库和保留策略, 用户账号信息.
2. 修改采集配置. 除了采集配置的名称无法修改外, 其它的配置信息都可修改. 如果有采集源正在使用该采集配置, 那么采集配置修改后, 自动在采集源中生效.
3. 删除采集配置. 在删除一个采集配置之前, 需要先确认没有正在运行的采集源使用该采集配置, 否则删除不成功.
4. 查看采集配置. 创建采集配置后, 用户可查看该配置的具体信息.
目前, 阿里云 InfluxDB 智能采集端已经支持以下采集类型:
1. 系统监控
- MySQL
- Redis
- MongoDB
如果用户的数据采集类型不在这 4 种常见选项当中, 也可以通过直接配置 Telegraf 来完成数据上报.
2.1.1.2 采集源管理
阿里云 InfluxDB 提供创建, 修改, 删除和查看采集源的 API. 同样地, 在阿里云 InfluxDB 中, 有专门的模块管理采集源, 所有采集源的信息都会存储在阿里云 InfluxDB 中, 并持久化到磁盘, 防止信息丢失. 图中红色箭头表示用户通过控制台对采集源进行的操作.
1. 创建采集源. 一个采集源包含以下信息: uuid(每个采集源有一个唯一的标志符, 用于标识不同的采集源), 主机 IP, 主机名称, 网络类型, 采集配置, 采集状态, 最新连接上报成功时间和最新采集上报成功时间.
2. 修改采集源. 用户可以修改采集源正在使用的采集配置和采集源的运行状态, 更新后的信息会保存在阿里云 InfluxDB 中.
3. 删除采集源. 在删除一个采集配置之前, 需要先确认没有正在运行的采集源使用该采集配置, 否则删除不成功. 删除采集源意味着该采集源无法再次采集数据.
4. 查看采集源. 用户可以在控制台查看所有将数据写入阿里云 InfluxDB 的采集源, 实时监控各个采集源的状态.
2.1.2 采集工具
用户在数据源所在机器上安装数据采集工具后, 采集工具即可开始采集数据并上传到阿里云 InfluxDB. 采集工具会周期性地从阿里云 InfluxDB 获得该采集源的配置信息, 判断是否需要开启或关闭采集数据, 同时, 也会判断采集源正在使用的采集配置是否有更新, 若有, 则中断当前数据的采集, 并且以新的配置信息开始采集数据.
当采集工具向阿里云 InfluxDB 发送获得采集源配置的请求时, 除了获得最新的配置信息, 也会更新采集源配置中的最新连接上报成功时间, 根据该时间, 用户可以知道采集工具的状态, 是否成功运行并与阿里云 InfluxDB 建立连接.
目前, 阿里云 InfluxDB 支持采集的数据类型有四种: MySQL,MongoDB,Redis 和系统监控. 根据采集源的配置, 采集工具自动采集某一种类型的数据并上传到阿里云 InfluxDB 中. 对于发送的写入数据请求, 阿里云 InfluxDB 会更新对应的采集源的最新采集上报成功时间, 根据该时间, 用户可以知道最近一次采集数据发送到阿里云 InfluxDB 的时间, 实时监控数据是否成功到达阿里云 InfluxDB.
图中的蓝色箭头部分展示了采集工具即会向阿里云 InfluxDB 获得采集源配置, 也会更新其信息. 橙色箭头表示采集工具向阿里云 InfluxDB 发送写入数据的请求.
2.1.3 阿里云 InfluxDB
阿里云 InfluxDB 提供采集配置和采集源模块, 用于处理来自控制台和数据采集工具的请求. 绿色箭头和红色箭头表示来自控制台的请求, 可对采集配置和采集源进行操作. 需要注意的是, 在采集源的配置中, 还会包含正在使用的采集配置的信息. 橙色箭头表示采集工具向阿里云 InfluxDB 发送写入数据的请求, 根据采集配置中数据写入的数据库和保留策略, 采集工具将采集数据发送到指定的数据库和保留策略, 同时, 也会更新采集源配置中的最新连接上报成功时间和最新采集上报成功时间.
2.2 阿里云 InfluxDB 智能数据采集总结
阿里云 InfluxDB 智能数据采集方案, 通过控制台, 采集工具和阿里云 InfluxDB 之间的通信, 实现数据采集的自动化管理. 用户无需自行运维或者编写代码, 只需通过控制台的图形界面操作, 即可对多种监控数据进行采集管理, 实现数据从采集到存储的无缝链接. 并且, 控制台的界面简洁明了, 易于操作, 用户可以直观地监测多个采集源的数据采集状态.
3. 阿里云 InfluxDB 的实例监控
虽然开源 InfluxDB 本身就有获取其运行状态的 API, 但没有基于此形成告警机制, 也没有便捷的图形化界面. 并且, 对于每秒写入数据点, 磁盘占用量, 总 series 数量等实例监控数据, 并未直接提供.
阿里云 InfluxDB 进一步完善了开源 InfluxDB 的状态上报, 新增了总磁盘使用量, 总 series 数量等状态信息. 最终经过阿里云管控系统后端的数据清洗和汇总, 在控制台 "实例监控" 页面向用户提供以下状态的数据曲线:
1. 每秒写入数据点
2. 时间线数量(所有 Databases 的 series 数量总和)
3. 磁盘空间占用率
这样, 用户可以通过这些曲线直观地了解服务的当前状态和历史状态, 并且当磁盘空间占用率较高时, 系统会自动向用户告警, 提醒用户清理数据或升配.
用户还可以在阿里云的 "云监控" 产品中 (基本功能免费对用户开放使用) 基于这些状态信息设置自己的报警规则.
上述一系列的监控能力, 使得用户使用阿里云 InfluxDB 更为清晰和安全, 而如果使用开源 InfluxDB, 用户就需要自己费心费力去搭建这些状态监控和告警.
4. 总结与展望
基于开源 InfluxDB, 阿里云 InfluxDB 在保留全部功能, 确保 100% 兼容性的基础上, 在服务稳定性, 数据采集便利性和服务监控告警便利性上做了进一步的优化与完善, 成为用户在云上使用 InfluxDB 的最佳选择.
未来, 阿里云 InfluxDB 还会在高可用和集群化上进一步发力, 提供更高端的服务能力. 也会继续增加智能数据采集的覆盖范围, 支持越来越多的数据类型. 除了这些, 阿里云 InfluxDB 也期待听到大家的心声, 在用户需要的方向上去做更多的努力与提升.
来源: https://yq.aliyun.com/articles/717901