OpenTSDB写数据(一)

写在前面

写入的一些配置和设计会对OpenTSDB数据库性能产生影响,所以这不单单是简单的数据输入,第一部分主要是对数据的写入规范。

原地址http://opentsdb.net/docs/build/html/user_guide/writing/index.html


写数据(Writing Data)

您可能希望直接进入并开始将数据投入TSD,但要真正利用OpenTSDB的强大功能和灵活性,您可能需要暂停并考虑您的命名模式。完成此操作后,您可以继续通过Telnet或HTTP API推送数据,或使用具有OpenTSDB支持的现有工具,例如'tcollector'。


命名架构(Naming Schema)

许多度量管理员习惯于为其时间序列提供单个名称。例如,用于RRD风格系统的系统管理员可以命名他们的时间序列webserver01.sys.cpu.0.user。该名称告诉我们,时间序列记录了cpu 0on 用户空间的时间量webserver01。如果您想稍后在该特定Web服务器上仅检索该cpu核心的用户时间,则此方法很有用。

但是,如果Web服务器有64个内核并且您希望获得所有内核的平均时间,该怎么办?某些系统允许您指定通配符,例如webserver01.sys.cpu.*.user读取所有64个文件并汇总结果的通配符。或者,您可以记录一个名为webserver01.sys.cpu.user.all相同聚合的新时间序列,但您现在必须编写'64 + 1'个不同的时间序列。如果您有一千个Web服务器并且您想要所有服务器的平均CPU时间,该怎么办?您可以制作一个外卡查询*.sys.cpu.*.user,系统将打开所有64,000个文件,聚合结果并返回数据。或者您设置了一个预先聚合数据并将其写入的过程webservers.sys.cpu.user.all

OpenTSDB通过引入“标签”的概念来处理事情。每个时间序列仍然具有“度量”名称,但它更通用,可以由许多独特的时间序列共享。相反,唯一性来自标记键/值对的组合,允许使用非常快速的聚合进行灵活查询。

注意

每次OpenTSDB中的系列必须至少有一个标签。

以前面的度量标准示例为例webserver01.sys.cpu.0.user。在OpenTSDB中,这可能会成为。现在,如果我们想要单个核心的数据,我们可以制作一个类似的查询。如果我们想要所有内核,我们只需删除cpu标记并要求。这将为我们提供所有64个核心的汇总结果。如果我们想要所有1,000台服务器的结果,我们只需要求。底层数据模式将存储彼此相邻的所有时间序列,以便聚合各个值非常快速和高效。OpenTSDB旨在尽可能快地进行这些聚合查询,因为大多数用户都是从较高级别开始,然后深入了解详细信息。sys.cpu.userhost=webserver01, cpu=0``sum:sys.cpu.user{host=webserver01,cpu=42}``sum:sys.cpu.user{host=webserver01}``sum:sys.cpu.user``sys.cpu.user


聚合

虽然标记系统很灵活,但如果您不了解OpenTSDB的查询方面,可能会出现一些问题,因此需要一些预先考虑。就拿上面的例子中查询:sum:sys.cpu.user{host=webserver01}。我们webserver01为每个CPU核心记录了64个唯一的时间序列,一个时间序列。当我们发出该查询时,sys.cpu.user带有标记的度量标准的所有时间序列host=webserver01都被检索,平均,并作为一系列数字返回。假设结果平均值是50时间戳1356998400。现在我们正在从另一个系统迁移到OpenTSDB,并且有一个预先聚合所有64个内核的进程,以便我们可以快速获得平均值并简单地编写一个新的时间序列。如果我们运行相同的查询,我们将获得值atsys.cpu.user host=webserver01``100``1356998400。发生了什么?OpenTSDB汇总了所有64个时间序列预先聚合的时间序列,以达到100个。在存储中,我们会有这样的事情:

SYS 。cpu 。user  host = webserver01         1356998400   50 
sys 。cpu 。user  host = webserver01 ,cpu = 0   1356998400   1 
sys 。cpu 。user  host = webserver01 ,cpu = 1   1356998400   0 
sys 。cpu 。user  host = webserver01 ,cpu = 2   1356998400   2
SYS 。cpu 。user  host = webserver01 ,cpu = 3   1356998400   0 
... 
sys 。cpu 。user  host = webserver01 ,cpu = 63  1356998400   1

