数据建模 - Amazon Timestream
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

要获得与亚马逊 Timestream 类似的功能 LiveAnalytics,可以考虑适用于 InfluxDB 的亚马逊 Timestream。适用于 InfluxDB 的 Amazon Timestream 提供简化的数据摄取和个位数毫秒级的查询响应时间,以实现实时分析。点击此处了解更多信息。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

数据建模

适用于 LiveAnalytics 的 Amazon Timestream 旨在收集、存储和分析来自应用程序和设备的时间序列数据,这些应用程序和设备会输出一系列带有时间戳的数据。为实现最佳性能,发送到适用于 LiveAnalytics 的 Timestream 的数据必须具有时间特征,且时间必须是数据的典型组成部分。

适用于 LiveAnalytics 的 Amazon Timestream 为您提供灵活的数据建模方式,可根据应用程序需求采用不同建模方式。本节将介绍其中几种模式,并为您提供优化成本和性能的指南。熟悉维度和度量等关键 概念 Amazon Timestream LiveAnalytics 。在本节中,您将了解以下内容,决定是创建单个表还是多个表以存储数据:

  • 哪些数据放入同一个表中,而哪些数据需拆分到多个表和数据库中。

  • 如何在适用于 LiveAnalytics 的 Timestream 多度量记录与单度量记录之间进行选择,以及使用多度量记录进行建模的优势,尤其是在应用程序同时跟踪多个测量值时。

  • 哪些属性应作为维度建模,哪些应作为度量建模。

  • 如何有效使用度量名称属性以优化查询延迟。

单表与多表

在应用程序中对数据进行建模时,另一重要方面是如何将数据建模为表和数据库。适用于 LiveAnalytics 的 Timestream 中的数据库和表是访问控制的抽象概念,用于指定 KMS 密钥、保留期等。适用于 LiveAnalytics 的 Timestream 会自动对您的数据进行分区,旨在扩展资源以匹配应用程序的摄取、存储、查询负载及要求。

适用于 LiveAnalytics 的 Timestream 中的表可扩展至存储数 PB 的数据以及每秒数十千兆字节的数据写入。查询每小时可处理数百 TB 数据。适用于 LiveAnalytics 的 Timestream 中的查询可以跨越多个表和数据库,通过联接和并集操作实现无缝访问多个表和数据库中的数据。因此,在决定如何在适用于 LiveAnalytics 的 Timestream 中组织数据时,数据规模或请求量通常并非首要考虑因素。在决定将哪些数据放入相同的表中,还是分散在不同表或不同数据库的表中时,需要考虑以下重要事项。

  • 按表的粒度支持数据留存策略(内存存储保留、磁性存储保留等)。因此,需要不同保留策略的数据应放入不同的表中。

  • 用于加密数据的 Amazon KMS 密钥在数据库级别进行配置。因此,不同的加密密钥要求意味着数据需放入不同的数据库中。

  • 适用于 LiveAnalytics 的 Timestream 支持在表和数据库的粒度上进行基于资源的访问控制。在决定将哪些数据写入相同的表,哪些数据写入不同的表时,请考虑访问控制要求。

  • 在决定将哪些数据存储于哪个表中时,需注意维度数量、度量名称和多度量属性名称的限制

  • 在决定如何组织数据时,请考虑查询工作负载和访问模式,因为查询延迟和写入查询的难易程度将取决于这些因素。

    • 如果将经常查询的数据存储在相同的表中,这通常会简化写入查询的方式,从而避免写入联接、并集或通用表表达式。这通常还可以降低查询延迟。您可以使用维度和度量名称上的谓词,以筛选与查询相关的数据。

      例如,假设存储来自六大洲设备的数据。如果查询经常跨洲访问数据以获取全球汇总视图,那么将来自这些洲的数据存储在相同的表中将使查询更易于写入。另一方面,如果将数据存储在不同的表上,仍可在同一查询中合并数据,但需要写入查询以跨表合并数据。

    • 适用于 LiveAnalytics 的 Timestream 对数据使用自适应分区和索引,因此仅按与查询相关的数据量进行查询计费。例如,如果您有一个表用于存储来自六大洲百万台设备的数据,如果查询中包含形式为 WHERE device_id = 'abcdef'WHERE continent = 'North America' 的谓词,则仅对设备或所在洲的数据进行查询而计费。

    • 在可能的情况下,如果使用度量名称将相同表中未同时输出或不经常查询的数据分开,则在查询中使用诸如 WHERE measure_name = 'cpu' 之类的谓词,不仅可获得计量优势,适用于 LiveAnalytics 的 Timestream 还可有效消除查询谓词中未使用度量名称的分区。这使您能够将具有不同度量名称的相关数据存储在相同的表中,而不会影响查询延迟或成本,同时可避免将数据分散到多个表中。度量名称本质上用于对数据进行分区,并修剪与查询无关的分区。

