Cloud Storage 建议您验证传入/传出存储桶的数据。本页面介绍了使用 CRC32C 或 MD5 校验和执行验证的最佳实践,并介绍了 gcloud storage rsync
命令所使用的更改检测算法。
使用哈希值来防止数据损坏
上传到云中或从云中下载时,存在多种方法可以造成数据损坏:
- 客户端或服务器计算机或路径上的路由器发生的内存错误
- 软件错误(例如,客户使用的库中发生软件错误)
- 上传时间较长时更改源文件
Cloud Storage 支持两种类型的哈希值,供您检查数据的完整性:CRC32C 和 MD5。CRC32C 是执行完整性检查的推荐验证方法。偏好 MD5 的客户也可以使用该哈希,但并非所有对象都支持 MD5 哈希。
客户端验证
您可以对下载的数据执行完整性检查,方法是动态对数据执行哈希处理并将结果与服务器提供的校验和进行比较。不过,请注意,服务器提供的校验和基于存储在 Cloud Storage 中的完整对象,这意味着无法使用服务器提供的哈希值验证以下类型的下载:
下载内容经过解压缩式转码,因为服务器提供的校验和代表对象的压缩状态,而传送的数据已移除压缩,因此具有不同的哈希值。
响应中仅包含部分对象数据,这种情况在发出
range
请求时会发生。Cloud Storage 建议您仅在最后一次收到偏移之后,使用范围请求重新开始下载完整对象,因为在这种情况下,您可以在完成完整下载时计算并验证校验和。
如果您可以使用校验和验证下载内容,则应丢弃具有错误哈希值的下载数据,并使用推荐的重试逻辑重试请求。
服务器端验证
在以下情况下,Cloud Storage 会执行服务器端验证:
在 Cloud Storage 中执行复制或重写请求时。
在上传请求中提供对象的预期 MD5 或 CRC32C 哈希值。仅当您提供的哈希值与 Cloud Storage 计算的值匹配时,Cloud Storage 才会创建对象。 如果不匹配,请求会被拒绝并显示
BadRequestException: 400
错误。在适用的 JSON API 请求中,您可以将校验和作为对象资源的一部分提供。
在适用的 XML API 请求中,您可以使用
x-goog-hash
标头提供校验和。XML API 还接受标准 HTTP Content-MD5 标头(请参阅规范)。或者,您可以通过如下方法执行上传的客户端验证:针对上传的对象的元数据发出请求,将上传的对象的哈希值与预期值进行比较,并在不匹配的情况下删除对象。如果在上传开始时不知道对象的 MD5 或 CRC32C 哈希值,则此方法很有用。
在进行并行复合上传时,用户应对上传的每个组件执行完整性检查,然后在合成请求中使用前提条件来防止出现竞争条件。Compose 请求不执行服务器端验证,因此,希望执行端到端完整性检查的用户应对新的复合对象执行客户端验证。
Google Cloud CLI 验证
对于 Google Cloud CLI,系统会验证复制到 Cloud Storage 存储桶或从其中复制的数据。这适用于 cp
、mv
和 rsync
命令。如果源数据的校验和与目标数据的校验和不匹配,则 gcloud CLI 会删除无效副本并输出一条警告消息。很少发生这种情况。如果发生这种情况,您应重试操作。
此自动验证操作发生在对象本身最终确定之后,因此无效对象在被识别和删除之前可显示 1-3 秒钟。此外,gcloud CLI 可能会在上传完成之后但在执行验证之前被中断,使无效对象保留下来。使用服务器端验证将单个文件上传到 Cloud Storage 时可避免这些问题,进行此操作时使用 --content-md5
标志。
对 rsync
的更改检测
gcloud storage rsync
命令还可以使用 MD5 或 CRC32C 校验和来确定在源对象中找到的对象版本与在目标对象中找到的版本之间是否存在差异。该命令会在以下情况下比较校验和:
源和目标都是 Cloud Storage 存储桶,并且对象在两个存储桶中都有 MD5 或 CRC32C 校验和。
对象在源或目标位置都没有文件修改时间 (
mtime
)。
如果相关对象在源和目标中都具有 mtime
值(例如,源和目标是文件系统),rsync
命令会比较对象的大小和 mtime
,而不是使用校验和。同样,如果来源是云端存储桶,而目标是本地文件系统,rsync
命令会使用为来源对象创建的时间来替代 mtime
,并且该命令不会使用校验和。
如果 mtime
和校验和均不可用,则 rsync
仅在确定对象的源版本与目标版本之间是否存在变化时才会比较文件大小。例如,当将复合对象与不支持 CRC32C 的云提供商中的对象进行比较时,mtime
和校验和均不可用,因为复合对象没有 MD5 校验和。