如果没有给出标记,OpenTSDB将自动聚合查询中度量的所有时间序列。如果定义了一个或多个标记,则聚合将“包括”与该标记匹配的所有时间序列,而不管其他标记。与查询sum:sys.cpu.user{host=webserver01},我们将包括和,和。这个例子的寓意是:小心你的命名模式sys.cpu.user host=webserver01,cpu=0``sys.cpu.userhost=webserver01,cpu=0,manufacturer=Intel``sys.cpu.user host=webserver01,foo=bar``sys.cpu.user host=webserver01,cpu=0,datacenter=lax,department=ops


时间序列基数(Time Series Cardinality)

任何命名方案的一个关键方面是考虑时间序列的基数。基数定义为集合中唯一项目的数量。在OpenTSDB的情况下,这意味着与度量相关联的项目数,即所有可能的标记名称和值组合,以及唯一度量标准名称,标记名称和标记值的数量。基数由于下面列出的两个原因很重要。

有限的唯一ID(UID)

为每个指标,标记名称和标记值分配的数量有限。默认情况下,每种类型只有超过1600万个可能的ID。例如,如果您运行非常流行的Web服务并尝试将客户端的IP地址作为标记进行跟踪,例如,您可能很快就会遇到UID分配限制,因为有超过40亿个可能的IP版本4地址。此外,这种方法会导致创建一个非常稀疏的时间序列,因为地址处的用户可能只是零星地使用您的应用程序,或者可能永远不会再使用该特定地址。web.app.hits clientip=38.26.34.10``38.26.34.10

对于标签很少更改的小型安装(例如,库存符号或一组固定的传感器),UID大小可能不是问题。为标记值分配一个与其标记名称完全取消关联的UID。如果对标记值使用数字标识符,则会为该编号分配一次UID,并且可以与许多标记名称一起使用。例如,如果我们分配一个UID与数2,我们可以存储时间序列与所述标签对cpu=2interface=2hdd=2fan=2同时仅消耗1标记值UID( 2)和4周标记名称的UID( ,,cpu 和)。interface``hdd``fan

如果您认为UID限制可能会影响您,请首先考虑您要执行的查询。如果我们查看web.app.hits上面的示例,您可能只关心服务的总点击次数,很少需要深入到特定的IP地址。在这种情况下,您可能希望将IP地址存储为注释。这样您仍然可以从低基数中受益,但如果需要,您可以使用外部脚本搜索特定IP的结果。

当存储数据为做高或改变基数源(如多克群),那么你可以通过设置改变UID宽度tsd.storage.uid.width.metrictsd.storage.uid.width.tagktsd.storage.uid.width.tagv。您只能在创建新的TSDB安装时执行此操作。

警告

您的情况可能需要增加此值。如果选择修改此值,则必须从新数据和新UID表开始。使用期望3字节UID编码的TSD写入的任何数据都将与此更改不兼容,因此请确保所有TSD都以相同的配置运行,并且在进行此更改之前存储在OpenTSDB中的所有数据都已导出到可以通过外部工具操纵的位置。

查询速度

基数也会大大影响查询速度,因此请考虑您将经常执行的查询并优化您的命名架构。OpenTSDB每小时每个时间序列创建一个新行。如果我们有一个主机有一个核心,它发出一个时间序列,每秒写入数据1天,那将导致24行数据或86,400个数据点。但是,如果我们为该主机提供8个可能的CPU内核,那么现在我们有192行和691,200个数据点。这看起来不错,因为我们可以通过发出类似的查询轻松获得所有核心的CPU使用量的总和或平均值。查询将遍历所有192行并将数据聚合到单个时间序列中。sys.cpu.userhost=webserver01,cpu=0``start=1d-ago&m=avg:sys.cpu.user{host=webserver01}

但是,如果我们有20,000个主机,每个主机有8个内核呢?现在,由于主机值的高基数,我们每天将有380万行和17.28亿个数据点。对主机上平均核心使用情况的查询webserver01速度较慢,因为它必须从380万行中挑出192行。(但是对于OpenTSDB 2.2,您可以使用显式标记功能进行指定cpu=*,模糊过滤器将启动以帮助更快地跳过这些不必要的行。)

此架构的好处是您的数据具有非常深的粒度,例如,基于每个核心存储使用量指标。您还可以轻松地创建查询以获得所有主机的所有核心的平均使用率:start=1d-ago&m=avg:sys.cpu.user。但是,针对该特定指标的查询将花费更长时间,因为需要筛选更多行。这在所有数据库中都很常见,并不仅仅是OpenTSDB的问题。

