时间序列数据架构设计

本页介绍了在 Bigtable 中存储时序数据的架构设计模式。本页面以设计您的架构为基础,并假设您熟悉该页面上介绍的概念和建议。

时间序列是一系列数据,包括测量值和测量值的记录时间。时间序列的示例包括:

  • 计算机内存用量图表
  • 通过新闻报道了解的一段时间内的的温度情况
  • 一段时间内的股票市场价格

一个设计良好的架构会带来出色的性能和可扩缩性,而一个设计不良的架构则可能会导致系统性能不佳。但是,没有一种架构设计能够完美地贴合所有使用场景。

本页面介绍的模式提供了一个起点。在为时间序列数据设计架构时,最重要的考虑事项是您的独特数据集和计划使用的查询。

在 Bigtable 中存储时间序列数据的基本设计模式如下:

示例数据

为说明模式之间的差异,本页面上的示例假设您存储一个应用的数据,该应用记录气象气球每分钟测量的数据。我们使用“事件”表示同时写入一个或多个单元的单个请求。位置 ID 与 Google Cloud 区域相对应。

测量结果 示例
  1. 此页面上的时间戳采用的格式为 `tYYYY-MM-DD-HHMM`,以方便阅读。在生产表中,时间戳通常表示为自世界协调时间 (UTC) 1970-01-01 00:00:00 开始计算的微秒数,例如“1616264288050807”。
压强(帕) 94587
温度(摄氏度) 9.5
湿度(百分比) 65
海拔(米) 601
相关数据 示例
气球 ID 3698
位置 asia-southeast1
时间戳1 t2021-03-05-1204

时段

在时段模式中,表中的每一行都表示一个时间“段”,例如小时、天或月。行键包含该行中记录的时间段的非时间戳标识符(例如 week49)以及其他标识数据。

您使用的时段大小(例如分钟、小时或天)取决于您计划使用的查询以及 Bigtable 数据大小限制。例如,如果包含一小时数据的行大于每行 100 MB 的建议大小上限,则表示半小时或一分钟的行可能是更好的选择。

时段模式的优点包括:

  • 提高性能。例如,与将 100 个测量值存储为 100 行相比,如果将 100 个测量值存储在一行中,Bigtable 写入和读取这些测量值的速度会更快。

  • 与行多列少的表相比,以这种方式存储的数据能够更高效地压缩。

缺点包括:

  • 时段架构设计模式比单时间戳模式更复杂,其开发需要更多时间和精力。

为新事件添加新列

在此时段模式中,为每个事件向一行写入一个新列,数据存储在列限定符中,而不是作为单元值存储。这意味着,对于每个单元,需要发送列族、列限定符和时间戳,但不发送值。

对示例气象气球数据使用此模式后,每一行包含一个气象气球的一个指标(例如 pressure)在一周内的所有测量值。每个行键都包含位置、气球 ID、行中记录的指标以及周编号。每当气球报告某个指标的数据时,便在相应的行中添加新列。列限定符包含由单元时间戳标识的分钟的压强测量值(以帕为单位)。

在此示例中,三分钟后,一行可能如下所示:

行键 94558 94122 95992
us-west2#3698#pressure#week1 "" (t2021-03-05-1200) "" (t2021-03-05-1201) "" (t2021-03-05-1202)

此模式的使用场景包括:

为新事件添加新单元

在此时间模式中,在写入新事件时向现有列添加新单元。此模式可让您利用 Bigtable 的功能,将多个带时间戳的单元存储在给定的行和列中。使用此模式时,请务必指定垃圾回收规则。

以气象气球数据为例,每一行包含一个气象气球在一周内的所有测量值。行键前缀是周的标识符,因此您可以使用单个查询读取多个气球在一周内的所有数据。其他行键片段是气球所在位置和气球的 ID。该表包含一个列族 (measurements),在该列族中每个测量值类型有一列:pressuretemperaturehumidityaltitude

每当气球发送其测量值时,应用会将新值写入保存该气球当周数据的行,并向每一列写入带时间戳的额外单元。在一周结束时,每一行中的每一列存储该周中每一分钟的测量值,一共 10080 个单元(在您的垃圾回收政策允许的情况下)。

每一行中的每一列存储该周中每一分钟的测量值。在此示例中,三分钟后,一行中的前两列可能如下所示:

行键 pressure temp
asia-south2#3698#week1 94558 (t2021-03-05-1200) 9.5 (t2021-03-05-1200)
94122 (t2021-03-05-1201) 9.4 (t2021-03-05-1201)
95992 (t2021-03-05-1202) 9.2 (t2021-03-05-1202)

此模式的使用场景包括:

  • 您希望能够测量一段时间内测量值的变化。

单时间戳行

在此模式中,为每个新事件或测量值创建一行,而不是在现有行中向列添加单元。行键后缀是时间戳值。遵循此模式的表通常行多列少,并且一行中的每列只包含一个单元。

单时间戳序列化

在此模式中,将一行的所有数据以序列化格式(例如协议缓冲区 (protobuf))存储在一列中。设计您的架构部分详细介绍了此方法。

例如,如果使用此模式来存储气象气球数据,四分钟后,表可能如下所示:

行键 measurements_blob
us-west2#3698#2021-03-05-1200 protobuf_1
us-west2#3698#2021-03-05-1201 protobuf_2
us-west2#3698#2021-03-05-1202 protobuf_3
us-west2#3698#2021-03-05-1203 protobuf_4

此模式的优点包括:

  • 存储效率

  • 速度

缺点包括:

  • 读取数据时无法仅检索某些列

  • 需要在读取数据之后进行反序列化处理

此模式的使用场景包括:

  • 您不确定将如何查询数据,或者查询可能波动。

  • 与能够在从 Bigtable 检索数据之前过滤数据相比,您更需要降低费用。

  • 如果将数据存储在多个列中,每个事件包含的测量值可能会超过每行 100 MB 的限制。

单时间戳非序列化

在此模式中,每个事件存储在其自己的行中,即使只记录一个测量值也是如此。列中的数据未序列化。

此模式的优点包括:

  • 通常比时段模式更容易实现。

  • 减少在使用架构之前优化架构花费的时间。

这种模式的缺点通常超出其带来的优势:

  • 使用这一模式时 Bigtable 性能不佳。

  • 以这种方式存储的数据,其压缩效率没有较宽列中数据的压缩效率高。

  • 即使时间戳位于行键末尾,这种模式也会导致热点。

此模式的使用场景包括:

  • 您希望始终检索所有列,但仅检索指定范围的时间戳,但出于某些原因需要不按序列化结构存储数据。

  • 您想要存储不定数量的事件。

使用气象气球示例数据时,列族和列限定符与使用时段和新单元的示例相同。但在此模式中,每个气象气球报告的每组测量值都会写入一个新行。下表显示了使用此模式写入的五行:

行键 pressure temperature humidity altitude
us-west2#3698#2021-03-05-1200 94558 9.6 61 612
us-west2#3698#2021-03-05-1201 94122 9.7 62 611
us-west2#3698#2021-03-05-1202 95992 9.5 58 602
us-west2#3698#2021-03-05-1203 96025 9.5 66 598
us-west2#3698#2021-03-05-1204 96021 9.6 63 624

其他策略

如果您需要向同一数据集发送多个不同的查询,请考虑将数据存储在多个表中,每个表的行键专为一个查询设计。

在某些情况下,您还可以组合使用多个模式。例如,在保证行不会太大的情况下,您可以将序列化数据存储在表示时段的行中。

后续步骤