2012-03-22 4 views
0

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

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

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

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

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

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

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

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

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

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

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

ответ

2

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

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

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

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

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

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

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

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

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

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

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

0

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

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

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

1

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

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

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

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

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

2

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

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

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