写入

本页面列出了可以发送到 Bigtable 的写入请求类型,并说明了何时应该使用以及何时不应使用这些请求。

借助 Bigtable Data API 和客户端库,您能以编程方式将数据写入表中。Bigtable 会针对每次写入发回响应或确认。

每个客户端库都具备发送以下类型的写入请求的功能:

  • 简单写入
  • 增量和附加
  • 条件写入
  • 批量写入

Bigtable 客户端库具备适用于简单写入和批量写入的内置智能重试功能,这意味着其可以无缝处理暂时无法使用的情况。例如,如果您的应用尝试写入数据却遇到临时中断或网络问题,它会自动重试,直至提交写入或达到请求时限。这种弹性同时支持采用单集群路由或多集群路由的单集群和复制的实例。

对于批量写入操作和流式写入操作,您可以使用 [Bigtable Beam 连接器。如需了解详情,请参阅批量写入

如需了解适用于写入请求的限制,请参阅配额和限制

每个 Cloud Bigtable 客户端库都提供了每种写入类型的示例

如需了解如何向汇总单元格添加数据,请参阅写入时汇总值预览版)。

写入的类型和适用情形

所有写入请求都包含以下基本组成部分:

  • 要写入的表的名称。
  • 向 Bigtable 说明如何进行流量路由的应用配置文件 ID。
  • 一项或多项变更。变更包含以下四个元素:
    • 列族名称
    • 列限定符
    • 时间戳
    • 要写入表的值

变更的时间戳以当前日期和时间作为默认值,时间是从 Unix 纪元(世界协调时间 [UTC] 1970 年 1 月 1 日 00:00:00)起经过的时间。

发送到 Bigtable 的时间戳必须是微秒值,精确率不高于毫秒级。精确率为微秒的时间戳(例如 3023483279876543)会被拒绝。在此示例中,可接受的时间戳值为 3023483279876000

单个写入请求中的所有变更都具有相同的时间戳,除非您将其覆盖。您可以将写入请求中所有变更的时间戳设置为彼此相同或不同。

简单写入

您可以通过 MutateRow 请求向 Bigtable 中写入一行,此请求包括表名称、应该使用的应用配置文件的 ID、一个行键以及该行的多达 10 万项的变更。单行写入为原子化写入。在对单行进行多项变更时,请使用这种类型的写入。

如需查看演示如何发送简单写入请求的代码示例,请参阅执行简单写入

何时不应使用简单写入

在以下使用场景中,简单写入不是写入数据的最佳途径:

  • 写入一批具有连续行键的数据。在这种情况下,您应该使用批量写入而非连续的简单写入,因为前者只需单次后端调用即可应用连续批处理。

  • 您需要高吞吐量(每秒行数或每秒字节数),不需要低延迟。在这种情况下,批量写入速度更快。

增量和附加

在许多情况下,如果您想要增加或增大值,最好使用汇总预览版),该功能可让您在写入时更新值。但是,汇总不支持附加操作。如需了解详情,请参阅写入时聚合值

如果要将数据附加到现有值,或者需要增加现有数值,并且不能使用聚合,可以发送 ReadModifyWriteRow 请求。此请求包括表名称、应该使用的应用配置文件的 ID、一个行键以及一组要在写入数据时使用的规则。每个规则都包含列族名称、列限定符以及附加值或增量。

规则按顺序应用。例如,如果您的请求包含将列的值增加 2 的请求,并且同一请求中的下一个规则将相同列增加 1,那么在这一单次原子化写入中该列增加 3。后面的规则不会覆盖前面的规则。

仅当值采用 64 位大端序有符号整数进行编码时,才可以对该值执行增量操作。如果对空值或不存在的值应用增量,Bigtable 会将该值视为零。ReadModifyWriteRow 请求是原子化请求。如果此类请求由于任何原因失败,将不会重试。

如需查看演示如何在单元中附加值的代码示例,请参阅递增现有值

何时不应使用 ReadModifyWriteRow

