Подтвердить что ты не робот

Spring Пакет: какая реализация ItemReader для высокой и низкой латентности

Случай использования: Прочитайте 10 миллионов строк [10 столбцов] из базы данных и напишите в файл (формат csv).

  • Будет ли предложена реализация ItemReader среди JdbcCursorItemReader и JdbcPagingItemReader? В чем причина?

  • Что было бы лучше (быстро) в приведенном выше примере использования?

  • Будет ли выбор отличаться в случае однопроцессного или многопроцессорного подхода?

  • В случае многопоточного подхода с использованием TaskExecutor, какой из них будет лучше и проще?

4b9b3361

Ответ 1

Чтобы обрабатывать такие данные, вы, вероятно, захотите распараллелить его, если это возможно (единственное, что предотвратило бы это, было бы, если выходной файл должен был сохранить заказ от ввода). Предполагая, что вы собираетесь распараллелить свою обработку, вы остаетесь с двумя основными параметрами для этого типа использования (из того, что вы предоставили):

  • Многопоточный шаг - это обработает кусок на поток до завершения. Это позволяет легко распараллеливать (просто добавляя TaskExecutor к определению шага). При этом вы теряете возможность повторного запуска из коробки, потому что вам нужно будет отключить постоянство состояния для любого из упомянутых вами ItemReaders (есть способы обойти это, помещая записи в базу данных как обработанные и т.д.).
  • Разделение - это разбивает ваши входные данные на разделы, которые обрабатываются параллельными экземплярами (конфигурация master/slave). Разделы могут выполняться локально через потоки (через TaskExecutor) или удаленно через удаленное разбиение. В любом случае вы получаете возможность перезапуска (каждый шаг обрабатывает свои собственные данные, чтобы не было перехода на состояние из раздела в раздел) с помощью парализации.

Я поговорил о обработке данных параллельно с Spring Batch. В частности, примером, который я представляю, является удаленное многосетевое задание. Вы можете посмотреть его здесь: https://www.youtube.com/watch?v=CYTj5YT7CZU

К вашим конкретным вопросам:

  • Какая реализация ItemReader среди JdbcCursorItemReader и JdbcPagingItemReader будет предложена? В чем причина?. Любой из этих двух параметров может быть настроен для удовлетворения многих потребностей в производительности. Это действительно зависит от используемой базы данных, доступных вариантов драйвера, а также от моделей обработки, которые вы можете поддерживать. Еще одно соображение: нужна ли перезагрузка?
  • Что будет лучше выполнять (быстро) в приведенном выше примере использования?. Опять же, это зависит от выбранной вами модели обработки.
  • Будет ли выбор отличаться в случае однопроцессорного или многопроцессорного подхода?. Это касается того, как вы управляете заданиями больше, чем то, что может обрабатывать пакет Spring. Вопрос в том, хотите ли вы управлять секционированием, внешним по отношению к заданию (передавая описание данных заданию в качестве параметров), или вы хотите, чтобы задание управляло им (через разбиение на разделы).
  • В случае многопоточного подхода с использованием TaskExecutor, какой из них будет лучше и проще?. Я не буду отрицать, что удаленное разделение добавляет уровень сложности, который локальное разбиение на разделы и многопоточные шаги Не знаю.

Я бы начал с определения базового шага. Затем попробуйте многопоточный шаг. Если это не соответствует вашим потребностям, перейдите к локальному разделению и, наконец, удалите разделы, если необходимо. Имейте в виду, что Spring Batch был разработан так, чтобы сделать эту прогрессию максимально безболезненной. Вы можете перейти от обычного шага к многопоточному шагу с помощью только обновлений конфигурации. Чтобы перейти к разделению, вам нужно добавить один новый класс (реализация Partitioner) и некоторые обновления конфигурации.

Последнее замечание. В большинстве случаев речь идет о параллелизации обработки этих данных. Spring Batch FlatFileItemWriter не потокобезопасен. Лучше всего было бы написать несколько файлов параллельно, а затем объединить их позже, если скорость будет вашей проблемой номер один.

Ответ 2

Вы должны прокомментировать это, чтобы сделать выбор. В простом JDBC я бы начал с чего-то, что:

  • готовит заявления с ResultSet.TYPE_FORWARD_ONLY и ResultSet.CONCUR_READ_ONLY. Несколько драйверов JDBC "имитируют" курсоры на стороне клиента, если вы не используете эти два, и для больших наборов результатов вы не хотите этого, поскольку это, вероятно, приведет вас к OutOfMemoryError, потому что ваш драйвер JDBC буферизует весь набор данных в памяти. Используя эти параметры, вы увеличиваете вероятность того, что вы получите курсоры на стороне сервера и получите "по потоку" результаты, которые вы хотите для больших наборов результатов. Обратите внимание, что некоторые драйверы JDBC всегда "имитируют" курсоры на стороне клиента, поэтому этот совет может оказаться бесполезным для вашей конкретной СУБД.
  • установите разумный размер выборки, чтобы свести к минимуму влияние сетевых обращений. 50-100 часто является хорошим стартовым значением для профилирования. Поскольку размер выборки является подсказкой, это может также оказаться бесполезным для вашей конкретной СУБД.

JdbcCursorItemReader, похоже, охватывает обе вещи, но, как сказано ранее, они не гарантируют лучшую производительность во всех СУБД, поэтому я бы начал с что, а затем, если производительность неадекватна, попробуйте JdbcPagingItemReader.

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

В любом случае профиль.