多度量记录与单度量记录

适用于 LiveAnalytics 的 Timestream 支持写入每条记录多个度量(多度量)或每条记录单个度量(单度量)的数据。

多度量记录

在许多使用案例中,您正在跟踪的设备或应用程序可能在同一时间戳发出多个指标或事件。在这种情况下,可将同一时间戳输出的所有指标存储在同一多度量记录中。也就是说,存储在同一多度量记录中的所有度量,在数据的同一行中显示为不同的列。

例如,假设应用程序正从同时测量的设备输出 cpu、内存和 disk_iops 等指标。以下是此类表的示例,其中同时输出的多个指标存储在同一行中。您会发现两个主机每秒输出一次指标。

主机名 measure_name Time cpu 内存 disk_iops
host-24Gju 指标 2021-12-01 19:00:00 35 54.9 38.2
host-24Gju 指标 2021-12-01 19:00:01 36 58 39
host-28Gju 指标 2021-12-01 19:00:00 15 55 92
host-28Gju 指标 2021-12-01 19:00:01 16 50 40

单度量记录

当设备在不同时间段输出不同指标,或者您使用在不同时间段(例如,当设备的读数/状态发生变化时)输出指标/事件的自定义处理逻辑时,单度量记录便适用。由于每个度量都具有唯一的时间戳,因此这些度量可以存储在适用于 LiveAnalytics 的 Timestream 独立记录中。例如,以 IoT 传感器为例,其可跟踪土壤温度和湿度,仅在检测到与之前报告条目存在变化时才会输出记录。以下示例展示使用单度量记录输出此类数据的具体情况。

device_id measure_name Time measure_value::double measure_value::bigint
sensor-sea478 温度 2021-12-01 19:22:32 35 NULL
sensor-sea478 温度 2021-12-01 18:07:51 36 NULL
sensor-sea478 湿度 2021-12-01 19:05:30 NULL 21
sensor-sea478 湿度 2021-12-01 19:00:01 NULL 23

比较单度量记录和多度量记录

适用于 LiveAnalytics 的 Timestream 为您提供灵活的数据建模方式,可根据应用程序的需求和特征,将数据建模为单度量记录或多度量记录。如果应用程序需要,单个表可同时存储单度量记录和多度量记录。通常情况下,当应用程序同时发出多个度量/事件时,建议将数据建模为多度量记录,以实现高性能的数据访问和经济高效的数据存储。

