Невероятно медленная запись в Amazon DynamoDB (PHP API)

Этот вопрос уже публиковался на форумах AWS, но до сих пор остается без ответа https://forums.aws.amazon.com/thread.jspa?threadID=94589

Я пытаюсь выполнить первоначальную загрузку длинного списка коротких элементов (около 120 миллионов из них), чтобы получить их позже с помощью уникального ключа, и это кажется идеальным случаем для DynamoDb.

Однако моя текущая скорость записи очень низкая (примерно 8-9 секунд на 100 записей), что делает первоначальную загрузку практически невозможной (при текущем темпе это займет около 3 месяцев).

Я читал форумы AWS в поисках ответа и уже пробовал следующие вещи:

  1. Я переключился с одиночных вызовов «put_item» на пакетную запись 25 элементов (рекомендуемый максимальный размер пакетной записи), и каждый из моих элементов меньше 1 КБ (что также рекомендуется). Очень типично, что даже 25 моих элементов также имеют размер менее 1 КБ, но это не гарантируется (и в любом случае не должно иметь значения, поскольку я понимаю, что для DynamoDB важен только размер одного элемента).

  2. Я использую недавно введенный регион ЕС (я нахожусь в Великобритании), указав его точку входа напрямую, вызвав set_region('dynamodb.eu-west-1.amazonaws.com'), поскольку в PHP, по-видимому, нет другого способа сделать это. API. Консоль AWS показывает, что таблица находится в нужном регионе, так что все работает.

  3. Я отключил SSL, вызвав disable_ssl() (получив 1 секунду на 100 записей).

Тем не менее, тестовый набор из 100 элементов (4 вызова пакетной записи для 25 элементов) никогда не занимает меньше 8 секунд для индексации. Каждый запрос на пакетную запись занимает около 2 секунд, поэтому первый запрос не является мгновенным, а последующие запросы выполняются медленно.

Пропускная способность, предоставленная моей таблицей, составляет 100 единиц записи и 100 единиц чтения, чего должно быть достаточно (на всякий случай также пробовал более высокие пределы, безрезультатно).

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

Я обнаружил, что некоторые люди изменяют заголовки cURL (в частности, «Ожидание:») в API, чтобы ускорить запросы, но я не думаю, что это правильный способ, а также API был обновлен с тех пор, как этот совет был опубликован.

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

Я застрял сейчас - есть ли что-нибудь еще, что я могу попробовать? Пожалуйста, не стесняйтесь запрашивать дополнительную информацию, если я не предоставил достаточно.

Есть и другие недавние темы, по-видимому, по той же проблеме, здесь (нет ответ пока что).

Этот сервис должен быть сверхбыстрым, поэтому я действительно озадачен этой проблемой в самом начале.


person Yuriy    schedule 21.05.2012    source источник
comment
Похоже, вам нужна реляционная база данных, такая как SQL Server. Просто SqlBulkCopy данные. SQL Server — это веб-масштаб, если вы спрашиваете.   -  person ta.speot.is    schedule 21.05.2012
comment
Мне здесь не нужна реляционная БД (это плоский индекс без фактических отношений), но да, я думаю вернуться к mySQL или Solr, если у меня нет других вариантов. Тем не менее, пока я все еще стремлюсь понять, что не так с этим подходом.   -  person Yuriy    schedule 21.05.2012
comment
На ваше сообщение на форуме ответили: forums.aws.amazon.com/ thread.jspa?messageID=365597#365597   -  person Jeremy Lindblom    schedule 18.07.2012
comment
Спасибо, попробую еще раз, если возникнет необходимость.   -  person Yuriy    schedule 18.07.2012


Ответы (3)


Если вы загружаете со своего локального компьютера, на скорость будут влиять все виды трафика / брандмауэра и т. д. между вами и серверами. Если я вызываю DynamoDB, каждый запрос занимает 0,3 секунды просто из-за времени, необходимого для поездки в/из Австралии.

Я бы предложил создать себе экземпляр (сервер) EC2 с PHP, загрузить скрипт и все файлы на сервер EC2 в виде блока, а затем сделать дамп оттуда. Сервер EC2 должен иметь невероятную скорость по сравнению с сервером DynamoDB.

Если вы не уверены в настройке EC2 с LAMP самостоятельно, у них есть новый сервис «Elastic Beanstalk», который может сделать все это за вас. Когда вы завершите загрузку, просто сожгите сервер — и, надеюсь, вы сможете сделать все это в рамках их ценовой структуры «бесплатного уровня» :)

Не решает долгосрочные проблемы с подключением, но сокращает трехмесячную загрузку!

person Robbie    schedule 21.05.2012
comment
Спасибо за Ваш ответ. Я не пробовал Beanstalk, но вместо этого пытался использовать Elastic MapReduce - здесь все еще есть проблема. Я создал еще один вопрос для: stackoverflow.com/questions/10683136/ - person Yuriy; 21.05.2012
comment
Как вы упомянули, даже из Австралии для вас все еще меньше 0,5 секунды, поэтому для меня не может быть 2 секунд из Лондона в Ирландию. Связь у нас очень хорошая, пока я это исключаю. - person Yuriy; 21.05.2012
comment
2 секунды безумно медленно, но это может быть просто, например, брандмауэр на сервере, выполняющий некоторые проверки, или брандмауэр на маршрутизаторе, выполняющий другие проверки. (Или, если быть циничным, это способ для Amzon подтолкнуть вас к EC2, возможно?!) Как я уже сказал, это не долгосрочное решение, просто что-то, что нужно для того, чтобы выполнить загрузку. Если вы хотите сохранить его локально, почему бы не посмотреть на Cassandra или Mongo? Но если вы используете Amazon и платите, просто переместите туда сервер - они будут довольны :) - person Robbie; 21.05.2012

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

person Chris Seline    schedule 01.06.2012

Я успешно использовал php sdk, используя пакетный метод в классе AmazonDynamoDB. Мне удалось запустить около 50 элементов в секунду из экземпляра EC2. Метод работает, ставя запросы в очередь до тех пор, пока вы не вызовете метод отправки, после чего он выполняет несколько одновременных запросов с помощью Curl. Вот несколько хороших ссылок:

http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LoadData_PHP.html

http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LowLevelPHPItemOperationsExample.html

Я думаю, вы также можете использовать HIVE sql с помощью Elastic Map Reduce для массовой загрузки данных из файла CSV. EMR может использовать несколько компьютеров для распределения рабочей нагрузки и достижения высокого параллелизма.

person Jonathan    schedule 02.07.2012
comment
Спасибо, Джонатан, но я переписал функциональность, чтобы использовать локальный индекс. Что касается HIVE, в нем также есть проблема, когда речь идет о DynamoDB, что было подтверждено Amazon (см. мой другой вопрос и мой ответ, опубликованный самостоятельно): stackoverflow.com/questions/10683136/ - person Yuriy; 02.07.2012