Быстрая запись данных в удаленную базу данных - PullRequest
0 голосов
/ 22 марта 2012

У меня есть приложение, которое будет генерировать 5-10 новых записей базы данных на одном хосте каждую секунду.

Записи не нуждаются в каких-либо проверках.Они просто должны быть записаны в удаленной базе данных.

Я использую Java для клиентского приложения.

База данных находится за сервером.

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

Отправка данных не должна завершиться сбоем.Моему приложению не нужен ответ от сервера, но оно должно быть на 100% безопасным, чтобы оно поступало на сервер правильно (что должно быть гарантировано, например, при использовании http-соединения по URL (TCP) ...?).

Я подумал о нескольких подходах для этого:

  • Запустите код отправки данных в отдельном потоке.

  • Сохраните данныетолько в памяти и отправка в базу данных после определенного количества.

  • Сохранение данных в локальной базе данных и отправка / извлечение сервером по запросу.

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

Ответы [ 4 ]

2 голосов
/ 22 марта 2012

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

На моем компьютере с использованием HornetQ , для создания и отправки короткого текстового сообщения в длительную очередь требуется ~ 1 мс.Это достаточно быстро, чтобы вы могли сделать это как часть обработки веб-запроса, не добавляя заметной дополнительной задержки.Любая хорошая очередь сообщений будет поддерживать пропускную способность 10 сообщений в секунду.HornetQ был оценен как обрабатывающий 8,2 миллиона сообщений в секунду .

Я должен добавить, что очереди сообщений не так сложны в настройке и использовании.Я скачал HornetQ и через несколько минут все заработало.Код, необходимый для создания очереди (с использованием собственного API-интерфейса HornetQ) и отправки и получения сообщений (с использованием API-интерфейса JMS), составляет менее ста строк .

2 голосов
/ 22 марта 2012

Ваши требования не очень понятны. Мой лучший ответ - пройтись по вашему вопросу и постараться указать вам правильное направление по точкам.

  • «Записи не нуждаются ни в каких проверках» и «Моему приложению не нужен ответ, но оно должно быть на 100% безопасным, чтобы оно поступало на сервер правильно».

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

  • «Выполнить код отправки данных в отдельном потоке», «сохранить данные в памяти и отправить позже», «сохранить данные локально и получить их на сервере», и «отправка данных не может быть выполнена» мое приложение ждет ".

Хорошо, похоже, вы хотите неблокирующий ввод / вывод. Но реальность такова, что даже при неблокирующем вводе / выводе все еще требуется некоторое количество времени для фактической отправки данных. Мой вопрос: почему вы запрашиваете неблокирующие и / или быстрые операции ввода-вывода? Если бы передача данных была просто чрезвычайно быстрой, имело бы значение, если бы она не была неблокируемой? Это дизайнерское решение с вашей стороны, но из вашего вопроса не понятно зачем вам это нужно, так что я просто выкидываю его туда.

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

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

Далее, что касается отправки данных в отдельном потоке, это хорошо, если вам нужен неблокирующий ввод / вывод, но (1) вам необходимо обосновать, почему это хорошая идея с точки зрения дизайна вашего программного обеспечения, прежде чем вы идти по этому пути, потому что это добавляет усложнение вашему приложению, поэтому, если оно не решит конкретную, реальную проблему (т.е. в вашем приложении есть пользовательский интерфейс, который не должен зависать / не отвечать из-за ожидающих операций ввода-вывода), то это только добавили усложнение, и вы не получите от этого никакой дополнительной производительности. (2) Существует распространенное искушение использовать потоки, чтобы, опять же, в основном откладывать работу. Перенос работы на другой поток не уменьшает общий объем работы, которую необходимо выполнить, или общий объем операций ввода-вывода, которые ваше приложение будет использовать для выполнения своей функции - он просто откладывает его на другой поток. Бывают случаи, когда это очень полезно, и, возможно, это правильное решение для вашего приложения, но из вашего описания я вижу много запрошенных функций, но не обоснование (или объяснение проблемы, которую вы пытаетесь решить), это резервное копирование это выбор функций / дизайна, который в конечном итоге должен определять направление, в котором вы идете.

Наконец, если сервер «вытягивает» его, а не отправляет на сервер, то все, что вы здесь делаете, это переключение ролей и заставление сервера действовать как клиент, а клиент - как клиент. сервер. Поймите, что «клиент» и «сервер» являются относительными терминами, а сервер - это то, что предоставляет услугу. Простое переключение ролей на самом деле ничего не меняет - просто переключает роли клиент / сервер с одной части программного обеспечения на другую. Сами метки - это просто метки - удобный способ узнать, какая часть предоставляет услугу, а какая часть потребляет услугу (клиент).

  • "У меня есть приложение, которое будет генерировать 5-10 новых записей базы данных на одном хосте каждую секунду."

Это не должно быть проблемой. Любой приличный сервер БД будет воспринимать такую ​​работу как крайне низкую нагрузку. С точки зрения скорости и скорости отклика от сервера больше будут зависеть такие вещи, как задержка в сети (если вы передаете эти данные по сети) и другие факторы, связанные с выбором ввода / вывода, которые будут влиять на то, можете ли вы писать 5- 10 записей в секунду, то есть ваша общая пропускная способность.

1 голос
/ 22 марта 2012

Если вы ставите данные в очередь и отправляете их в потоке, все будет в порядке, если ваша скорость составляет 5-10 в секунду, а клиент только один. Если у вас несколько клиентов, то к тому моменту, когда вставки в вашу базу данных начинают замедляться, у вас могут возникнуть проблемы; учитывая ваше требование «отправка данных не должна завершиться ошибкой». Это гораздо более сложное требование, особенно в случае сбоя компьютера или сети.

Рассмотрим следующий сценарий. У вас больше клиентов, чем ваша база данных может обработать эффективно, и один из ваших пользователей быстро печатать на машинке. Вставки начинают резервировать в памяти в своем приложении. Они заканчивают свою работу и закрывают ее до того, как последние действительно будут загружены в базу данных. Или машина выходит из строя до отправки данных или во время их отправки; или, что еще хуже, база данных падает при отправке, и из-за проблем с сетью клиент не может точно сказать, что его транзакция не завершена.

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

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

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

0 голосов
/ 22 марта 2012

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

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

Вы не говорите, как пишете в базу данных ... JDBC?ORM нравится Hibernate?Но принципы одинаковы.

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