例如,如果某个 DevOps 使用案例需跟踪来自数十万台服务器的指标和事件,则每台服务器会定期输出 20 个指标和 5 个事件,且这些事件和指标会同时输出。可以使用单度量记录或多度量记录对该数据进行建模(有关生成的架构,请参阅开源数据生成器)。对于此使用案例,使用多度量记录与单度量记录对数据进行建模的结果如下:

  • 摄取计量:多度量记录使写入的摄取字节数减少约 40%

  • 摄取批处理:多度量记录会导致发送的数据批量更大,这意味着客户端需要更少的线程和更少的 CPU 以处理摄取。

  • 存储计量:多度量记录可将存储空间减少约 8 倍,从而显著节省内存存储和磁性存储的存储空间。

  • 查询延迟:与单度量记录相比,多度量记录可降低大多数查询类型的查询延迟。

  • 查询计量字节:对于扫描小于 10MB 数据的查询,单度量记录和多度量记录具有可比性。对于访问单个度量且扫描数据量大于 10MB 的查询,单度量记录通常会导致计量的字节数较低。对于涉及三个或更多度量的查询,多度量记录会导致计量的字节数降低。

  • 轻松表达多度量查询:当查询涉及多个度量时,使用多度量记录对数据进行建模可使查询更易写入且更紧凑。

上述因素将因跟踪的指标数量、数据维度数量等而有所不同。虽然上述示例为单一情况提供具体数据,但在众多应用场景和使用案例中,我们发现当应用程序在同一时刻输出多个度量时,以多度量记录的形式存储数据更为高效。此外,多度量记录可灵活处理数据类型,并支持存储多个其他值作为上下文信息(例如,存储请求 ID 和其他时间戳,相关内容将在后文详述)。

请注意,多度量记录也可对稀疏度量进行建模,例如上述的单度量记录示例:可以使用 measure_name 存储度量的名称,也可以使用通用的多度量属性名称,例如使用 value_double 存储 DOUBLE 度量、使用 value_bigint 存储 BIGINT 度量、使用 value_timestamp 存储其他 TIMESTAMP 值等。

维度和度量

适用于 LiveAnalytics 的 Timestream 中的表可用于存储维度(标识正在存储的设备/数据的属性)和度量(正在跟踪的指标/值);有关更多详细信息,请参阅 概念 Amazon Timestream LiveAnalytics 。当在适用于 LiveAnalytics 的 Timestream 上对应用程序进行建模时,如何将数据映射到维度和度量会影响数据摄取和查询延迟。以下是有关如何将数据建模为维度和度量的指南,可应用于您的使用案例。

选择维度

用于标识发送时间序列数据源的数据,天然适合用作维度,即不会随时间推移而变化的属性。例如,如果您的服务器输出指标,则用于标识服务器的属性(例如主机名、区域、机架和可用区)可作为维度候选项。同样,对于具有多个报告时间序列数据的传感器的 IoT 设备,设备 ID 和传感器 ID 等属性可作为维度的候选项。

如果以多度量记录形式写入数据,当对该表执行 DESCRIBE 或运行 SELECT 语句时,维度和多度量属性将以列的形式呈现于表中。因此,在写入查询时,可在同一查询中自由使用维度和度量。然而,在构建写入记录以摄取数据时,选择哪些属性作为维度属性,哪些属性作为度量值属性时,请注意以下事项:

  • 维度名称、维度值、度量名称和时间戳可唯一标识时间序列数据。适用于 LiveAnalytics 的 Timestream 使用此唯一标识符自动删除重复数据。也就是说,如果适用于 LiveAnalytics 的 Timestream 接收到两个具有相同维度名称、维度值、度量名称和时间戳值的数据点,且这些值具有相同的版本号,则适用于 LiveAnalytics 的 Timestream 将删除重复数据。如果新写入请求的版本低于适用于 LiveAnalytics 的 Timestream 中已有的数据版本,则写入请求将被拒绝。如果新写入请求具有更高的版本,则新值会覆盖旧值。因此,如何选择维度值将影响此重复数据删除行为。

  • 无法更新维度名称和维度值,但可更新度量值。因此,最好将任何可能需要更新的数据建模为度量值。例如,如果工厂车间里有台颜色可变的机器,可将颜色建模为度量值,除非还需要将颜色用作去重所需的标识属性。也就是说,度量值可用于存储仅会随时间推移而缓慢变化的属性。

