fsck

与文件系统检查类似,fsck 命令将扫描并有选择地尝试修复 OpenTSDB 数据表中数据点的问题。 fsck 命令仅在tsdb存储表上运行,扫描整个数据表或与给定查询匹配的任何数据行。通过压缩未由 TSD 压缩的行和 OpenTSDB 早期版本的可变长度编码数据点,Fsck 可用于修复错误并回收空间。

默认情况下,运行 fsck 将仅报告查询发现的错误。除非您提供--fix--fix-all标志,否则不会对基础数据进行任何更改。通常,您应该首先运行不带修复标记的 fsck,然后验证日志文件中发现的问题。如果您对维修有信心,请添加一个维修标志。并非所有错误都可以自动修复。

Warning

使用--fix--fix-all运行 fsck 可能会删除数据点,列或整个行,除非您从备份中还原,否则无法恢复已删除的数据。 (或执行一些 HBase 欺骗以在进行重大压缩之前还原数据)

Note

此页面记录了 OpenTSDB 2.1 fsckUtil。对于以前的版本,只有--fix标志可用,并且仅查询中的数据可能是 fsckd。

Parameters

fsck [flags] [START-DATE [END-DATE] query [queries...]]
NameData TypeDescriptionDefaultExample
--fixFlag尝试修复错误的可选标志。就其本身而言,修复程序只能修复符号扩展错误,带有 4 字节限定符的 8 字节浮点数和 VLE 独立数据点。与其他标志一起使用可修复更多问题。Not set--fix
--fix-allFlag设置所有修复标志以尝试一次修复所有问题。 请谨慎使用Not set--fix
--compactFlag在修复过程中压缩未压缩的行。Not Set--compact
--delete-bad-compactsFlag删除看似已压缩但解析失败的列。如果一列正确解析,但该值的最后字节未设置为 0 或 1,则该列将被保留。Not Set--delete-bad-compacts
--delete-bad-rowsFlag删除与度量标准 UID 的 OpenTSDB 行键格式不匹配的任何行,后跟时间戳和标记 UID。Not Set--delete-bad-rows
--delete-bad-valuesFlag删除所有无法修复或不符合 OpenTSDB 规范的独立数据点。Not Set--delete-bad-values
--delete-orphansFlag删除无法将一个或多个 UID 解析为名称的行。Not Set--delete-orphans
--delete-unknown_columnsFlag删除所有看起来不是压缩列,独立数据点或已知或将来的 OpenTSDB 对象的列。Not Set--delete-unknown-columns
--resolve-duplicatesFlag通过删除除最新或最早的数据点之外的所有数据点来启用重复的数据点解析。另请参见--last-write-winsNot Set--resolve-duplicates
--last-write-winsFlag置位时,在解决重复项时删除除最近写入的数据点以外的所有数据点。如果配置值tsd.storage.fix_duplicates设置为 true,则无论该值如何,都将保留最新的数据点。Not Set--last-write-wins
--full-scanFlag扫描整个数据表。 注意: 这可能需要很长时间才能完成。Not Set--full-scan
--threadsInteger执行完全扫描时要使用的线程数。默认值为 CPU 内核数的两倍。2 x 个 CPU 核心--threads=16
START-DATE字符串或整数查询的开始时间。这可以是绝对时间或相对时间。有关详情,请参见日期和时间 1h-ago
END-DATE字符串或整数查询的可选结束时间。如果未提供,则使用当前时间。这可以是绝对时间或相对时间。有关详情,请参见日期和时间Current timestamp2014/01/01-00:00:00
queryString一个或多个命令行查询 sum tsd.hbase.rpcs type = put

Examples

Query

fsck --fix 1h-ago now sum tsd.hbase.rpcs type=put sum tsd.hbase.rpcs type=scan

Full Table

fsck --full-scan --threads=8 --fix --resolve-duplicates --compact

全表与查询

使用--full-scan标志,将扫描整个 OpenTSDB tsdb数据表。默认情况下,该 Util 将启动2 x CPU core线程以获得最佳性能。数据以度量 UID 作为每个行键的开头存储,因此 Util 将确定最大度量 UID 并将主数据表平均分配给线程。如果您的数据在 Metrics 之间平均分配,则每个线程应在大致相同的时间内完成。但是,某些 Metrics 通常比其他 Metrics 具有更多的数据或时间序列,因此这些线程的运行时间可能比其他 Metrics 更长。 OpenTSDB 的 Future 更新将能够以更有效的方式减少工作量。

或者,您可以指定一个 CLI 查询以在较小的时间 Span 内进行 fsck,并查看特定的 Metrics 或时间序列。这些查询几乎总是比完整扫描快得多,并且会发现类似的问题。但是,找不到孤立的 Metrics,因为查询仅在已知的时间序列上运行。仍会找到标记名称或值已删除的孤儿。

