OSS性能最佳实践

本文介绍利用阿里云OSS分布式架构提升OSS数据处理速度、降低数据延迟、加速应用程序响应能力的多种方法,旨在优化OSS性能表现。

将顺序前缀改为随机性前缀

为了优化OSS的数据分布和提升处理效率,建议您采用随机性前缀替代传统的顺序前缀来命名您的文件。OSS根据文件keyUTF-8编码顺序自动划分数据分区,以支持大规模文件管理和高并发请求。然而,在使用顺序前缀(如时间戳或按字典序排列的字符串)的情况下,可能引起部分分区过载现象,即大量文件集中在少数几个分区中。

例如,当您的请求速率超过2000次/秒时(下载、上传、删除、拷贝、获取元数据信息等操作算1次操作,批量删除N个文件、列举N个文件等操作算N次操作),会带来以下问题:

  • 热点分区形成:高频率的请求集中在某些特定分区,使之变成热点分区,导致分区的I/O能力被耗尽,或被系统自动限制请求速率。

  • 请求速率受限:热点分区的存在会触发系统进行持续的分区数据再均衡,这个过程可能会延长请求处理时间。

    说明

    分区数据再均衡基于实时系统状态和处理能力分析,而非固定拆分规则,使用顺序前缀命名的文件也可能在重新均衡后仍处于热点分区。

为解决以上问题,您可以将文件key的顺序前缀改为随机性前缀,使得文件索引(以及I/O负载)均匀地分布在多个分区。

  • 向文件key添加十六进制哈希前缀

    如果您使用日期与客户ID生成文件key,则包含顺序时间戳前缀:

    sample-bucket-01/2024-07-19/customer-1/file1
    sample-bucket-01/2024-07-19/customer-2/file2
    sample-bucket-01/2024-07-19/customer-3/file3
    ...
    sample-bucket-01/2024-07-20/customer-2/file4
    sample-bucket-01/2024-07-20/customer-5/file5
    sample-bucket-01/2024-07-20/customer-7/file6
    ...

    针对这种情况,您可以对客户ID计算哈希(即MD5),并取若干字符的哈希前缀作为文件key的前缀。假如取4个字符的哈希前缀,那么经过改造后的文件key示例变为:

    sample-bucket-01/9b11/2024-07-19/customer-1/file1
    sample-bucket-01/9fc2/2024-07-19/customer-2/file2
    sample-bucket-01/d1b3/2024-07-19/customer-3/file3
    ...
    sample-bucket-01/9fc2/2024-07-20/customer-2/file4
    sample-bucket-01/f1ed/2024-07-20/customer-5/file5
    sample-bucket-01/0ddc/2024-07-20/customer-7/file6
    ...

    加入4个字符组成的十六进制哈希来作为前缀,则每个字符有0~9以及a~f16种取值,4个字符共有16 4=65536种可能的字符组合。在存储系统中,这些数据理论上会被持续划分至最多65536个分区,以每个分区操作2000次/秒的性能瓶颈标准,再结合您业务的请求速率,可以评估哈希桶的个数是否合适。

    如果您想要列出文件key中带有特定日期的文件,例如列出sample-bucket-01里带有2024-07-19的文件,您只要对sample-bucket-01进行列举(即通过多次调用ListObject接口,分批次地获得sample-bucket-01下的所有文件),然后合并带有该日期的文件即可。

  • 反转文件key

    如果您使用了毫秒精度的Unix时间戳生成文件key,同样属于顺序前缀:

    sample-bucket-02/1513160001245.log
    sample-bucket-02/1513160001722.log
    sample-bucket-02/1513160001836.log
    sample-bucket-02/1513160001956.log
    ...
    sample-bucket-02/1513160002153.log
    sample-bucket-02/1513160002556.log
    sample-bucket-02/1513160002859.log
    ...

    这种情况可以考虑通过反转时间戳前缀来避免文件key包含顺序前缀,反转后结果如下:

    sample-bucket-02/5421000613151.log
    sample-bucket-02/2271000613151.log
    sample-bucket-02/6381000613151.log
    sample-bucket-02/6591000613151.log
    ...
    sample-bucket-02/3512000613151.log
    sample-bucket-02/6552000613151.log
    sample-bucket-02/9582000613151.log
    ...

    由于文件key中的前3位数字代表毫秒时间,会有1000种取值。而第4位数字,每1秒钟就会改变一次。同理第5位数字每10秒钟就会改变一次。以此类推,反转文件key将极大地增强前缀的随机性,从而将负载压力均匀地分摊在各个分区上,避免出现性能瓶颈。

使用字节范围提取

当下载OSS中的大文件(大于100 MB)时,由于网络环境不稳定可能导致传输中断。如果您只需要下载文件的部分内容,而不是下载完整文件的情况下,可以使用HTTP Range请求获取文件的部分内容。请求方法说明如下:

Get /ObjectName HTTP/1.1
Host:examplebucket.oss-cn-hangzhou.aliyuncs.com
Date:Fri, 19 Jul 2024 17:27:45 GMT
Authorization:SignatureValue
Range:bytes=[$ByteRange]

根据HTTP协议规范,Range请求头允许客户端指定希望接收的数据片段有效区间位于0content-length - 1的范围内。关于通过HTTP Range请求分段获取OSS资源的更多示例,请参见如何通过HTTP Range请求分段获取OSS资源

使用OSS传输加速

当您需要实现Bucket远距离数据传输加速(例如从中国内地向非中国内地Bucket请求加速上传或下载文件),上传和下载GB、TB级大文件时,您可以开启传输加速。传输加速利用全球分布的云机房,将全球各地用户对Bucket的访问,经过智能路由解析至就近的接入点,使用优化后的网络及协议,为云存储的上传、下载提供端到端的加速方案。更多信息,请参见传输加速