请注意,适用于 LiveAnalytics 的 Timestream 中的表不会限制维度名称和维度值的唯一组合数量。例如,可将数十亿个这样的唯一值组合存储在表中。然而,正如以下示例所示,谨慎选择维度和度量可以显著优化请求延迟,尤其对于查询而言。

维度中的唯一 ID

如果应用场景要求提供存储每个数据点的唯一标识符(例如,请求 ID、交易 ID 或关联 ID),则将 ID 属性建模为度量值将显著降低查询延迟。使用多度量记录对数据进行建模时,ID 会出现在与其他维度和时间序列数据相同的行中,因此查询可以继续有效地使用这些数据。例如,在某个 DevOps 使用案例中,当服务器输出的每个数据点都具有唯一的请求 ID 属性时,如果将请求 ID 建模为度量值,相较于将其建模为维度,不同查询类型的查询延迟可降低高达 4 倍。

对于并非每个数据点都完全唯一但具有数十万或数百万个唯一值的属性,可使用类似的类比。可将这些属性建模为维度值或度量值。如前所述,如果需在写入路径中对这些值进行去重处理,或在查询中频繁将其用作谓词(例如,在 WHERE 子句中对 device_id = 'abcde' 等属性的值设置等值谓词,其中应用程序需要追踪数百万台设备),则应将其建模为维度。

数据类型丰富,具备多度量记录

多度量记录提供灵活选项,以对数据进行有效建模。存储在多度量记录中的数据在表中以列的形式呈现,类似于维度,因此查询维度和度量值同样便捷。上述讨论过的示例中已出现其中一些模式。以下是其他模式,可有效使用多度量记录以满足应用程序的使用案例需求。

多度量记录支持以下数据类型的属性:DOUBLEBIGINTVARCHARBOOLEANTIMESTAMP。因此,多度量记录自然适合不同类型的属性:

  • 位置信息:例如,如果需要跟踪某个位置(以纬度和经度表示),与将其存储为 VARCHAR 维度相比,将其建模为多度量属性可降低查询延迟,尤其是当经纬度存在谓词时。

  • 记录中的多个时间戳:如果应用场景要求跟踪时间序列记录的多个时间戳,可将其建模为多度量记录中的其他属性。此模式可用于存储带有未来时间戳或过去时间戳的数据。请注意,每条记录仍将使用时间列中的时间戳,以便对记录进行分区、索引和唯一标识。

特别是,如果查询中包含带谓词的数值数据或时间戳,将这些属性建模为多度量属性而非维度将降低查询延迟。这是因为当使用多度量记录支持的丰富数据类型对此类数据进行建模时,如果将此类数据建模为维度,可以直接使用原生数据类型表示谓词,无需将值从 VARCHAR 转换为其他数据类型。

将度量名称与多度量记录结合使用

适用于 LiveAnalytics 的 Timestream 中的表支持名为度量名称的特殊属性(或列)。可为写入适用于 LiveAnalytics 的 Timestream 的每条记录指定此属性的值。对于单度量记录,自然应使用指标的名称(例如,使用 CPU 或内存表示服务器指标,或使用温度或压力表示传感器指标)。当使用多度量记录时,会对多度量记录中的属性进行命名,这些名称将成为表中的列名。因此,CPU、内存、温度和压力均可成为多度量属性名称。自然而然的问题是:如何有效使用度量名称。

适用于 LiveAnalytics 的 Timestream 使用度量名称属性中的值对数据进行分区和索引。因此,如果表有多个不同的度量名称,且查询使用这些值作为查询谓词,则适用于 LiveAnalytics 的 Timestream 可使用其自定义分区和索引,清理与查询无关的数据。例如,如果表包含 cpumemory 度量名称,且查询包含谓词 WHERE measure_name = 'cpu',则适用于 LiveAnalytics 的 Timestream 可有效清理与查询无关的度量名称的数据,例如本示例中具有度量名称内存的行。即使在多度量记录中使用度量名称,此修剪操作仍适用。可有效使用度量名称属性作为表的分区属性。度量名称以及维度名称和值及时间可用于对适用于 LiveAnalytics 的 Timestream 表中的数据进行分区。请注意,在适用于 LiveAnalytics 的 Timestream 表中,允许的唯一度量名称数量存在限制。另请注意,度量名称也会与度量值数据类型相关联。例如,单个度量名称仅可与一种类型的度量值相关联。该类型可以是 DOUBLEBIGINTBOOLEANVARCHARMULTI 其中之一。使用度量名称存储的多度量记录,其数据类型为 MULTI。由于单个多度量记录可以存储多个不同数据类型(DOUBLEBIGINTVARCHARBOOLEANTIMESTAMP)的指标,因此可在多度量记录中关联不同类型的数据。

