Amazon Simple Storage Service
开发人员指南 (API Version 2006-03-01)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

请求速率和性能注意事项

本主题讨论根据您的请求速率优化性能的 Amazon S3 最佳实践。 如果 Amazon S3 存储桶中的日常工作负载超出每秒 100 个 PUT/LIST/DELETE 请求,或超出每秒 300 个 GET 请求,请遵循本主题中的指南,以确保实现最佳性能和可扩展性。 

Amazon S3 可进行扩展,以支持非常高的请求速率。如果请求速率稳定增长,则 Amazon S3 会自动根据需要将您的存储桶进行分区,以支持更高的请求速率。但是,如果预计存储桶的请求速率会快速提高到超过每秒 300 个 PUT/LIST/DELETE 请求或超过每秒 800 个 GET 请求,我们建议您开立一个支持案例,以便为工作负载做好准备,并且避免对请求速率的任何临时限制。要开立一个支持案例,请参阅联系我们

注意

本主题中的 Amazon S3 最佳实践准则仅适用于日常每秒处理 100 个或更多请求的情况。如果您的典型工作负载只是偶尔达到每秒 100 个请求的突发量,并且请求数少于每秒 800 个,则您无需遵循下述准则。

如果 Amazon S3 中的工作负载将服务器端加密与 AWS 密钥管理服务 (SSE-KMS) 结合使用,请转至 AWS Key Management Service Developer Guide 中的限制以获取有关使用案例支持的请求速率的更多信息。

本主题中给出的 Amazon S3 最佳实践准则基于两类工作负载:

  • 包含混合请求类型的工作负载 – 如果请求一般为 GET、PUT、DELETE 或 GET Bucket (列出对象) 的组合,则为对象合理选择键名称可缩短访问 Amazon S3 索引的延迟,从而确保实现更高的性能。这样还可确保可扩展性 (与每秒发送的请求数无关)。

  • GET 密集型工作负载 – 如果工作负载中包含大量的 GET 请求,则我们建议使用 Amazon CloudFront 内容传输服务。

具有混合请求类型的工作负载

上传大量对象时,客户有时会在其键名称中使用顺序编号或日期和时间值。例如,您可以选择使用某种日期和时间组合的键名称,如下例所示,其中前缀包含时间戳:

Copy
examplebucket/2013-26-05-15-00-00/cust1234234/photo1.jpg examplebucket/2013-26-05-15-00-00/cust3857422/photo2.jpg examplebucket/2013-26-05-15-00-00/cust1248473/photo2.jpg examplebucket/2013-26-05-15-00-00/cust8474937/photo2.jpg examplebucket/2013-26-05-15-00-00/cust1248473/photo3.jpg ... examplebucket/2013-26-05-15-00-01/cust1248473/photo4.jpg examplebucket/2013-26-05-15-00-01/cust1248473/photo5.jpg examplebucket/2013-26-05-15-00-01/cust1248473/photo6.jpg examplebucket/2013-26-05-15-00-01/cust1248473/photo7.jpg ...

键名称的顺序模式引入了性能问题。为了理解该问题,我们来看看 Amazon S3 如何存储键名称。

Amazon S3 在每个 AWS 区域维护对象键名称的索引。对象键以 UTF-8 二进制顺序保存在索引的多个分区中。键名称指示用于存储键的分区。对于大量键,使用顺序前缀 (如时间戳或字母顺序) 可增大 Amazon S3 以特定分区为目标的可能性,从而耗尽该分区的 I/O 容量。如果您在键名称前缀中引入某种随机性,则键名称 (以及 I/O 负载) 会在多个分区间分布。

如果您预计工作负载将持续超过每秒 100 个请求,则应避免使用顺序键名称。如果必须在键名称中使用顺序编号或日期和时间模式,请向键名称添加随机前缀。前缀的随机性可在多个索引分区间更加均匀地分布键名称。本主题后面部分提供了引入随机性的示例。

注意

以下部分中为键名称前缀提供的准则还适用于存储桶名称。Amazon S3 将键名称存储在索引中时,会将存储桶名称作为键名称的一部分进行存储 (例如 examplebucket/object.jpg)。

示例 1:向键名称添加十六进制哈希前缀

向键名称引入随机性的一种方式是向键名称添加哈希字符串作为前缀。例如,您可以计算计划分配为键名称的字符序列的 MD5 哈希。从哈希中选取特定数量的字符,然后将其作为前缀添加到键名称。以下示例演示具有四字符哈希的键名称。

注意

包含三个或四个字符的哈希前缀可满足需要。 我们强烈建议使用十六进制哈希作为前缀。

