На прошлой неделе AWS выпустила новую функцию, позволяющую экспортировать полную таблицу Dynamo несколькими щелчками мыши, но также стоит знать, как наполнить таблицу данными любого масштаба.

Больше никто не будет страдать при настройке процесса полного экспорта таблицы DynamoDB в S3.

Однако этого нельзя сказать о тех, кто хочет импортировать данные в таблицу Dynamo. Особенно много данных и быстро.

Необходимость в быстром массовом импорте может возникнуть, когда записи в таблице повреждены, и самый простой способ исправить их - выполнить полное удаление и воссоздание таблицы. Или при потоковой передаче данных в таблицу может быть полезно запускать еженощное пакетное «сверточное» задание для исправления любых внутридневных аномалий, которые могли произойти.

Сокращение времени до завершения для этих типов заданий с более чем часа до менее чем минуты дает вам больше уверенности в состоянии ваших данных в любой момент времени. И он обеспечивает более стабильную основу для создания приложений с низким уровнем скрытой активности на основе ваших данных.

Простой способ писать

Допустим, у нас есть данные в корзине S3 в точке A, и мы хотим переместить их в таблицу Dynamo в точке B… как это сделать?

Что ж, самый простой подход - написать небольшой сценарий, который считывает файл в объект DataFrame, просматривает строки этого объекта, а затем выполняет dynamo.Table().batch_writer().put_item() операцию для вставки элементов в таблицу.

Запуск этого сценария в DataFrame со строкой 500 КБ приводит к следующей производительности записи:

Как видите, количество записей в секунду (Вт / с) в таблицу ограничено примерно 650 Вт / с. Amazon указывает, что истинный предел однопроцессной записи в Dynamo составляет 1000 Вт / с, но из-за сетевых и других накладных расходов наблюдаемое значение ниже (выполняется локально с моего ноутбука).

Для 500 000 записей вставка всех записей в таблицу занимает около 15 минут. В зависимости от вашего варианта использования это может быть приемлемо. Но для массовой вставки больших наборов данных - скажем, 100 миллионов строк (!) - очевидно, что повышение скорости записи было бы полезным.

Можем ли мы сделать лучше?

Превышение предельной скорости динамо

Очевидно, что для повышения производительности записи в таблицу должно быть записано более одного процесса. Так как же сделать так, чтобы несколько процессов могли писать параллельно?

Самый элегантный способ, который я нашел для этого, - это вызвать несколько экземпляров модуля записи лямбда-функций одновременно. Каждый из них берет часть набора данных и параллельно записывает его в таблицу Dynamo.

Это работает путем установки лямбда-функции для запуска очереди SQS. Это означает, что если сообщение помещается в очередь, функция Lambda вызовет и выполнит свой код, приняв значение сообщения SQS в качестве входного параметра функции.

Чтобы пойти дальше - если такая лямбда должна содержать код, как в simple_dynamo_write.py snippet выше, а сообщение, помещенное в очередь, является указателем пути к файлу S3 на данные, которые мы хотим записать, тогда должно быть ясно, как эти данные сделают это путь в Динамо!

Каждый экземпляр Lambda будет записывать в таблицу со скоростью от 750 до 1000 Вт / с, поэтому, как только мы получим несколько операций одновременно, мы сможем достичь гораздо более высокой скорости записи!

Уловка состоит в том, чтобы разделить и организовать данные таким образом, чтобы Lambda могла эффективно их обрабатывать без ошибок. Существуют установленные AWS ограничения на количество Lambda, которые могут быть вызваны одновременно (1000), как долго один вызов Lambda может выполняться до выключения (15 минут) и сколько записей в секунду может выполнять одна таблица Dynamo. ручка (40,000).

Всегда полезно знать соответствующие квоты при работе с сервисом, и в целом AWS хорошо документирует и делает эту информацию доступной.

Помня об этих ограничениях, должно быть ясно, что при полном распараллеливании мы не можем распределить набор данных более чем на 1000 сообщений SQS - в противном случае мы достигнем предела в 1000 одновременных вызовов лямбда-выражения.

Каждый файл также не может быть слишком большим, иначе лямбда-функциям потребуется более 15 минут, чтобы записать его в таблицу (напомним, что ранее для записи файла с 500 000 строками потребовалось около 15 минут). Для Lambda было бы нехорошо отключать промежуточный файл, поскольку не было бы возможности гарантировать, что все строки будут записаны без повторной обработки всего файла.

Чтобы контролировать все эти факторы, можно создать до 40 сообщений SQS, состоящих из разделенных запятыми строк путей к файлам S3 данных.

Например, если у нас есть 3 файла в S3 для записи в Dynamo, мы могли бы создать сообщение SQS, например:

's3://bucket/file1.csv,s3://bucket/file2.csv,s3://bucket/file3.csv'

С этим сообщением в качестве входных данных лямбда делает следующее:

  1. Удалите последний путь к файлу из входной строки.
  2. Запишите данные этого файла в таблицу Dynamo.
  3. Создайте новое сообщение в очереди SQS, которое запускается само, когда остаются только необработанные файлы.

Таким образом, после записи одного файла новое созданное сообщение SQS будет выглядеть, как показано ниже, и, что очень важно, новый экземпляр функции Lambda почти сразу же будет вызван, чтобы начать обработку file2.

's3://bucket/file1.csv,s3://bucket/file2.csv'

И как только file2 будет обработан, новое сообщение SQS помещается в очередь:

's3://bucket/file1.csv'

И после того, как file1 будет записан, больше не будут генерироваться сообщения очереди, больше не будут вызываться лямбда-выражения, и в таблице Dynamo больше нет данных!

Чтобы дать более наглядное представление об этой рекурсивной стратегии, вот пример кода лямбда-функции:

Теперь вместо графика ограниченных показателей емкости записи вы увидите более захватывающие визуальные эффекты, подобные этой!

Заключение

С помощью этой архитектуры мы можем достичь скорости записи в секунду до 40 КБ в Dynamo, поскольку до 40 процессов могут работать параллельно, каждый записывая со скоростью 1 КБ строк в секунду.

В то время как раньше набор данных из 100 миллионов строк занимал 40 часов при 1000 Вт / с, при увеличении скорости мы можем импортировать полный набор данных всего за 40 минут! (Кстати, ограничение максимальной скорости записи в 40 КБ для таблицы Dynamo просто установлено AWS по умолчанию и может быть увеличено по запросу).

При работе с Dynamo в качестве серверной части для нескольких приложений, интенсивно использующих данные, я обнаружил, что чрезвычайно полезно иметь возможность таким образом быстро обновлять полный набор данных. В ситуациях, когда определенные строки могли быть повреждены или неправильно обработаны, более хирургические подходы к исправлению данных могут быть подвержены ошибкам и требуют много времени и не рекомендуются.

Наконец, есть еще пара факторов, которые мне не удалось осветить в статье, например, идеальная обработка режима Dynamo Capacity и влияние на связанные процессы, такие как потоки Dynamo.

Если это интересно, спросите в комментариях ниже или напишите в Twitter.

Спасибо Райану Келли и Майклу Петришину за вдохновение для этой статьи.

Ещё от Paul Singman