以下各节将通过若干不同示例说明如何有效利用度量名称属性,将同一表中的不同类型数据进行分组。

IoT 传感器报告质量和价值

假设有一个应用程序,用于监控来自 IoT 传感器的数据。每个传感器跟踪不同的度量值,例如温度和压力。除实际值以外,传感器还报告测量值的质量,该指标反映读数的准确性,并标注测量值单位。由于质量、单位和值会同时输出,因此可将其建模为多度量记录,如以下示例数据所示,其中 device_id 为维度,qualityvalueunit 为多度量属性:

device_id measure_name Time Quality 单位
sensor-sea478 温度 2021-12-01 19:22:32 92 35 c
sensor-sea478 温度 2021-12-01 18:07:51 93 34 c
sensor-sea478 pressure 2021-12-01 19:05:30 98 31 psi
sensor-sea478 pressure 2021-12-01 19:00:01 24 132 psi

此方法使您能够利用多度量记录的优势,同时结合度量名称的值对数据进行分区和修剪。如果查询引用单个度量(例如温度),则可在查询中包含 measure_name 谓词。以下是此类查询的示例,该查询还会投影质量高于 90 的测量值单位。

SELECT device_id, time, value AS temperature, unit FROM db.table WHERE time > ago(1h) AND measure_name = 'temperature' AND quality > 90

在查询上使用 measure_name 谓词可让适用于 LiveAnalytics 的 Timestream 有效修剪与查询无关的分区和数据,从而降低查询延迟。

如果所有指标都在相同的时间戳输出,且/或在同一查询中同时查询多个指标,则所有指标也可以存储在同一多度量记录中。例如,您可以使用 temperature_quality、temperature_value、temperature_unit、pressure_quality、pressure_value 和 pressure_unit 等属性构造多度量记录。就决定如何对数据进行建模,先前讨论的关于使用单度量记录与多度量记录对数据进行建模的诸多要点同样适用。根据查询访问模式以及数据生成方式,选择能够优化成本、数据摄取和查询延迟以及便于写入查询的模型。

同一个表中不同类型的指标

另一个可将多度量记录与度量名称值结合使用的使用案例,是对来自同一设备但独立输出的不同类型数据进行建模。以 DevOps 监控使用案例为例,服务器会输出两种类型的数据:定期输出的指标和不规则的事件。此方法的一个示例是在数据生成器建模 DevOps 使用案例中讨论的架构。在此情况下,您可以使用不同的度量名称,将同一服务器输出的不同类型数据存储在同一个表中。例如,所有同时输出的指标都使用度量名称指标进行存储。所有在与指标不同时间点输出的事件都使用度量名称事件进行存储。表的度量架构(例如,SHOW MEASURES 查询的输出)为:

measure_name data_type 维度
events [{"data_type":"varchar","dimension_name":"availability_zone"},{"data_type":"varchar","dimension_name":"microservice_name"},{"data_type":"varchar","dimension_name":"instance_name"},{"data_type":"varchar","dimension_name":"process_name"},{"data_type":"varchar","dimension_name":"jdk_version"},{"data_type":"varchar","dimension_name":"cell"},{"data_type":"varchar","dimension_name":"region"},{"data_type":"varchar","dimension_name":"silo"}]
指标 [{"data_type":"varchar","dimension_name":"availability_zone"},{"data_type":"varchar","dimension_name":"microservice_name"},{"data_type":"varchar","dimension_name":"instance_name"},{"data_type":"varchar","dimension_name":"os_version"},{"data_type":"varchar","dimension_name":"cell"},{"data_type":"varchar","dimension_name":"region"},{"data_type":"varchar","dimension_name":"silo"},{"data_type":"varchar","dimension_name":"instance_type"}]

