发布于: Jun 28, 2022

本文将会介绍 Amazon S3 中数据的复制和传输应注意到哪些原则以及关键任务的设计。

有了存储桶中所有的对象清单,接下来,我们就看看如何设计传输任务。设计传输任务的原则如下:

  • 如果网络条件非常良好,比如同区域的不同存储桶之间,按照作者的测试,复制带宽平均可以达到xxMB/s,如此可以直接利用S3 cp命令
  • 尽可能将单进程的复制任务分解成多个子任务并发执行,任务分解后进入到Amazon SQS队列,这样将任务分解和任务执行进行解耦
  • 如果网络条件非常一般,比如平均在10KB/s并且网络抖动大的情况下,对于超过一定大小的文件需要切割成小文件,组成子任务并发执行

传输任务分解算法的设计,涉及到几个关键参数:

  • max_task_size_mb:单个任务的对象总大小上限,比如最大大小限制在 100MB,那么单个任务最多有 100MB 的对象列表,或者该任务就一个对象,该对象本身大小就超过了 100MB
  • max_task_objects:单个任务的对象数量上限,比如数量上限为 50,那么单个任务中最多有 50 个对象需要传输
  • multipart_threshold 及 multipart_chunksize:对象太大时,需要分割成多个小对象传输任务,那么多大的对象需要进行分解?分段的单位大小是多少?比如阈值是 10MB,单位大小是 2MB,那么大于 10MB 的对象都需要再分解成 2MB 的多个子对象并发续传

传输任务在设计时分成两大类,一种是本身对象就是小文件,我们按照max_task_size_mb 和 max_task_objects 进行分组,即每个任务总数据量大小不会超过 max_task_size_mb,而且对象数量也不超过 max_task_objects ;这些任务我们会发送到自动创建的 S3Task_NormalQueue 开头的 SQS 队列中,每个队列的消息数量上限本文设为 80000 条;另外一类是,对象大小超过 multipart_threshold 限制的,我们会进一步把该对象分解成  multipart_chunksize 大小的独立对象,同样按照 max_task_size_mb 和 max_task_objects 的算法进行分组,但这些任务会保存到自动创建的以 S3Task_BigSizeQueue 开头的队列中。

另外遵循 Amazon SQS 操作的最佳实践,我们分别为这两类任务队列设定了同样的死信队列,当消息被读取10次而没被处理成功的会自动转移到 S3Task_DeadQueue 进行存储和后续处理。

当任务队列产生之后,接下来,就到了如何高效执行如何多的传输任务的阶段,很多网络和客观条件的限制,我们都放到了如何分解传输任务的算法里面进行了实现,在执行数据传输任务环节,逻辑非常简单:

  • 读取一条 SQS 任务
  • 根据任务中的具体对象,每个对象利用独立线程进行复制或者下载再上传
  • 只有该任务中所有的对象都传输成功,才把该任务消息从 SQS 队列中删除

同区域不同 S3 存储桶之间数据复制,由于网络条件较好,IAM 权限简单,可以尽量利用 boto3的copy-object 方法直接利用S3服务本身能力,进行快速数据复制,该方法数据无需经过命令执行的机器中转。因此在任务分解环节,multipart_threshold 的值需要设置一个比较大而且合理的值,避免大文件被分片之后,需要先下载后上传,这样会消耗更多的流量。

海外不同区域的 S3 存储桶之间复制,和同区域的不同存储桶复制场景类似,但由于跨区域传输,网络状况取决于两个区域的位置及它们之间的互联网状况。

该情况最复杂,Amazon Web Services 海外和国内是独立的区域,需要不同的账号权限体系,因此,对象需要先进行下载再上传,这样就需要占用执行命令的机器的内存和网络带宽;

  • 在任务分解时,需要尽量把大对象分解成小的片段比如 2MB 或者 1MB 的大小以提高单次数据传输的成功率。
  • 在任务执行时,需要尽量并发,以单任务小带宽累积成可以接受的总体平均传输速度,并充分 Amazon Web Services 出口带宽的优势 

相关文章