请求率和访问分配准则

Cloud Storage 是一项可扩缩性极强的服务,利用自动扩缩技术来实现极高的请求速率。本页面介绍关于优化 Cloud Storage 规模扩缩能力和性能的一些准则。

自动扩缩

Cloud Storage 是一项多租户服务,这意味着用户可以共享同一组底层资源。为了充分利用这些共享资源,存储桶的初始 IO 容量如下:

  • 每秒大约 1000 次对象写入请求(包括上传、更新和删除对象的请求)。注意,Cloud Storage 对相同对象名称的重复写入也具有较小的限制
  • 每秒大约 5000 次对象读取请求(包括列出对象、读取对象数据和读取对象元数据的请求)。

对于大小为 1 MB 的对象而言,这些初始读取和写入速率每月平均可读取 13 PB 的对象及写入 2.5 PB 的对象。随着指定存储桶请求速率的增长,Cloud Storage 会通过将请求负载分配到多个服务器上,自动扩缩和自动提高该存储桶的 IO 容量。

负载重新分配时间

当存储桶的 IO 容量即将达到其上限时,Cloud Storage 通常会数分钟检测一次负载,并根据情况将负载重新分配到更多服务器上。因此,如果您存储桶的请求率增长过快,使 Cloud Storage 来不及执行这种重新分配,那么您可能会遇到临时性限制,具体而言,可能出现较长的延迟时间和较高的错误率。 如要避免出现此类延时和错误,请按照下文所述逐渐提高您存储桶的请求率。

对象键索引

Cloud Storage 支持一致的对象列表,这可让用户轻松地针对 Cloud Storage 运行数据处理工作流。为了提供一致的对象列表,Cloud Storage 会针对每个存储桶维护一个对象键索引。这种索引按字典顺序存储,并会在有对象写入存储桶或从存储桶删除时进行更新。 添加和删除对象时,如果相应对象键全部存在于小范围索引之中,自然会增加争用的可能性。

Cloud Storage 会检测此类争用情况(也称为 hotspotting),并自动将受影响索引范围内的负载重新分配到多个服务器上。与扩缩存储桶的 IO 容量类似,当访问新的索引范围时(例如,以新前缀写入对象),您应逐步提升请求速率,如下所述。否则,可能会导致暂时性的高延时和高错误率。

最佳做法

以下部分提供了有关如何通过提升请求速率、选择对象键和分配请求来避免存储桶出现临时性限制的最佳做法。 请注意,除了这些针对单个存储桶的考虑因素之外,还存在适用于同一位置和项目中的存储桶的组合带宽限制

逐步提升请求速率

为确保 Cloud Storage 自动扩缩功能始终发挥最佳性能,对于那些请求速率已持续数天保持较低水平或具有新对象键范围的任何存储桶,您应逐步提升其请求速率。如果您的请求速率低于每秒 1000 次写入请求或每秒 5000 次读取请求,则不需要提升请求速率。如果预计您的请求速率会超过这些阈值,您应先从低于或接近阈值的请求速率开始,然后逐渐提高速率,在 20 分钟的时间段内不超过速率的一倍。

如果您遇到任何问题(例如,延迟时间延长或错误率增加),请暂停提升操作或暂时降低请求率,以便为 Cloud Storage 提供更多时间来扩缩您的存储桶。在以下情况下,您应该使用指数退避算法重试您的请求

  • 收到响应代码为 408429 的错误。
  • 收到响应代码为 5xx 的错误。

与未启用分层命名空间的存储分区相比,启用了分层命名空间的存储分区可为读写对象提供高达 8 倍的初始每秒查询次数 (QPS) 限制。更高的初始 QPS 可让您更轻松地扩展数据密集型工作负载,并提高吞吐量。如需详细了解如何在存储桶上启用分层命名空间,请参阅创建启用了分层命名空间的存储桶

借助命名惯例将负载均匀分配到多个键范围中

使用顺序名称(例如基于数字序列或时间戳序列的对象键)时,索引范围的自动扩缩速度可能会很慢。发生这种情况的原因在于,请求不断变换新的索引范围,使负载的重新分配更加困难,效率也更加低下。

