哈希值和 ETag:最佳做法

Cloud Storage 鼓励用户使用 CRC32c 或 MD5 校验和来验证他们从存储分区传入/传出的数据。本节介绍了执行这些验证的最佳做法。

使用哈希值进行完整性检查

上传到云中或从云中下载时,存在多种方法可以造成数据损坏:

  • 嘈杂的网络链接
  • 客户端或服务器计算机或路径上的路由器发生的内存错误
  • 软件错误(例如,客户使用的库中发生软件错误)

为防止数据损坏,Cloud Storage 支持两种类型的哈希值:CRC32C 和 MD5(如下所述)。Google 建议客户在所有情况下都使用 CRC32C(如下面的“验证”一节所述)。偏好 MD5 的客户可以使用哈希值,但复合对象不支持哈希值。

CRC32C

所有 Cloud Storage 对象都具有 CRC32c 哈希值。CRC32C 是一个基于 Castagnoli 多项式的 32 位循环冗余校验 (CRC)。此 CRC 由 SCTP 的 IETF 规范进行描述。用于计算 CRC32c 的库包括:

Base64 编码的 CRC32c 采用大端序字节顺序。

MD5

Cloud Storage 支持为非复合对象使用 MD5 哈希值。此哈希值仅适用于完整对象,因此不能对部分下载(因执行范围 GET 请求而导致)执行完整性检查。

ETag

过去,对象的 MD5 通过 ETag 标头进行表达。对于 XML API 中的非复合对象,仍然会采用这种方式,但由于复合对象不支持 MD5 哈希值,用户不应根据规范做出与这些 ETag 有关的任何假设(除非它们会随着基础数据的更改而发生更改)。

验证

您可以对下载的数据动态执行哈希处理并将结果与服务器提供的哈希值进行比较,以此来执行下载完整性检查。您应丢弃具有错误哈希值的下载数据,并应使用重试逻辑来避免可能代价高昂的无限循环。

Cloud Storage 支持对上传的数据执行服务器端验证,但客户端验证也是一种常见方法。如果您的应用在开始上传之前已经计算了对象的 MD5 或 CRC32c,您可以随同上传请求提供这些数据,并且,仅当您提供的哈希值与我们计算的值匹配时,Cloud Storage 才会创建对象。

或者,用户可以选择通过如下方法执行客户端验证:针对新对象的元数据发出请求,比较报告的哈希值,并在不匹配的情况下删除对象。为避免出现竞争条件(导致独立进程删除或覆盖彼此的数据),我们还建议您使用对象世代和前提条件

在使用对象合成进行并行上传时,用户应对上传的每个组件执行完整性检查,然后在合成请求中使用组件前提条件来防止出现竞争条件。 对象合成功能不提供服务器端 MD5 验证,因此,希望执行端到端完整性检查的用户应将客户端验证应用于新的复合对象。

在每个复制操作结束时,gsutil cprsync 命令会验证本地文件的校验和是否与存储在 Cloud Storage 中的对象的校验和匹配。如果不匹配,gsutil 将删除无效副本并输出一则警告消息。很少发生这种情况。如果确实出现了这种问题,您可以重试操作。

XML API

在 XML API 中,系统通过 x-goog-hash 标头展示并接受 base64 编码的 MD5 和 CRC32c 哈希值。在过去,MD5 用作对象的 ETag,但我们建议用户避免做出这种假设,因为复合对象将使用不透明的 ETag 值,这些值无法保证在对象更改时也会发生更改。

您可以通过 x-goog-hash 请求标头提供本地计算的哈希值,以便执行服务器端上传验证。此外,您可以使用标准 HTTP Content-MD5 标头提供 MD5(请参阅规范)。

JSON API

在 JSON API 中,对象资源 md5Hashcrc32c 属性分别包含 base64 编码的 MD5 和 CRC32c 哈希值。您可以选择提供任意一种元数据属性。如果没有在对象的插入请求中提供这些属性,Cloud Storage 会计算这些值并将其写入对象的元数据。在插入请求中提供任意一种属性后,会为新对象触发服务器端验证。如果 Cloud Storage 为任一属性计算出的值与提供的值不匹配,则不会创建该对象。对于可恢复的上传和多部分上传,您使用的是 md5Hashcrc32c 属性,其使用方式与插入单个对象时相同。