在此情况下,您可以发现事件和指标也有不同的维度集,其中事件具有维度 jdk_versionprocess_name,而指标具有维度 instance_typeos_version

使用不同的度量名称,可让您写入带有谓词(例如 WHERE measure_name = 'metrics')的查询,以便仅获取指标。此外,将同一实例输出的所有数据存储在同一个表中,意味着您可以写入带有 instance_name 谓词的更简单查询语句,以获取该实例的所有数据。例如,形式为 WHERE instance_name = 'instance-1234' 且不带 measure_name 谓词的谓词将返回特定服务器实例的所有数据。

对多度量记录进行分区的建议

重要

此部分已弃用!

这些建议已经过时。现在,使用客户定义的分区键可以更有效地控制分区。

我们注意到,在时间序列生态系统中,越来越多的工作负载需要同时满足两大需求:既要处理海量数据的采集与存储,又要在通过高基数维度值集访问数据时实现低延迟的查询响应。

由于这些特性,本节中的建议尤其适用于具有以下特征的客户工作负载:

  • 已采用或计划采用多度量记录。

  • 预计将有大量数据进入系统,且会长期存储其中。

  • 客户工作负载的主要访问(查询)模式要求低延迟响应时间。

  • 请注意,最重要的查询模式都涉及谓词中某种形式的筛选条件。此筛选条件基于高基数维度构建。例如,考虑按 UserId、DeviceId、ServerID、host-name 等进行的事件或聚合。

在这些情况下,所有多度量值的单一名称并无助益,因为我们的引擎使用多度量名称对数据进行分区,而使用单个值会限制您获得的分区优势。这些记录的分区主要基于两大维度。假设时间在 x 轴上,维度名称的哈希值和 measure_name 在 y 轴上。在这些情况下,measure_name 的作用近似于分区键。

我们的建议如下:

  • 针对类似前述的使用案例,对数据进行建模时,请使用 measure_name,这是主查询访问模式的直接衍生。例如:

    • 使用案例需要从最终用户的角度跟踪应用程序性能和 QoE。这也可能是跟踪单个服务器或 IoT 设备的测量值。

    • 如果按 UserId 进行查询和筛选,则需在摄取时找到将 measure_name 与 UserId 关联的最佳方式。

    • 由于多度量表仅能容纳 8192 个不同的度量名称,因此无论采用何种公式,生成的不同值数量都不应超过 8192 个。

  • 对于字符串值,我们成功应用的一种方法是对其进行哈希算法处理。然后使用哈希结果的绝对值与 8192 进行取模运算。

    measure_name = getMeasureName(UserId)
    int getMeasureName(value) {
        hash_value =  abs(hash(value))
        return hash_value % 8192
    }
  • 我们还添加了 abs(),以删除符号,从而消除值介于 -8192 到 8192 之间的可能性。这应在取模运算之前执行。

  • 采用此方法后,您的查询运行时间将仅需未分区数据模型运行所需时间的一小部分。

  • 查询数据时,请确保在谓词中包含筛选条件,该条件使用 measure_name 的新派生值。例如:

    • SELECT * FROM your_database.your_table WHERE host_name = 'Host-1235' time BETWEEN '2022-09-01' AND '2022-09-18' AND measure_name = (SELECT cast(abs(from_big_endian_64(xxhash64(CAST('HOST-1235' AS varbinary))))%8192 AS varchar))
    • 这将大幅减少扫描的分区总数,从而确保数据可随时间推移加快转化为查询。

