随着移动互联网和物联网的广泛应用,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. 系统监控
2. MySQL
3. Redis
4. 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也期待听到大家的心声,在用户需要的方向上去做更多的努力与提升。