对频繁访问的内容使用缓存

为提升OSS高频访问内容的访问速度,推荐使用CDN加速访问。CDN的工作原理是将静态内容复制至全球各地的边缘节点,让用户可以从最近的节点快速获取内容,从而大幅提升网站访问速度和稳定性。

具体而言,当用户请求OSS某个文件时,CDN首先检查边缘节点是否存在该文件。若不存在或文件已过期,则向源站OSS请求内容并复制至附近边缘节点。当源站OSS内容变更时,CDN自动更新边缘节点缓存,确保源站与CDN边缘节点内容同步。

借助以上方案,CDN可以有效减轻源站OSS负载,提高内容访问速度及稳定性,特别适用于全球用户广泛分布的企业。更多信息,请参见CDN加速访问

使用最新版本OSS SDK

OSS SDK为优化OSS性能的建议准则提供了内置支持。使用阿里云最新版本OSS SDK对于性能提升的帮助主要体现在以下几个方面:

  • 新特性的支持:新版SDK通常包含最新的功能和改进,能够利用OSS的新特性,例如最新的API、优化的算法和更高效的编码方式,从而提高性能。

  • 错误处理和重试机制:新版SDK通常包含更完善的错误处理和重试机制,能够自动处理常见的错误,例如HTTP 503错误,减少因网络问题导致的失败操作,提高成功率。

  • 传输管理:新版SDK会提供更高级别的传输管理功能,自动扩展连接并在适当的时候使用范围请求,实现高效的吞吐量。

  • 多线程支持:新版SDK通常支持多线程编程模型,可以并行处理多个请求,提高数据处理速度。

  • 内存管理优化:考虑到内存资源的有效利用,新版SDK在内存管理层面进行了深度优化,旨在减少不必要的内存开销,提升内存使用效率。

  • 兼容性增强:新版SDK致力于修复历史遗留问题,持续增强与各类第三方软件库及操作系统平台的兼容性。

如何获取阿里云最新版本OSS SDK,请参见SDK简介

在同一地域内中结合使用OSSECS

为了充分利用阿里云OSSECS的优势,推荐您在同一地域内部署您的ECS实例和OSS存储空间。这种部署策略能够显著减少数据传输的延迟时间,提升数据读取速度,从而增强应用的整体性能。 当您的ECS实例和OSS存储空间位于同一个地域时,通过内网Endpoint进行通信,可以免除内网流量费用。这意味着,在ECS实例与OSS之间传输大量数据时,无需额外支付高额的网络带宽费用,降低了总体成本。 要实现这一配置,请参见ECS实例通过OSS内网地址访问OSS资源

对时延敏感的应用程序进行超时重试

OSS针对管控类API,如GetService(ListBuckets)、PutBucket、GetBucketLifecycle等进行QPS限制。如果应用程序产生高请求速率,可能会收到HTTP 503减速响应。如果发生这类错误,建议您延迟几秒后进行重试。

单个阿里云账号的总QPS10,000,如果您需要更高的QPS,请联系技术支持。注意,在整体访问QPS未超过上述阈值的情况下,如果请求集中在特定分区,服务端也可能会因为超过单分区的服务能力而限流并返回503;如果请求前缀合理打散(参见OSS性能与扩展性最佳实践),OSS会自动扩展分区数量来支持更高QPS的访问,您只需要等待并重试即可。

当您发出大量不同大小的请求时(例如超过128 MB),建议您测量吞吐量,并重试最慢的5%请求。当您发出较小的请求时(例如小于512 KB),时延通常在数十毫秒以内。建议您在2秒后重试GETPUT操作。如果需要额外的重试,最好的做法是退出。例如,建议您在2秒后重试,然后等4秒后再次重试。

如果您的应用程序向OSS发出固定大小的请求,您期望每个请求的响应时间趋于一致。在这种情况下,推荐的策略是识别最慢的1%请求并重试。通常情况下,即使一次重试也能有效减少时延。

通过水平扩展和并行请求实现高吞吐量

OSS是一个超大的分布式系统。为了帮助您利用其规模,建议您将并行请求水平扩展到OSS服务终端节点,这种扩展方式有助于通过网络将负载分布在多个路径上。

对于高吞吐量传输,建议您在多个线程或多个实例中同时启动多个请求连接来并行上传和下载数据。对于某些应用程序,您可以通过在不同的线程或实例中同时启动多个请求来实现并行连接。扩展策略取决于您的应用程序和您访问的对象的结构。

当您要调整并发的请求数时,性能测量非常重要。建议从单个请求开始,测量当前的网络带宽以及其他资源的使用情况,从而识别瓶颈资源(即使用率最高的资源),以及可能的并发请求数。例如,如果一次处理一个请求导致CPU使用率为10%,则表明最多可以支持10个并发请求。

水平扩展存储连接

将请求分散在多个连接上是横向扩展性能的常见设计模式。当您构建高性能应用程序时,可将OSS作为一个大的分布式系统,而不是像传统存储服务器那样作为单个网络终端节点。您可以通过向OSS发送多个并发请求来实现最佳性能。将这些请求分散到不同的连接上,可以最大限度地利用阿里云OSS的可访问带宽。OSS对存储空间的连接数没有限制。

增加重试次数

鉴于阿里云OSS的规模较大,如果第一次请求速度较慢,您可以尝试发送重试请求。您可以通过OSS SDK配置超时和重试值,并根据您应用程序的容错要求进行调整。