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

Выбор между Spring Пакетный шаг, Tasklet или Chunks

У меня есть прямое требование, в котором мне нужно прочитать список элементов (из БД) и нужно обработать элементы и после его обработки он должен быть обновлен в БД.

Я думаю использовать Spring пакетные чанки с устройством чтения, процессором и писателем. Мой читатель вернет один элемент за раз из списка и отправит его процессору, и как только обработка закончится, он вернется в Writer, где он обновит DB

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

Здесь я предвижу несколько проблем.

  • Количество элементов для обработки может быть больше. Может быть в 10 000 или даже больше.
  • В процессоре требуется некоторый логический расчет. следовательно, обрабатывает 1 элемент за раз. не уверен в производительности, даже если он многопоточен с 10 потоками.
  • Writer может обновлять результаты в БД для этого обработанного элемента. Не знаете, как выполнять пакетные обновления, потому что он всегда имеет только один обработанный и готовый элемент.

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

Пожалуйста, бросьте некоторые огни на этот дизайн для лучшей производительности.

Спасибо,

4b9b3361

Ответ 1

Spring Пакет - идеальный инструмент для того, чтобы делать то, что вам нужно.

Шаг, ориентированный на блок, позволяет настроить, сколько элементов вы хотите читать/обрабатывать/записывать с помощью свойства commit-interval.

        <batch:step id="step1" next="step2">
        <batch:tasklet transaction-manager="transactionManager" start-limit="100">
            <batch:chunk reader="myReader" processor="myProcessor" writer="MyWriter" commit-interval="800" />
            <batch:listeners>
                <batch:listener ref="myListener" />
            </batch:listeners>
        </batch:tasklet>
    </batch:step>

Скажем, ваш читатель будет вызывать оператор SELECT, который возвращает 10 000 записей. И вы установите интервал фиксации = 500.

MyReader будет вызывать метод read() 500 раз. Скажем, что на самом деле реализация читателя может фактически удалить элементы из набора результатов. Для каждого вызова read() он также вызывается методом process() MyProcessor.

Но он не будет вызывать метод write() MyWriter до тех пор, пока не будет достигнут интервал фиксации.

Если вы посмотрите на определение интерфейса ItemWriter:

public interface ItemWriter<T> {

/**
 * Process the supplied data element. Will not be called with any null items
 * in normal operation.
 * 
 * @throws Exception if there are errors. The framework will catch the
 * exception and convert or rethrow it as appropriate.
 */
void write(List<? extends T> items) throws Exception;

}

Вы видите, что запись получает список элементов. Этот список будет размером вашего интервала фиксации (или меньше, если конец будет достигнут)

И btw, 10 000 записей ничего. Вы можете рассматривать многопоточность, если вам приходится иметь дело с миллионами записей. Но даже в этом случае достаточно просто поиграть со сладким пятном значения фиксации-интервала.

Надеюсь, что это поможет