以下是处理基数的一些常用方法:

预聚合 - 在上面的示例中sys.cpu.user,您通常关心主机的平均使用情况,而不是每个核心的使用情况。虽然数据收集器可以使用上面的标记模式为每个核心发送单独的值,但收集器也可以发送一个额外的数据点,例如。现在你有一个完全独立的时间序列,每天只有24行,有20K主机,只有480K行可以筛选。对于每个主机的平均值,查询响应速度要快得多,并且您仍然可以将每个核心数据分别向下钻取。sys.cpu.user.avg host=webserver01

转换为指标 - 如果您真的只关心特定主机的指标而不需要跨主机聚合,该怎么办?在这种情况下,您可以将主机名转换为指标。我们之前的例子成了。针对此模式的查询速度非常快,因为度量标准每天只有192行。但是,要跨主机聚合,您必须执行多个查询并在OpenTSDB之外进行聚合。(未来的工作将包括此功能)。sys.cpu.user.websvr01 cpu=0


命名规范

在设计命名模式时,请记住以下建议:

  • 与您的命名保持一致以减少重复。始终对度量标准,标记名称和值使用相同的大小写。

  • 为每个指标使用相同数量和类型的标记。例如,不要存储和。my.metric host=foo``my.metric datacenter=lga

  • 考虑一下您将要执行的最常见查询,并针对这些查询优化架构

  • 想一想在查询时如何向下钻取

  • 不要使用太多标签,将其保持在相当小的数量,通常最多4或5个标签(默认情况下,OpenTSDB最多支持8个标签)。


数据规范(Data Specification)

每次系列数据点都需要以下数据:

  • 指标-的时间等系列的通用名称sys.cpu.userstock.quoteenv.probe.temp

  • timestamp - 一个Unix / POSIX纪元时间戳,以秒或毫秒为单位,定义为自1970年1月1日00:00:00 UTC时间以来经过的秒数。目前仅支持正时间戳。

  • value - 要在时间系列的给定时间戳存储的数值。这可以是整数或浮点值。

  • tag(s) - 由tagk(键)和tagv(值)组成的键/值对。每个数据点必须至少有一个标记。

时间戳

可以使用秒或毫秒分辨率将数据写入OpenTSDB。时间戳必须是整数且不超过13位数(请参见下面的[注]]。毫秒时间戳必须是1364410924250最后三位代表毫秒的格式。在提交之前,生成时间戳超过13位(即大于毫秒分辨率)的应用程序必须四舍五入到最多13位数,否则将生成错误。

具有第二分辨率的时间戳存储在2个字节上,而毫秒分辨率存储在4个字节上。因此,如果您不需要毫秒分辨率或所有数据点都在1秒边界上,我们建议您为第二个分辨率提交10位数的时间戳,以便你可以节省存储空间。避免在给定时间序列中混合使用秒和毫秒时间戳也是一个好主意。这样做会减慢查询速度,因为跨混合时间戳的迭代比仅记录一种类型或另一种类型需要更长的时间。OpenTSDB将存储您提供的任何内容。

注意

当写入telnet接口时,可以选择以表格形式写入时间戳1364410924.250,其中表示毫秒的三位数位于句点之后。/api/put通过HTTP 发送到端点的时间戳必须是整数,并且可能没有句点。分辨率为毫秒的数据目前只能通过/api/query端点或CLI命令提取。有关详细信息,请参阅query / index。

注意

提供毫秒分辨率并不一定意味着OpenTSDB在许多时间序列中支持每毫秒1个数据点的写入速度。虽然单个TSD可能能够处理每秒几千次写入,但如果您尝试每毫秒存储一个点,则只能覆盖几个时间序列。相反,OpenTSDB旨在提供更高的测量精度,通常应避免以这样的速度记录数据,特别是对于长时间运行的系列。

指标和标签

以下规则适用于指标和标记值:

  • 字符串区分大小写,即“Sys.Cpu.User”将与“sys.cpu.user”分开存储

  • 不允许有空格

  • 只有允许使用以下字符:azAZ09-_./或Unicode字母(按照规范)

度量和标签的长度不受限制,但您应该尽量保持这些值非常短。

整数值