不管使用哪种方法,fsck 只会查看 HBase 中的最新列值。如果表配置为存储多个版本,则将忽略列的旧版本。

Results

结果将以logback.xml文件中的设置记录下来。对于长 fscks,建议在后台运行并将 LogBack 配置为具有足够的空间来写入数据。完成后,将打印有关运行的统计信息。一个例子如下:

2014-07-07 13:09:15,610 INFO  [main] Fsck: Starting full table scan
2014-07-07 13:09:15,619 INFO  [main] Fsck: Max metric ID is [0]
2014-07-07 13:09:15,619 INFO  [main] Fsck: Spooling up [1] worker threads
2014-07-07 13:09:16,358 INFO  [main] Fsck: Thread [0] Finished
2014-07-07 13:09:16,358 INFO  [main] Fsck: Key Values Processed: 301
2014-07-07 13:09:16,358 INFO  [main] Fsck: Rows Processed: 1
2014-07-07 13:09:16,359 INFO  [main] Fsck: Valid Datapoints: 300
2014-07-07 13:09:16,359 INFO  [main] Fsck: Annotations: 1
2014-07-07 13:09:16,359 INFO  [main] Fsck: Invalid Row Keys Found: 0
2014-07-07 13:09:16,360 INFO  [main] Fsck: Invalid Rows Deleted: 0
2014-07-07 13:09:16,360 INFO  [main] Fsck: Duplicate Datapoints: 0
2014-07-07 13:09:16,360 INFO  [main] Fsck: Duplicate Datapoints Resolved: 0
2014-07-07 13:09:16,361 INFO  [main] Fsck: Orphaned UID Rows: 0
2014-07-07 13:09:16,361 INFO  [main] Fsck: Orphaned UID Rows Deleted: 0
2014-07-07 13:09:16,361 INFO  [main] Fsck: Possible Future Objects: 0
2014-07-07 13:09:16,362 INFO  [main] Fsck: Unknown Objects: 0
2014-07-07 13:09:16,362 INFO  [main] Fsck: Unknown Objects Deleted: 0
2014-07-07 13:09:16,362 INFO  [main] Fsck: Unparseable Datapoint Values: 0
2014-07-07 13:09:16,362 INFO  [main] Fsck: Unparseable Datapoint Values Deleted: 0
2014-07-07 13:09:16,363 INFO  [main] Fsck: Improperly Encoded Floating Point Values: 0
2014-07-07 13:09:16,363 INFO  [main] Fsck: Improperly Encoded Floating Point Values Fixed: 0
2014-07-07 13:09:16,363 INFO  [main] Fsck: Unparseable Compacted Columns: 0
2014-07-07 13:09:16,364 INFO  [main] Fsck: Unparseable Compacted Columns Deleted: 0
2014-07-07 13:09:16,364 INFO  [main] Fsck: Datapoints Qualified for VLE : 0
2014-07-07 13:09:16,364 INFO  [main] Fsck: Datapoints Compressed with VLE: 0
2014-07-07 13:09:16,365 INFO  [main] Fsck: Bytes Saved with VLE: 0
2014-07-07 13:09:16,365 INFO  [main] Fsck: Total Errors: 0
2014-07-07 13:09:16,366 INFO  [main] Fsck: Total Correctable Errors: 0
2014-07-07 13:09:16,366 INFO  [main] Fsck: Total Errors Fixed: 0
2014-07-07 13:09:16,366 INFO  [main] Fsck: Completed fsck in [1] seconds

在大多数情况下,这些统计数据应该是不言自明的。 Key Values Processed表示 HBase 中各个列的数量。 VLE指的是variable length encoding

在运行过程中,将每 5 秒报告一次进度,以便您知道该 Util 仍在工作。您应该看到类似于以下内容的行:

10:14:00.518 INFO  [Fsck.run] - Processed 47689680000 rows, 449891670779 valid datapoints
10:14:01.518 INFO  [Fsck.run] - Processed 47689730000 rows, 449892264237 valid datapoints
10:14:02.519 INFO  [Fsck.run] - Processed 47689780000 rows, 449892880333 valid datapoints

每当发现错误(并可能已修复)时,日志将立即更新。错误通常包括在输出中发现错误的列。字节数组以 Java 样式的带符号字节表示,例如[0, 1, -42]或十六进制编码的字符串,例如00000000000000040000000000000005。快捷方式引用包括(k)表示行键,(q)表示限定符,(v)表示值。

错误和修复的类型

以下是可以使用 fsck 查找或执行的错误和/或修复程序的列表。

错误的行键

