Хранение данных в памяти, дизайнерский подход - PullRequest
1 голос
/ 25 августа 2011

У меня проблема с тем, что мне нужно обрабатывать некоторые файлы размером от нескольких килобайт до 1 ГБ макс.Вариант использования таков, что ввод осуществляется в каком-то плоском формате файла, где данные хранятся в одной строке, например, в некоторых инструкциях по оплате.Заявка должна пройти каждую платежную инструкцию и сформировать группы на основе некоторой логики группировки.В конце группы должны быть преобразованы в другой формат (ISO 20022 xml), с помощью которого будет выполняться обработка платежей.

Текущий дизайн таков, что у нас есть две таблицы, в которых данные критериев группировки хранятся в однойтаблица и отдельная платежная инструкция хранятся в другой таблице (отношение «один ко многим» из группы «Таблица» к таблице «Платежная инструкция»).И на шаге 1: как и когда мы просматриваем плоский файл, мы идентифицируем группу, к которой он принадлежит, и записываем в базу данных (Bult commit btw).

На шаге 2: при групповой обработке группы читаются одна за другой, формируют выходной xml и отправляются по назначению.

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

Я думаю о подходе, при котором я могу сохранить HashTable (Google Guava ( MapMaker )) вид кэширования, размер которого я могу указать, и как только кеш достигнет верхнего предела, я могу записать их в таблицы базы данных (переплетая аспект в кеше).

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

Каково ваше мнение об этом подходе к проектированию (Это еще одна ошибка или что-то, что я могу сделать практическими в то же время стабильный и может масштабироваться).

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

Не могли бы вы дать несколько советов?

Спасибо

Ответы [ 4 ]

2 голосов
/ 25 августа 2011

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

1 голос
/ 25 августа 2011

Нет, вероятно, не стоит затрачивать усилия на кэширование и переходить на (временную?) Таблицу, главным образом потому, что она будет сложной, увеличивая риски и затраты.

Однако существуетпотенциал для ускорения первоначальной сортировки по группам, и нет ничего, что говорит о том, что вам нужно использовать RDMS для этого.

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

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

Google для постоянных коллекций или nosql для java;Вот некоторые из них, которые я знаю:

http://jdbm.sourceforge.net/ может использоваться как «постоянная / масштабируемая» карта.Может быть http://code.google.com/p/pcollections/ (но я сам не пробовал)

Вы сможете найти больше;попробуйте и проверьте: -)

1 голос
/ 25 августа 2011

Вы смотрели на Spring Batch , который поддерживает обработку плоских файлов, разбив их по значениям полей и результатам параллельной обработки.В Spring jdbc вы все еще можете сохранять критерии группировки в базе данных, но просто обрабатывать файл без использования промежуточной таблицы.

1 голос
/ 25 августа 2011

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

Во-вторых, вы рассматривали вопрос об использовании отображенных в память файлов через MappedByteBuffer?Если вы имеете дело с огромными объектами, которые превышают пространство кучи Java и готовы приложить немного усилий, вы можете подумать о том, чтобы спроектировать объекты так, чтобы они сохранялись в файлах с отображением в памяти.Вы можете сделать это, создав класс-оболочку, которая по сути является тонкой оболочкой, которая преобразует запросы в операции в отображенном байтовом буфере.Например, если вы хотите сохранить список запросов, вы можете сделать это, создав объект, который использует MappedByteBuffer для хранения списка строк на диске.Например, строки могут храниться разделенными символами новой строки или нулевыми терминаторами.Затем вы могли бы перебирать строки, проходя через байты файла и повторно их гидрируя.Преимущество этого подхода состоит в том, что он снимает сложность кэширования с операционной системой, которая десятилетиями настраивалась на производительность (при условии, что вы используете основную ОС!) Для эффективного решения этого случая.Однажды я работал над проектом на Java, где я создал фреймворк для автоматизации этого, и во многих случаях он работал замечательно.Это определенно немного трудоемкая кривая обучения, но как только она заработает, вы сможете хранить в кучи Java больше данных, чем могли бы раньше.По сути, это делает то, что вы предложили выше, за исключением того, что он торгует с некоторой предварительной сложностью реализации, чтобы позволить ОС обрабатывать все кэширование.

В-третьих, есть ли способ объединить проходы (1) и (2))?То есть, вы могли бы сгенерировать XML-файл одновременно с базой данных?Из вашего описания я предполагаю, что проблема в том, что вы не можете сгенерировать XML, пока все записи не будут готовы.Однако вам может потребоваться создать на диске несколько разных файлов, каждый из которых хранит объекты одного типа в сериализованном формате XML, и в конце прохода можно использовать стандартную утилиту командной строки, такую ​​как cat, чтобы объединить их все вместе.,Поскольку это можно сделать, просто выполнив массовую байтовую конкатенацию, а не анализируя содержимое базы данных, это может быть намного быстрее (и проще в реализации), чем предложенный вами подход.Если файлы все еще горячие в кэше ОС (что, вероятно, и есть, поскольку вы только что писали в них), это может быть на самом деле быстрее, чем ваш текущий подход.

В-четвертых, если вам важна производительность,Вы рассматривали распараллеливание вашего кода?Учитывая потрясающе огромные файлы для обработки, вы можете разбить этот файл на множество небольших областей.Каждая задача будет затем читать из файла и распределять части в соответствующие выходные файлы.После этого вы можете получить окончательный процесс для объединения идентичных файлов и создания общего XML-отчета.Поскольку я предполагаю, что это в основном операция ввода-вывода (в основном это просто чтение файлов), это может дать вам гораздо большую выигрыш в производительности, чем однопоточный подход, который пытается сохранить все в памяти.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...