Copy
examplebucket/232a-2013-26-05-15-00-00/cust1234234/photo1.jpg examplebucket/7b54-2013-26-05-15-00-00/cust3857422/photo2.jpg examplebucket/921c-2013-26-05-15-00-00/cust1248473/photo2.jpg examplebucket/ba65-2013-26-05-15-00-00/cust8474937/photo2.jpg examplebucket/8761-2013-26-05-15-00-00/cust1248473/photo3.jpg examplebucket/2e4f-2013-26-05-15-00-01/cust1248473/photo4.jpg examplebucket/9810-2013-26-05-15-00-01/cust1248473/photo5.jpg examplebucket/7e34-2013-26-05-15-00-01/cust1248473/photo6.jpg examplebucket/c34a-2013-26-05-15-00-01/cust1248473/photo7.jpg ...

请注意,这种随机性会带来一些有趣的挑战。Amazon S3 提供一个 GET Bucket (列出对象) 操作,该操作返回以 UTF-8 二进制顺序列出的键名称列表。下面是一些副作用:

  • 不过,因为使用哈希前缀,所以该列表以随机顺序显示。

  • 如果您想要列出键名称中带有特定日期的对象键,问题会更加复杂。前面的示例使用由 4 个字符组成的十六进制哈希,因此有 65536 种可能的字符组合 (4 字符前缀,每个字符都可以是十六进制字符 0-f 中的任何一个)。因此,您将发送 65536 个 List Bucket 请求,每个请求都带有一个特定的 4 位哈希和日期组合前缀。例如,假设您要查找键名称中带有 2013-26-05 的所有键,您将发送带有 [0-f][0-f][0-f][0-f]2013-26-05 这样的前缀的 List Bucket 请求。

可以选择在键名称中的哈希字符串前添加更多前缀,以对对象进行分组。以下示例向键名称添加 animations/videos/ 前缀。

Copy
examplebucket/animations/232a-2013-26-05-15-00-00/cust1234234/animation1.obj examplebucket/animations/7b54-2013-26-05-15-00-00/cust3857422/animation2.obj examplebucket/animations/921c-2013-26-05-15-00-00/cust1248473/animation3.obj examplebucket/videos/ba65-2013-26-05-15-00-00/cust8474937/video2.mpg examplebucket/videos/8761-2013-26-05-15-00-00/cust1248473/video3.mpg examplebucket/videos/2e4f-2013-26-05-15-00-01/cust1248473/video4.mpg examplebucket/videos/9810-2013-26-05-15-00-01/cust1248473/video5.mpg examplebucket/videos/7e34-2013-26-05-15-00-01/cust1248473/video6.mpg examplebucket/videos/c34a-2013-26-05-15-00-01/cust1248473/video7.mpg ...

这种情况下,GET Bucket (列出对象) 操作返回的有序列表按前缀 animationsvideos 进行分组。

注意

同样,为对对象进行分组而添加的前缀不应具有顺序,否则将再次耗尽单个索引分区。

示例 2:反转键名称字符串

假设应用程序上传的对象的键名称前缀包含递增应用程序 ID 序列。

Copy
examplebucket/2134857/data/start.png examplebucket/2134857/data/resource.rsrc examplebucket/2134857/data/results.txt examplebucket/2134858/data/start.png examplebucket/2134858/data/resource.rsrc examplebucket/2134858/data/results.txt examplebucket/2134859/data/start.png examplebucket/2134859/data/resource.rsrc examplebucket/2134859/data/results.txt

在这一键命名方案中,写入操作会耗尽单个索引分区。但是,如果反转应用程序 ID 字符串,则键名称包含随机前缀:

Copy
examplebucket/7584312/data/start.png examplebucket/7584312/data/resource.rsrc examplebucket/7584312/data/results.txt examplebucket/8584312/data/start.png examplebucket/8584312/data/resource.rsrc examplebucket/8584312/data/results.txt examplebucket/9584312/data/start.png examplebucket/9584312/data/resource.rsrc examplebucket/9584312/data/results.txt

反转键名称字符串奠定了基础,使 Amazon S3 从以下分区开始,每个分区用于键名称中每个不同的首字符。examplebucket 引用您在其中上传应用程序数据的存储桶的名称。

Copy
examplebucket/7 examplebucket/8 examplebucket/9

此示例介绍 Amazon S3 如何使用键名称的第一个字符进行分区,但对于非常大的工作负载 (每秒多于 2000 个请求或对于包含数十亿对象的存储桶) 来说,Amazon S3 可以使用更多字符进行分区。随着键计数和请求速率随时间而提高,Amazon S3 可以自动进一步拆分这些分区。

GET 密集型工作负载

如果工作负载主要发送 GET 请求,则除了上述准则之外,还应考虑使用 Amazon CloudFront 实现性能优化。

通过将 Amazon CloudFront 与 Amazon S3 集成,可以在向用户分发内容时同时实现低延迟和高数据传输速率。另外可以减少向 Amazon S3 发送直接请求,从而降低成本。

例如,假设有几个十分常用的对象。Amazon CloudFront 将从 Amazon S3 提取这些对象并对其进行缓存。Amazon CloudFront 随后可以从其缓存中为针对这些对象的更多请求提供服务,从而减少它发送到 Amazon S3 的 GET 请求数。有关更多信息,请参阅 Amazon CloudFront 产品详细信息页面。