为了保持较高的请求速率,请避免使用顺序名称。使用完全随机的对象名称可让您实现负载的最佳分配。如果您想要将序列号或时间戳用作对象名称的一部分,请通过在序列号或时间戳之前添加哈希值来为对象名称引入随机性。

例如,如果要使用的原始对象名称如下:

my-bucket/2016-05-10-12-00-00/file1
my-bucket/2016-05-10-12-00-00/file2
my-bucket/2016-05-10-12-00-01/file3
...

您可以计算原始对象名称的 MD5 哈希值,并将所得哈希值的前 6 个字符作为前缀添加到对象名称中。新对象名称如下:

my-bucket/2fa764-2016-05-10-12-00-00/file1
my-bucket/5ca42c-2016-05-10-12-00-00/file2
my-bucket/6e9b84-2016-05-10-12-00-01/file3
...

在循序渐进地达到非常高的读写速率时,较长的随机前缀可提供更有效的自动扩缩功能。例如,使用随机十六进制值的 1 个字符的前缀会提供从最初每秒 5000/1000 次读取/写入有效自动扩缩至每秒大约 80000/16000 次读取/写入,因为前缀具有 16 个可能的值。如果您的使用场景不需要高于此速率的速率,则在循序渐进地提高请求速率时,1 个字符的随机前缀与 2 个字符或更长的随机前缀同样有效。

在通用前缀后面引入的随机性仅在该前缀范围内有效

请注意,随机字符串并非必须位于对象名称的开头。如果将随机字符串添加到通用前缀之后,自动扩缩功能仍然可以发挥作用,但效果仅局限于该前缀,而不考虑存储桶的其余部分。

例如:

my-bucket/images/animals/4ce4c6af-6d27-4fa3-8a91-5701a8552705/1.jpg
my-bucket/images/animals/9a495e72-1d85-4637-a243-cbf3e4a90ae7/2.jpg
...
my-bucket/images/landscape/585356ac-ce89-47a8-bdd2-78a86b58fee6/1.jpg
my-bucket/images/landscape/2550ae5b-395e-4243-a29b-bbf5aece60ef/2.jpg
...
my-bucket/images/clouds/1.jpg
my-bucket/images/clouds/2.jpg
...

上述命名方式可让 images/animalsimages/landscape, 中的对象有效地自动扩缩,而 images/clouds 中的对象则不会受到影响。

在顺序前缀后面引入随机值的效果不大

如上所述,在通用前缀之后使用随机字符串仅有助于在该前缀范围内实现自动扩缩。一旦请求变换为新的前缀,您可能就无法再获得先前的自动扩缩效果。如果前缀采用的是顺序模式,此问题尤为明显。

例如,如果您每小时以新的时间戳式前缀写入文件:

my-bucket/2016-05-10-00/cf9a7b95-0d2e-4466-9596-840ff388ddbd
my-bucket/2016-05-10-00/f1e16a88-16b8-4c66-ba66-a225c87be80c
my-bucket/2016-05-10-00/646d8272-4a88-4dc2-b2d4-d537c778df41
...
my-bucket/2016-05-10-01/bdcba6de-ac25-4c27-8550-0d08f249e69d
my-bucket/2016-05-10-01/a32c867c-09a9-4d65-9668-ddd4ebe4138b
my-bucket/2016-05-10-01/d619485c-5243-4a4e-8ef3-0f7e1d26ce1d
...

虽然自动扩缩有助于提高一段时间内某前缀下的写入速率,但系统会在每小时一开始时重置该写入速率。这会导致无法实现最理想的写入速率,并且延迟时间和错误率也会定期增加。 如果某段时间内您需要以不同的前缀执行写入操作,那么为避免出现上述问题,请务必在整个键范围内均匀分配新的前缀。

重新排序批量操作,将负载均匀分配到键范围中

有时,您需要在 Cloud Storage 中对数据执行批量上传或删除操作。在这两种情况下,您可能无法控制对象名称。不过,您可以控制对象的上传或删除顺序,从而尽可能实现最高的写入或删除速率。

为此,您应该在多个前缀之间分配上传或删除操作。 例如,如果要上传的每个文件夹下包括许多文件夹和文件,最好从多个文件夹并行上传,并随机选择要上传的文件夹和文件。采用这种方法,系统可在整个键范围内更均匀地分配负载,从而可以在初始加速后实现高请求率。

后续步骤