Home

Awesome

s3-bucket-loader

This project originated out of a need to quickly import (and backup) a massive amount of files (hundreds of gigabytes) into an AWS S3 bucket, with the ultimate intent that this bucket be managed going forward via the S3 distributed file-system; yas3fs. Initial attempts at doing this a traditional way, (i.e. rsyncing or copying from source to destination) quickly became impractical due to the sheer amount of time that single-threaded, and even limited multi-threaded copiers would take.

s3-bucket-loader leverages a simple master/worker paradigm to get economies of scale for copying many files from sourceA to targetB. "sourceA" and "targetB" could be two S3 buckets, or a file-system to S3 bucket (via an S3 file-system abstraction like yas3fs or s3fs etc). Even though this is coded with S3 being the ultimate destination it could be used for other targets as well including other shared file-systems. The speed at which you can import a given file-set into S3 (through yas3fs in this case) is only limited on how much money you want to spend in worker hardware. For example this has been used to import and validate in S3 over 35k files (11gb total) in roughly 16 minutes; using 40 ec2 t2.medium instances as workers. In another scenario it was used to import and validate over 800k files totaling roughly 600gb in under 8 hours. This program has also been used to copy the previously imported buckets to secondary 'backup' buckets in under an hour.

Alt text

Alt text

How it works

This is a multi-threaded Java program that can be launched in two modes master or worker. The master is responsible for determining a table of contents (TOC) (i.e. file paths) which are candidates for WRITE to the destination and subsequently VALIDATED. The master node streams these TOC events over an SQS queue which is consumed to by one or more workers. Each worker must also have access to the source from which the TOC was generated from. The source data could be the same physical set of files, an S3 bucket, a copy of them or whatever... it really does not matter, but they just need to be accessible from each worker (i.e. via a SAN/NAS/NFS share, source S3 bucket etc). The worker then copies each item (in the case of files via rsync (or cp) to S3 via an S3 FS abstraction) or via an S3 key-copy. It uses rsync to preserve uid/gid information which is important for the ultimate consumer; and ensured preservation if written to S3 via S3 file-system abstractions like yas3fs. It is also important to note that each worker leverages N threads to increase parallelism and maximize the throughput to S3. The more workers you have the faster it goes.

Please see s3BucketLoader.sample.properties for more details on configuration options and how-to-use etc

Flow overview

  1. End user starts the Master which creates the SNS control-channel and SQS TOC queue

  2. The Master (optionally) launches N worker nodes on EC2

  3. As each worker node initializes its subscribes to the control-channel and publishes that it is INITIALIZED

  4. Once the master sees all of its workers in INITIALIZED state, the master changes the state to WRITE

  5. The master begins creating the TOC (consisting of path, isDirectory and size), and sends a SQS message for each file to the TOC queue. Again the 'source' for these TOC entries could be a path realized via the file-system, or a file-like key name in a source S3 bucket.

  6. Workers begin consuming TOC messages off the queue and execute their TOCPayloadHandler, which might do a S3 key-copy or rsyncs (or cp) from the source -> destination through an S3 file-system abstraction. As workers are consuming they periodically send CURRENT SUMMARY updates to the master. If failfast is configured and any failures are detected the master can switch the cluster to ERROR_REPORT mode immediately (see below). Depending on the handler, they can also do chowns, chmods etc.

  7. When workers are complete, they publish their WRITE SUMMARY and go into an IDLE state

  8. Master receives all WRITE SUMMARYs from the workers

  1. In VALIDATE state, all workers consume TOC file paths from the SQS queue and attempt to verify the file exists and its sizes matches the expected TOC size (locally and/or s3 object metat-data calls). When complete they go into IDLE state and publish their VALIDATE SUMMARY

  2. After receiving all VALIDATE SUMMARYs from the workers

  1. In ERROR REPORT state, workers summarize and publish their errors from either state WRITE/VALIDATE, the master aggregates them and reports them to the master log file for analysis. All workers are then shutdown.

  2. At any stage, issuing a control-C on the master triggers a shutdown of the entire cluster, including ec2 worker termination if configured in the properties file

How to run

java -jar -DisMaster=true|false -Ds3BucketLoaderHome=/some/dir -DconfigFilePath=s3BucketLoader.properties s3-bucket-loader-0.0.1-SNAPSHOT.jar

Enjoy.