如果发现不符合 OpenTSDB 数据表规范<metric_UID><base_timestamp><tagk1_UID><tagv1_UID>[...<tagkn_UID><tagvn_UID>]的行键,则认为整行无效。

2014-07-07 15:03:46,483 ERROR [Fsck #0] Fsck: Invalid row key.
      Key: 000001

Fix:

如果设置了--delete-bad-rows,则整个行将从 HBase 中删除。

Orphaned Rows

如果将行键解析为正确的 OpenTSDB 行,则该行的时间序列 ID(TSUID)的 UID 将解析为其名称。如果任何 UID 与tsdb-uid表中的名称都不匹配,则该行被视为孤立行。如果从 UID 表中手动删除了 UID 或删除未正确完成,则可能会发生这种情况。

2014-07-07 15:08:45,057 ERROR [Fsck #0] Fsck: Unable to resolve the metric from the row key.
      Key: 00000150E22700000001000001
      No such unique ID for 'metric': [0, 0, 1]

Fix:

如果设置了--delete-orphans,则整个行将从 HBase 中删除。

Compact Row

尽管这并不是严格的错误,但 fsck 可用于将行压缩为单个列。压缩行通过将多列合并为一个来节省存储空间。这减少了 HBase 的开销。如果配置为压缩列的 TSD 崩溃,则某些行可能会丢失,并保持独立数据点形式。由于压缩会消耗资源,因此可以在群集上的负载减少时使用 fsck 来压缩行。

同时指定--compact标志和--fix将压缩查询范围内具有独立数据点的任何行。在压缩过程中,来自旧 OpenTSDB 版本符合 VLE 的所有数据点都将被重新编码。

Note

如果某行由于某种原因被修复并且具有一个或多个压缩的列,则该行将被重新压缩,而不考虑--compact标志。

压缩列错误错误

当发现无法解析为单个数据点的压缩列时,会发生这些错误。如果限定符看起来正确,但是值数组中的字节数与限定符中编码的长度不匹配,则会发生这种情况。数据点乱序的压缩列不视为错误列。相反,如果存在--fix--fix-all标志,则该列将被正确排序并重写。

2014-07-07 13:29:40,251 ERROR [Fsck #0] Fsck: Corrupted value: couldn't break down into individual values (consumed 20 bytes, but was expecting to consume 24): [k '00000150E22700000001000001' q '000700270033' v '00000000000000040000000000000005000000000000000600'], cells so far: [Cell([0, 7], [0, 0, 0, 0, 0, 0, 0, 4]), Cell([0, 39], [0, 0, 0, 0, 0, 0, 0, 5]), Cell([0, 51], [0, 0, 0, 0])]

Fix:

解决此错误的唯一方法是通过指定--delete-bad-compacts标志删除该列。

压缩的最后一个字节错误

压缩值的最后一个字节用于存储元数据。如果所有数据点都以秒或毫秒编码,则通常为0。如果秒和毫秒的混合时间将被设置为1。如果该值是其他值,则可能来自 OpenTSDB 的将来版本,或者该列可能无效。

18:13:35.979 [main] ERROR net.opentsdb.tools.Fsck - The last byte of a compacted should be 0 or 1. Either this value is corrupted or it was written by a future version of OpenTSDB.
      [k '00000150E22700000001000001' q '00070027' v '00000000000000040000000000000005']

Fix:

目前无法修复。您可以将最后一个字节手动设置为 0 或 1,以防止引发错误。 --delete-bad-compacts标志不会删除这些列。

值太长或太短

如果单个数据点列的值记录在大于 8 个字节上,则可能会发生这种情况。各个数据点存储在 2 个或 4 个字节的限定符上。对于压缩列中的数据点,不会发生此错误。如果进行了压缩,则该列将引发严重的压缩列错误,因为它无法解析。

2014-07-07 14:50:44,022 ERROR [Fsck #0] Fsck: This floating point value must be encoded either on 4 or 8 bytes, but it's on 9 bytes.
      [k '00000150E22700000001000001' q 'F000020B' v '000000000000000005']

Fix:

--delete-bad-values将删除该列。

旧版本 Float

早期的 OpenTSDB 版本在浮点值存储中存在一个错误,即在写入 8 个字节的值的前 4 个字节并将所有位都设置为 1 时,该值应在最后四个字节上。因为限定符将长度编码为 4 个字节。但是,如果压缩了无效数据,则无法正确分析数据,并且将记录错误。

18:43:35.297 [main] ERROR net.opentsdb.tools.Fsck - Floating point value with 0xFF most significant bytes, probably caused by sign extension bug present in revisions [96908436..607256fc].
      [k '00000150E22700000001000001' q '002B' v 'FFFFFFFF43FA6666']

Fix:

--fix标志将通过重写不包含前四个字节的值来修复这些错误。限定词保持不变。

4 字节浮点数,且 8 字节值确定

将限定符长度设置为 4 个字节时,某些版本的 OpenTSDB 可能已在 8 个字节上编码了浮点值。前四个字节应为 0.如果压缩了该值,则压缩列将无效,因为不再可能进行解析。

2014-07-07 14:33:34,498 WARN  [Fsck #0] Fsck: Floating point value was marked as 4 bytes long but was actually 8 bytes long
      [k '00000150E22700000001000001' q '000B' v '0000000040866666']

Fix:

--fix标志将通过重写不包含前四个字节的值来修复这些错误。限定词保持不变。

具有 4 字节值错误的 4 字节浮点数

在这种情况下,将值编码在 8 个字节上,并且前四个字节设置为非零值。可能是该值是 8 字节的两倍,因为 OpenTSDB 从未实际在 8 字节上编码,因此该值很可能已损坏。如果对值进行了压缩,则压缩列将无效,因为不再可能进行解析。

2014-07-07 14:37:02,717 ERROR [Fsck #0] Fsck: Floating point value was marked as 4 bytes long but was actually 8 bytes long and the first four bytes were not zeroed
      [k '00000150E22700000001000001' q '002B' v 'FB02F40F43FA6666']

Fix:

--delete-bad-values标志将删除该列。您可以尝试手动将值解析为 Double 并查看其是否有效,否则可能是损坏的列。

Unknown Object

OpenTSDB 2.0 支持数据表中的对象,例如 Comments。如果找到与 OpenTSDB 对象,压缩列或独立数据点不匹配的列,则将其视为未知对象,并有可能被删除。

2014-07-07 14:55:03,019 ERROR [Fsck #0] Fsck: Unknown qualifier, must be 2, 3, 5 or an even number of bytes.
      [k '00000150E22700000001000001' q '00270401010101' v '0000000000000005']

Fix:

--delete-unknown-columns标志将从行中删除此列。

Future Object

对象在 3 或 5 个字节的限定符上编码,并且类型由前缀确定。如果发现 OpenTSDB 无法识别的前缀,则它将报告对象,但不会删除该对象。请注意,这实际上可能是未知列或损坏列,因为 fsck 仅查看限定符的长度和限定符的第一个字节。在这种情况下,您可以安全地手动删除此列。

2014-07-07 14:57:15,858 WARN  [Fsck #0] Fsck: Found an object possibly from a future version of OpenTSDB
      [k '00000150E22700000001000001' q '042704' v '467574757265204F626A656374']

Fix:

在 fsck 期间,将来的对象将保持不变。使用不支持该对象的 TSD 查询数据将引发异常,但是确实支持该对象的版本应 continue 进行。

Duplicate Timestamps

由于在限定符中对数据点使用了编码长度和类型,因此可以使用两个不同的限定符为同一时间戳记录一个数据点。例如,如果您为时间1发布一个整数值,然后为时间1发布一个浮点值,则将创建两个不同的列。如果已压缩一行,并且 TSD 写入一个与压缩列中的时间戳匹配的新独立列,则也会发生重复。在查询时,由于 TSD 不知道哪个值是正确的值,将引发异常。

2014-07-07 15:22:43,231 ERROR [Fsck #0] Fsck: More than one column had a value for the same timestamp: (1356998400000)
  row key: (00000150E22700000001000001)
  write time: (1388534400000)  compacted: (false)  qualifier: [0, 7]  <--- Keep oldest
  write time: (1388534400001)  compacted: (false)  qualifier: [0, 11]
  write time: (1388534400002)  compacted: (false)  qualifier: [0, 3]
  write time: (1388534400003)  compacted: (false)  qualifier: [0, 1]

Fix:

如果设置了--resolve-duplicates,则将删除除最新值或最早值以外的所有数据点。该修复程序适用于独立数据点和压缩数据点。如果设置了--last-write-wins标志,则将保存最新值。如果没有--last-write-wins标志,则会保存最早的值。

Note

如果tsd.storage.fix_duplicates配置值设置为true,则无论--last-write-wins都将保存最新值。

Note

启用压缩后,有可能(尽管不太可能)在压缩行时写入数据点。在这种情况下,压缩列的时间戳将比压缩期间写入的数据点晚*。因此,默认结果--resolve-duplicates将保留独立数据点,或者,如果最后一次写入获胜,则保留压缩值。

Variable-Length Encoding

早期的 OpenTSDB 实现始终在 8 个字节上编码整数值。在 2.0 中,整数被写入到尽可能少的字节数(1、2、4 或 8)上。在 fsck 期间,如果指定了--fix--fix-all标志,则检测到的任何 8 个字节编码的整数都将用 VLE 重写。这包括独立值和压缩值。运行结束时,将显示用 VLE 保存的字节数。