在以下情况下,您不应发送 ReadModifyWriteRow 请求:

  • 您的用例可以通过汇总预览版)进行处理。

  • 使用具有多集群路由的应用配置文件。

  • 使用多个单集群应用配置文件并发送写入请求,该请求可能与写入实例中其他集群内的同一行和列的数据冲突。采用单集群路由时,写入请求会发送到单个集群,然后进行复制。

  • 您依赖客户端库提供的智能重试功能。 增量和附加功能不可重试。

  • 写入大量数据并需要快速完成写入操作。与简单写入请求相比,读取然后修改行的请求速度较慢。因此,这类写入往往不是规模较大时的最佳方法。例如,如果要计数的内容数以百万计(例如网页浏览量),则应在写入时使用汇总更新计数。您还可以考虑将每个视图记录为简单写入(而不是递增值),然后使用 Dataflow 作业来聚合数据。

条件写入

如果要检查行是否符合某条件,然后根据检查结果向该行中写入数据,请提交 CheckAndMutateRow 请求。 这种类型的请求包括行键和行过滤条件。行过滤条件是一组用于检查现有数据值的规则。只有当过滤器检查的特定条件得到满足之后,系统才会将变更提交到行中的特定列。这个先检查后写入的过程作为单个原子化操作完成。

过滤请求必须包含以下两种类型的变更中的一种或两种:

  • 真变更,或过滤返回值时应用的变更。
  • 假变更,即过滤未产生任何结果时应用的变更。

在一次写入中,您最多可以提供 100,000 个每种类型的变更(真和假),并且必须至少发送一个。所有变更都完成后,Bigtable 会发送响应。

如需查看演示如何发送条件写入的代码示例,请参阅有条件地写入值

何时不应使用条件写入

以下使用场景下不能使用条件写入:

  • 使用具有多集群路由的应用配置文件。

  • 使用多个单集群应用配置文件并发送写入请求,该请求可能与写入实例中其他集群内的同一行和列的数据冲突。采用单集群路由时,写入请求会发送到单个集群,然后进行复制。

批量写入

您可以使用 MutateRows 请求,通过单个调用写入多个行。MutateRows 请求包含一组多达 10 万个的条目,其中的每个条目均以原子化方式应用。每个条目包含一个行键以及至少一个要应用于该行的变更。一个批量写入请求可包含多达 100,000 个变更,这些变更分布于所有条目之间。例如,批量写入可能包括以下任何排列:

  • 100,000 个条目,每个条目中包含 1 项变更。
  • 包含 100,000 项变更的 1 个条目。
  • 1000 个条目,每个条目中包含 100 项变更。

MutateRows 请求中的每个条目都是原子化条目,但整个请求不是。如有必要,Bigtable 会重试该批次中未成功的任何条目,直到所有写入成功或达到请求期限。然后,它会返回一个标识批次中各写入操作以及写入操作是否成功的响应。

如需查看演示如何发送批量写入的代码示例,请参阅执行批量写入

何时不应使用批量写入

  • 将批量数据写入彼此不靠近的行。Bigtable 按行键的字典顺序存储数据,这是字母顺序的二进制版本。因此,当请求中的行键彼此不相似时,Bigtable 会按顺序对其进行处理,而不会采取并行处理方式。吞吐量高,但延迟也高。为了避免这种高延迟,当行键类似并且 Bigtable 要写入彼此靠近的行时,请使用 MutateRows。针对彼此不靠近的行,请使用 MutateRow 或简单写入。

  • 请求对同一行进行多项变更。在这种情况下,如果在单个简单写入请求中执行所有变更,则效果更佳。这是因为在简单写入中,所有更改都通过单个原子化操作提交,但系统会强制批量写入对同一行的变更进行序列化,从而导致延迟。

批量写入流控制

如果您使用以下某种方式发送批量写入,则可以在代码中启用批量写入流控制

为 Dataflow 作业启用批量写入流控制后,Bigtable 会自动执行以下操作:

  • 限制流量速率以避免 Bigtable 集群过载
  • 确保集群负载足以触发 Bigtable 自动扩缩(如果已启用),从而在需要时自动向集群添加更多节点

