写在前面
UID和TSUID设计openTSDB的表结构,这里解释为什么选择和其中的一些用法
原地址https://opentsdb.github.io/asynchbase/docs/build/html/configuration.html
在OpenTSDB中,当您编写时间序列数据点时,它始终与度量标准和至少一个标记名称/值对相关联。在第一次遇到或通过API或CLI工具显式分配时,会为每个度量标签,标记名称和标记值分配唯一标识符(UID)。度量标准和标记名称/值对的组合创建时间序列UID或TSUID。
UID
UID对象的类型包括:
-
指标 -
sys.cpu.0
或等指标trades.per.second
-
tagk - 标签名称,如
host
或symbol
。这始终是标记键/值对中的“键”(第一个值)。 -
tagv - 标记值,如
web01
或goog
。这始终是标记键/值对中的“值”(第二个值)。
分配
UID是一个正整数,对于UID对象的名称及其类型是唯一的。在存储系统有是增加每个计数器metric
,tagk
和tagv
。创建新tsdb-uid
表时,对于每种类型,此计数器都设置为0。因此,如果您使用度量标准对sys.cpu.0
和标记对放置新数据点,host=web01
则将有3个新UID对象,每个对象的UID为1。
当数据点写入TSD时,会自动为新对象tagk
和tagv
对象分配UID 。metric
对象也会收到新的UID,但前提是自动度量设置已配置为true
。否则,将拒绝包含新指标的数据点。在每个传入数据点的缓存映射中查找UID。如果查找失败,则TSD将尝试分配新的UID。
存储
默认情况下,UID在存储器中的3个字节上进行编码,每个UID类型的最大唯一ID为16,777,215。这样做是为了减少存储空间占用的空间并减少TSD的内存占用。对于绝大多数用户来说,1600万个唯一指标,1600万个唯一标记名称和1600万个唯一标记值就足够了。但是,如果您确实需要更多特定类型,则可以修改OpenTSDB源代码并使用4个字节或更多字节重新编译。从版本2.2开始,您可以通过配置文件覆盖UID大小。
警告
如果您确实调整了字节编码数,则必须从一个tsdb
新鲜的tsdb-uid
表开始,否则结果将是意外的。如果现有设置中有数据,则必须将其导出,删除所有表,从头创建它们并重新导入数据。
显示
UID可以通过几种方式显示。最常见的方法是通过HTTP API,其中3字节的UID数据被编码为十六进制字符串。例如,UID 1
将以二进制形式写为000000000000000000000001
。作为无符号字节值的数组,您可以将其想象为。编码为十六进制字符串,该值将是每个字节用0填充字符串的位置。UID为255将导致十六进制值(或作为字节数组,。要在十进制UID到十六进制之间转换,请使用您喜欢的任何类型的十六进制转换工具,并将0放在结果值的前面,直到您有要从十六进制UID转换为十进制,只需从前面删除任何0,然后使用工具将十六进制字符串转换为十进制。[0, 0, 1]``000001``0000FF``[0, 0, 255]
在某些CLI工具和日志文件中,UID可能会显示为带符号字节的数组(感谢Java),例如上面的示例或。要将此带符号数组转换为无符号字节数组,请转换为十六进制。例如,将是二进制,其导致十进制值和十六进制值。[0, 0, 1]``[0, 0, -28]``-28``10011100``156``9C
修改
可以重命名或删除UID。重命名可以通过CLI完成,通常是安全的,但会影响包含重命名ID的每个时间序列。例如,如果我们有一个系列而另一个并且将标记值重命名为,则两个系列现在都将反映新的主机名,并且必须更新引用旧名称的所有查询。如果数据点具有前一个字符串,将分配新的UID。sys.cpu.user host=web01``apache.requestshost=web01``web01``web01.mysite.org
从版本2.2开始,删除UID可能很棘手。删除指标是安全的,因为用户可能不再查询数据,并且在调用建议API时也不会显示。但是,删除标记名称或值可能会导致查询失败。例如,如果你有度量时间序列sys.cpu.user
与主机web01
,web02
,web03
等你删除的UID web02
,将扫描在包括一系列数据的任何查询,因为数据保留在存储会抛出异常给用户。我们强烈建议您运行带有查询的FSCK来修复此类问题。sys.cpu.user host=web02
为何选择UID?
这个问题经常被问到,值得在这里列出原因。查找或分配UID会占用TSD中的宝贵周期,因此人们想知道使用度量标准或计算机的原始名称是否更快。实际上,从写作的角度来看,它会稍微快一点,但有许多缺点变得明显。
原始名称
由于OpenTSDB使用HBase作为存储层,因此可以使用字符串作为行键。在当前架构之后,您可能有一个看起来像的行键。排序与现有模式类似,但现在每小时使用70个字节的存储而不是19个。此外,必须编写行密钥并将每个查询返回到HBase,这样就增加了网络使用率同样。因此,使用UID可以帮助节省空间。sys.cpu.0.user 1292148000host=websv01.lga.mysite.com owner=operations
哈希
另一个想法是简单地将UID提升到4个字节,然后计算字符串上的哈希值,并使用正向和反向映射存储哈希,就像我们目前所做的那样。这肯定会减少分配UID所需的时间,但是存在一些问题。首先,您将遇到不同名称返回相同哈希的冲突。您可以尝试不同的算法,甚至尝试将哈希增加到8个字节,但是您总是会遇到冲突哈希的问题。其次,您现在为每个数据添加哈希计算,因为它必须确定哈希值,然后在UID表中查找哈希值以查看它是否已被映射。现在,每个数据点只执行查找。第三,您无法轻松预分割HBase区域。
TSUIDs
将数据点写入OpenTSDB时,行键的格式为<metric_UID><timestamp><tagk1_UID><tagv1_UID>[...<tagkN_UID><tagvN_UID>]
。通过简单地从行键中删除时间戳,我们有一长串UID组合在一起,形成一个唯一的时间序列ID。将字节编码为十六进制字符串将为我们提供可用于传递各种API调用的有用TSUID。因此,从我们上面的UID示例中,每个度量标签,标记名称和值的UID为1,我们的TSUID编码为十六进制字符串000001000001000001
。
虽然这种TSUID格式可能很长且很难看,特别是对于早期UID的所有0都是如此,但有几个原因可用于此:
-
如果您知道每个UID的宽度(默认情况下如上所述为3个字节),那么您可以轻松地从UID字符串中解析每个度量标准,标记名称和值的UID。
-
为每个时间序列分配唯一的数字ID会产生锁争用和/或同步问题,如果UID无法递增,则可能会丢失时间序列。
OpenTSDB系列
总结目录https://blog.youkuaiyun.com/jyj1100/article/details/83450282