写入
本页面列出了可以发送到 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 万项的变更。单行写入为原子化写入。在对单行进行多项变更时,请使用这种类型的写入。
如需查看演示如何发送简单写入请求的代码示例,请参阅执行简单写入。
何时不应使用简单写入
在以下使用场景中,简单写入不是写入数据的最佳途径:
写入一批具有连续行键的数据。在这种情况下,您应该使用批量写入而非连续的简单写入,因为前者只需单次后端调用即可应用连续批处理。
您需要高吞吐量(每秒行数或每秒字节数),不需要低延迟。在这种情况下,批量写入速度更快。
汇总(包括增量)
汇总是指 Bigtable 表单元格,用于在写入数据时汇总单元格值。可用的汇总类型如下:
- 求和 - 递增计数器或保持累计总和。
- 最小值 - 向单元格发送一个整数,Bigtable 会保留当前单元格值和发送值中的较小值,如果单元格尚不存在,则保留发送值。
- 最大值 - 将整数发送到包含值的单元格,Bigtable 会保留这两个值中较大的值。
- HyperLogLog (HLL) - 发送添加到单元格中所有值的概率集合的值。
更新汇总单元格的请求会随 MutateRow
请求一起发送,并且更改类型为 AddToCell
或 MergeToCell
,或为删除更改类型之一。如需详细了解汇总列族和汇总类型,请参阅在写入时汇总值。
附加
如需将数据附加到现有值,您可以使用 ReadModifyWriteRow
请求。该请求包括表名称、应该使用的应用配置文件的 ID、一个行键以及一组要在写入数据时使用的规则。每个规则都包括列族名称、列限定符以及附加值或增量。
规则按顺序应用。例如,如果您的请求包含将包含值 some
的列的值附加字符串 thing
的请求,并且同一请求中的下一个规则将相同列附加 body
,那么在单次原子化写入中,该值会被修改两次,最终值为 somethingbody
。后面的规则不会覆盖前面的规则。
您还可以使用 ReadModifyWriteRow
调用递增整数,但我们建议您改用汇总单元格和 AddToCell
或 MergeToCell
。仅当值采用 64 位大端序有符号整数进行编码时,才可以使用 ReadModifyWrite
对该值执行增量操作。如果对空值或不存在的值应用增量,Bigtable 会将该值视为零。
ReadModifyWriteRow
请求是原子化请求。如果此类请求由于任何原因失败,将不会重试。
不应使用 ReadModifyWriteRow
的情况
请勿在以下情况下发送 ReadModifyWriteRow
请求:
您可以通过发送包含
AddToCell
更改的MutateRow
请求来处理您的用例。如需了解详情,请参阅汇总。使用具有多集群路由的应用配置文件。
使用多个单集群应用配置文件并发送写入请求,该请求可能与写入实例中其他集群内的同一行和列的数据冲突。采用单集群路由时,写入请求会发送到单个集群,然后进行复制。
您依赖客户端库提供的智能重试功能。 无法再次尝试发出
ReadModifyWriteRow
请求。写入大量数据并需要快速完成写入操作。与简单写入请求相比,读取然后修改行的请求速度较慢。因此,这类写入往往不是规模较大时的最佳方法。
例如,如果要计数的内容数以百万计(例如网页浏览量),则应使用
AddToCell
更改MutateRow
,以便在写入时更新计数。
条件写入
如果要检查行是否符合某条件,然后根据检查结果向该行中写入数据,请提交 CheckAndMutateRow
请求。 这种类型的请求包括行键和行过滤条件。行过滤条件是一组用于检查现有数据值的规则。只有当过滤器检查的特定条件得到满足之后,系统才会将变更提交到行中的特定列。这个先检查后写入的过程作为单个原子化操作完成。
过滤请求必须包含以下两种类型的变更中的一种或两种:
- 真变更,或过滤返回值时应用的变更。
- 假变更,即过滤未产生任何结果时应用的变更。
在一次写入中,您最多可以提供 100,000 个每种类型的变更(真和假),并且必须至少发送一个。所有变更都完成后,Bigtable 会发送响应。
如需查看演示如何发送条件写入的代码示例,请参阅有条件地写入值。
何时不应使用条件写入
以下使用场景下不能使用条件写入:
使用具有多集群路由的应用配置文件。
使用多个单集群应用配置文件并发送写入请求,该请求可能与写入实例中其他集群内的同一行和列的数据冲突。采用单集群路由时,写入请求会发送到单个集群,然后进行复制。
写入大量数据并需要快速完成写入操作。与
ReadModifyWriteRow
类似,条件写入请求需要先读取行,然后才能修改它们,因此CheckAndModifyRow
请求的速度比简单写入请求慢。因此,这类写入往往不是规模较大时的最佳方法。
批量写入
您可以使用 MutateRows
请求,通过单个调用写入多个行。MutateRows
请求包含一组多达 10 万个的条目,其中的每个条目均以原子化方式应用。每个条目包含一个行键以及至少一个要应用于该行的变更。一个批量写入请求可包含多达 100,000 个变更,这些变更分布于所有条目之间。例如,批量写入可能包括以下任何排列:
- 100,000 个条目,每个条目中包含 1 项变更。
- 包含 100,000 项变更的 1 个条目。
- 1000 个条目,每个条目中包含 100 项变更。
MutateRows
请求中的每个条目都是原子化条目,但整个请求不是。如有必要,Bigtable 会重试批次中未成功的所有条目,直到所有写入都成功或达到请求截止期限为止。然后,它会返回一个标识批次中各写入操作以及写入操作是否成功的响应。
如需查看演示如何发送批量写入的代码示例,请参阅执行批量写入。
何时不应使用批量写入
将批量数据写入彼此不靠近的行。Bigtable 按行键的字典顺序存储数据,这是字母顺序的二进制版本。因此,当请求中的行键彼此不相似时,Bigtable 会按顺序对其进行处理,而不会采取并行处理方式。吞吐量高,但延迟也高。为了避免这种高延迟,当行键类似并且 Bigtable 要写入彼此靠近的行时,请使用
MutateRows
。针对彼此不靠近的行,请使用MutateRow
或简单写入。请求对同一行进行多项变更。在这种情况下,如果在单个简单写入请求中执行所有变更,则效果更佳。这是因为在简单写入中,所有更改都通过单个原子化操作提交,但系统会强制批量写入对同一行的变更进行序列化,从而导致延迟。
批量写入流控制
如果您使用以下任一方法发送批量写入(包括删除),则可以在代码中启用批量写入流控制。
- Bigtable Beam 连接器 (
BigtableIO
) - Java 版 Bigtable 客户端库
- Bigtable HBase Beam 连接器 (
CloudBigtableIO
) - Java 版 Bigtable HBase 客户端
为 Dataflow 作业启用批量写入流控制后,Bigtable 会自动执行以下操作:
- 限制流量速率以避免 Bigtable 集群过载
- 确保集群负载足以触发 Bigtable 自动扩缩(如果已启用),从而在需要时自动向集群添加更多节点
这些组合操作可防止集群过载和作业失败,并且您无需在运行批量写入之前手动扩缩集群。启用流控制后,集群扩缩会在 Dataflow 作业期间(而不是之前)发生,因此作业完成所需的时间可能比手动扩缩集群更长。
您必须使用针对单集群路由配置的应用配置文件。为目标集群启用 Bigtable 自动扩缩不是必需的,但自动扩缩可让您充分利用批量写入流控制。您可以像使用任何其他作业一样使用 Dataflow 自动扩缩功能。
如需详细了解 Bigtable 自动扩缩,请参阅自动扩缩。如需了解应用配置文件路由政策,请参阅应用配置文件概览。
如需查看代码示例,请参阅启用批量写入流控制。
将数据写入授权视图
如需将数据写入已获授权的视图,您必须使用以下方法之一:
- gcloud CLI
- Java 版 Bigtable 客户端
其他 Bigtable 客户端库尚不支持授权视图访问。
向授权视图写入数据时,您需要提供授权视图 ID 以及表 ID。
对已获授权视图的所有写入都会直接应用于底层表。
获授权视图定义限制
在已获授权的视图中,您可以写入数据的行或列受授权视图定义的限制。也就是说,您只能写入符合为已获授权视图指定的相同条件的行和列。
例如,如果已获授权的视图由行键前缀 examplepetstore1
定义,则您无法使用行键 examplepetstore2
写入数据;行键值的开头必须包含整个字符串 examplepetstore1
。
同样,如果授权视图由列限定符前缀 order-phone
定义,则您可以使用列限定符 order-phone123
写入数据,但不能使用列限定符 order-tablet
。
您的写入请求也不能引用授权视图之外的数据,例如在有条件写入请求中检查值时。
对于写入或引用授权视图之外数据的任何请求,系统都会返回 PERMISSION_DENIED
错误消息。
复制
当复制的实例的一个集群收到写入时,该写入会立即复制到该实例中的其他集群。
原子性
您发送到复制的实例的每个 MutateRows
请求都会在请求路由到的集群上作为单个原子操作提交。当写入被复制到实例中的其他集群时,每一个这些集群也会将写入作为原子操作接收。集群不会收到部分变更;变更要么成功,要么对于它修改的所有单元自动失败。
一致性
您写入的数据在多长时间之后可用于读取取决于多个因素,其中包括实例中的集群数量以及应用配置文件使用的路由类型。
就单集群实例而言,数据立即就可以读取,但如果实例有多个集群(即使用复制),Bigtable 将实现最终一致性。通过将请求路由到同一集群,您可以实现读己所写一致性
发送写入请求后,您可以创建并使用一致性令牌,并在 StandardReadRemoteWrites
模式下调用 CheckConsistency
。该令牌会检查副本是否一致。通常,您在发送完一批写入请求后或在特定时间间隔(例如一小时)之后创建一致性令牌。然后,您可以将令牌交给其他进程使用,例如发出读取请求的模块,此模块使用该令牌进行检查,以确保所有数据在其尝试读取前都已被复制。
如果您在创建令牌后立即使用该令牌,首次使用时可能需要几分钟时间来检查一致性。此延迟是因为各集群会检查每个其他集群,以确保不再有数据传入。初次使用之后,或者如果您等待几分钟再首次使用令牌,则每次使用令牌时都会立即成功。
冲突解决
Bigtable 表中的每个单元格值都通过四元组(行键、列族、列限定符、时间戳)进行唯一标识。如需详细了解这些标识符,请参阅 Bigtable 存储模型。在极少数情况下,当将两个具有完全相同的四元组的写入发送到两个不同的集群时,Bigtable 会基于服务器端时间使用内部“最后写入内容生效”算法自动解决冲突。Bigtable“最后写入内容生效”实现具有确定性,当副本完成同步后,所有集群都具有四元组的相同值。