如果put解析了命令中的值而没有小数点(.),则将其视为有符号整数。整数存储,无符号,具有可变长度编码,因此数据点可能只占用1个字节的空间或最多8个字节。这意味着数据点的最小值可以是-9,223,372,036,854,775,808,最大值可以是9,223,372,036,854,775,807(含)。整数不能有逗号或除数字和短划线以外的任何字符(对于负值)。例如,为了存储最大值,必须在表单中提供9223372036854775807

浮点值

如果put使用小数点(.)解析命令中的值,则将其视为浮点值。目前,所有浮点值都存储在4个字节,单精度,在2.4及更高版本中支持8字节双精度。浮点数以IEEE 754浮点“单一格式”存储,具有正值和负值支持。不支持Infinity和Not-a-Number值,如果提供给TSD,则会抛出错误。有关详细信息,请参阅Wikipedia和Java文档。

注意

由于OpenTSDB仅支持浮点值,因此不适合存储需要货币等精确值的测量。这就是为什么,当存储像15.2数据库这样的值时可能会返回15.199999809265137

排序

与其他解决方案不同,OpenTSDB允许以您想要的任何顺序编写给定时间序列的数据。这使得将数据写入TSD具有很大的灵活性,允许从系统中填充当前数据,然后在以后导入历史数据。


重复的数据点

在原始写入的一小时内,在OpenTSDB中写入数据点通常是幂等的。这意味着您可以42在时间戳写入值1356998400然后写入42同时又一次没有坏事发生。但是,如果在压缩数据行之后启用了压缩以减少存储消耗并写入相同的数据点,则在查询该行时可能会返回异常。如果尝试使用相同的时间戳写入两个不同的值,则在查询时可能会抛出重复的数据点异常。这是由于在1,2,4或8字节和浮点数上编码整数的差异。如果第一个值是整数而第二个值是浮点,则将始终抛出重复错误。但是,如果两个值都是浮点数,或者它们都是可以在相同长度上编码的整数,那么如果行上没有发生压缩,则原始值可能会被覆盖。

在大多数情况下,如果写入重复的数据点,通常表明数据源出现问题,例如进程意外重启或脚本中出现错误。当您查询具有一个或多个重复项的行时,OpenTSDB将通过抛出异常来“安全”失败,这样您就可以解决问题。

使用OpenTSDB 2.1,您可以通过将tsd.storage.fix_duplicates配置值设置为来启用last-write-wins true。启用此标志后,在查询时,将返回记录的最新值,而不是抛出异常。警告也将写入日志文件,注意到找到了重复项。如果还启用了压缩,则原始压缩的值将被最新值覆盖。

输入方式

目前有三种主要方法可以将数据导入OpenTSDB:Telnet API,HTTP API和从文件批量导入。或者,您可以使用提供OpenTSDB支持的工具,或者如果您非常冒险,请使用Java库。

警告

不要尝试直接写入底层存储系统,例如HBase。只是不要。它会很快变得混乱。

注意

如果tsd.mode设置为ro而不是rw,TSD将不会通过RPC调用接受数据点。Telnet样式调用将引发异常,对HTTP端点的调用将返回404错误。但是,当模式设置为只读时,仍然可以通过JAVA API进行写入。

远程登录

开始使用OpenTSDB的最简单方法是打开终端或telnet客户端,连接到TSD并发出put命令并点击“回车”。如果您正在编写程序,只需打开一个套接字,用新行打印字符串命令并发送数据包。telnet命令格式为:

put  < metric >  < timestamp >  < value >  < tagk1 = tagv1 [  tagk2 = tagv2  ... tagkN = tagvN ] >

例如:

把 sys 。cpu 。用户 1356998400  42.5  host = webserver01  cpu = 0

每个put只能发送一个数据点。不要忘记换行符,例如\n在命令结束时。

注意

不建议使用Telnet写入方法,因为它没有提供确定哪些数据点由于格式化或存储错误而无法写入的方法。而是使用HTTP API。

Http API

从版本2.0开始,数据可以通过HTTP以“Serializer”插件支持的格式发送。可以在单个HTTP POST请求中发送多个不相关的数据点以节省带宽。有关详细信息,请参阅../api_http/put。

批量导入

如果要从其他系统导入数据,或者需要回填历史数据,则可以使用importCLI实用程序。有关详细信息,请参阅cli / import。


OpenTSDB系列

总结目录https://blog.csdn.net/jyj1100/article/details/83450282

你可能感兴趣的:(OpenTSDB)