如果您在上传大量文件(Object)时,在命名上使用了顺序前缀(如时间戳或字母顺序),可能会出现大量文件索引集中存储于存储空间(Bucket)中的某个特定分区的情况。此时如果您的请求次数过多,会导致请求速率下降。出现此类问题时,建议您为文件名称增加随机前缀。

背景信息

OSS按照文件名UTF-8编码的顺序对用户数据进行自动分区,从而能够处理海量文件并承载高速率的客户请求。但是,OSS限制了在顺序读写模式下,每秒请求数QPS的值为2,000。如果您在上传大量文件时,在命名上使用了顺序前缀(如时间戳或字母顺序),可能会导致大量文件索引集中存储于某个特定分区。关于单个账号QPS的更多信息,请参见使用限制

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

  • 该分区成为热点分区,导致分区的I/O能力被耗尽,或被系统自动限制请求速率。
  • 热点分区的存在会触发系统进行持续的分区数据再均衡,这个过程可能会延长请求处理时间。
    说明 分区数据再均衡是依赖于对当前系统状态、处理能力等信息做各种智能分析后进行的,并不是某个固定的拆分规则。所以分区数据再均衡后,使用了顺序前缀的文件可能还会处于高热点的分区当中。

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

解决方案

以下提供了两个将顺序前缀改为随机性前缀的方法。

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

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

    sample-bucket-01/2017-11-11/customer-1/file1
    sample-bucket-01/2017-11-11/customer-2/file2
    sample-bucket-01/2017-11-11/customer-3/file3
    ...
    sample-bucket-01/2017-11-12/customer-2/file4
    sample-bucket-01/2017-11-12/customer-5/file5
    sample-bucket-01/2017-11-12/customer-7/file6
    ...

    针对这种情况,您可以对客户ID计算哈希(即MD5),并取若干字符的哈希前缀作为文件名的前缀。假如取4个字符的哈希前缀,结果如下:

    sample-bucket-01/9b11/2017-11-11/customer-1/file1
    sample-bucket-01/9fc2/2017-11-11/customer-2/file2
    sample-bucket-01/d1b3/2017-11-11/customer-3/file3
    ...
    sample-bucket-01/9fc2/2017-11-12/customer-2/file4
    sample-bucket-01/f1ed/2017-11-12/customer-5/file5
    sample-bucket-01/0ddc/2017-11-12/customer-7/file6
    ...

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

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

  • 反转文件名

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

    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
    ...

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

    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
    ...

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