这些合并操作可防止集群过载和作业失败,并且您无需为运行批量写入而手动扩缩集群。启用流控制后,集群扩缩会在 Dataflow 作业期间(而不是之前)发生,因此作业完成所需的时间可能比手动扩缩集群更长。

您必须使用针对单集群路由配置的应用配置文件。为目标集群启用 Bigtable 自动扩缩不是必需的,但自动扩缩可让您充分利用批量写入流控制。您可以像处理任何其他作业一样使用 Dataflow 自动扩缩。

如需详细了解 Bigtable 自动扩缩,请参阅自动扩缩。如需了解应用配置文件路由政策,请参阅应用配置文件概览

如需查看演示如何使用 Bigtable HBase Beam 连接器启用批量写入流控制的代码示例,请参阅向 Bigtable 写入数据

将数据写入已获授权的视图

如需将数据写入已获授权的视图,您必须使用以下方法之一:

  • gcloud CLI
  • Java 版 Bigtable 客户端

其他 Bigtable 客户端库尚不支持已获授权的视图访问。

当您将数据写入已获授权的视图时,除了表格 ID 之外,还需要提供已获授权的视图 ID。

对授权视图的所有写入都会直接应用于底层表。

已获授权的视图定义限制

在授权视图中,可以写入数据的行或列受到已获授权的视图定义的限制。换言之,您只能写入符合为已获授权的视图指定的相同条件的行和列。

例如,如果授权视图由行键前缀 examplepetstore1 定义,那么您不能使用行键 examplepetstore2 来写入数据;行键值的开头必须包含整个字符串 examplepetstore1

同样,如果授权视图由列限定符前缀 order-phone 定义,那么您可以使用列限定符 order-phone123 写入数据,但不能使用列限定符 order-tablet

您的写入请求也无法引用已获授权的视图之外的数据,例如,当您检查条件写入请求中的值时。

对于在授权视图之外写入或引用数据的任何请求,系统将返回 PERMISSION_DENIED 错误消息。

复制

当复制的实例的一个集群收到写入时,该写入会立即复制到该实例中的其他集群。

原子性

您发送到复制的实例的每个 MutateRows 请求都会在请求路由到的集群上作为单个原子操作提交。当写入被复制到实例中的其他集群时,每一个这些集群也会将写入作为原子操作接收。集群不会收到部分变更;变更要么成功,要么对于它修改的所有单元自动失败。

一致性

您写入的数据在多长时间之后可用于读取取决于多个因素,其中包括实例中的集群数量以及应用配置文件使用的路由类型。就单集群实例而言,数据立即就可以读取,但如果实例有多个集群(即使用复制),Bigtable 将实现最终一致性。通过将请求路由到同一集群,您可以实现读己所写 (read-your-writes) 一致性

发送写入请求后,您可以创建并使用一致性令牌,并在 StandardReadRemoteWrites 模式下调用 CheckConsistency。该令牌会检查复制一致性。通常,您可以在发送完一批写入操作之后或在特定时间间隔(例如一小时)之后创建一致性令牌。然后,您可以将令牌交给其他进程使用,例如发出读取请求的模块,该模块使用令牌进行检查,以确保所有数据在其尝试读取前都已被复制。

如果您在创建令牌后立即使用该令牌,首次使用时可能需要几分钟时间来检查一致性。此延迟是因为各集群会检查每个其他集群,以确保不再有数据传入。初次使用之后,或者如果您等待几分钟再首次使用令牌,则每次使用令牌时都会立即成功。

冲突解决

Bigtable 表中的每个单元格值都通过四元组(行键、列族、列限定符、时间戳)进行唯一标识。如需详细了解这些标识符,请参阅 Bigtable 存储模型。在极少数情况下,当将两个具有完全相同的四元组的写入发送到两个不同的集群时,Bigtable 会基于服务器端时间使用内部“最后写入内容生效”算法自动解决冲突。Bigtable“最后写入内容生效”实现具有确定性,当副本完成同步后,所有集群都具有四元组的相同值。

后续步骤