请注意,如果想从此分区架构中受益,则需在客户端计算哈希值,并将其作为查询引擎的静态值传递给适用于 LiveAnalytics 的 Timestream。上述示例提供一种验证引擎是否可在需要时解析所生成哈希值的方法。

时间 host_name location server_type cpu_usage available_memory cpu_temp

2022-09-07 21:48:44 .000000000

host-1235

us-east1

5.8xl

55

16.2

78

R2022-09-07 21:48:44 .000000000

host-3587

us-west1

5.8xl

62

18.1

81

2022-09-07 21:48:45.000000000

host-258743

eu-central

5.8xl

88

9.4

91

2022-09-07 21:48:45 .000000000

host-35654

us-east2

5.8xl

29

24

54

R2022-09-07 21:48:45 .000000000

host-254

us-west1

5.8xl

44

32

48

根据我们的建议生成关联的 measure_name 时,有两种路径可选,具体取决于您的摄取模式。

  1. 对于历史数据的批量摄取:如果您要使用自己的代码进行批处理,可将转换添加至写入代码中。

    基于前面的示例进行构建。

    List<String> hosts = new ArrayList<>(); hosts.add("host-1235"); hosts.add("host-3587"); hosts.add("host-258743"); hosts.add("host-35654"); hosts.add("host-254"); for (String h: hosts){ ByteBuffer buf2 = ByteBuffer.wrap(h.getBytes()); partition = abs(hasher.hash(buf2, 0L)) % 8192; System.out.println(h + " - " + partition); }

    Output

    host-1235 - 6445
    host-3587 - 6399
    host-258743 - 640
    host-35654 - 2093
    host-254 - 7051
    

    生成的数据集

    时间 host_name location measure_name server_type cpu_usage available_memory cpu_temp

    2022-09-07 21:48:44 .000000000

    host-1235

    us-east1

    6445

    5.8xl

    55

    16.2

    78

    R2022-09-07 21:48:44 .000000000

    host-3587

    us-west1

    6399

    5.8xl

    62

    18.1

    81

    2022-09-07 21:48:45.000000000

    host-258743

    eu-central

    640

    5.8xl

    88

    9.4

    91

    2022-09-07 21:48:45 .000000000

    host-35654

    us-east2

    2093

    5.8xl

    29

    24

    54

    R2022-09-07 21:48:45 .000000000

    host-254

    us-west1

    7051

    5.8xl

    44

    32

    48

  2. 对于实时摄取:您需要在数据传入时实时生成 measure_name

在这两种情况下,我们建议您在两端(摄取和查询)测试哈希生成算法,以确保获得相同结果。

以下是一些基于 host_name 生成哈希值的代码示例。

例 Python
>>> import xxhash >>> from bitstring import BitArray >>> b=xxhash.xxh64('HOST-ID-1235').digest() >>> BitArray(b).int % 8192 ### 3195
例 Go(转到)
package main import ( "bytes" "fmt" "github.com/cespare/xxhash" ) func main() { buf := bytes.NewBufferString("HOST-ID-1235") x := xxhash.New() x.Write(buf.Bytes()) // convert unsigned integer to signed integer before taking mod fmt.Printf("%f\n", abs(int64(x.Sum64())) % 8192) } func abs(x int64) int64 { if (x < 0) { return -x } return x }
例 Java
import java.nio.ByteBuffer; import net.jpountz.xxhash.XXHash64; public class test { public static void main(String[] args) { XXHash64 hasher = net.jpountz.xxhash.XXHashFactory.fastestInstance().hash64(); String host = "HOST-ID-1235"; ByteBuffer buf = ByteBuffer.wrap(host.getBytes()); Long result = Math.abs(hasher.hash(buf, 0L)); Long partition = result % 8192; System.out.println(result); System.out.println(partition); } }
例 Maven 中的依赖项
<dependency> <groupId>net.jpountz.lz4</groupId> <artifactId>lz4</artifactId> <version>1.3.0</version> </dependency>