Стратегии для Java ORM с ненадежной сетью и низкой пропускной способностью

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

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

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

Ищете некоторый опыт или возможные альтернативы.

6 ответов

Решение

Репликатор Daffodil (http://enterprise.replicator.daffodilsw.com/index.html) позволяет выполнять репликацию между источниками JDBC. Он поддерживает двунаправленные обновления, слияние и разрешение конфликтов, а также частичные реплики.

Это можно использовать для синхронизации основной базы данных с локальной (частичной) репликой. Вы можете использовать hibernate, чтобы общаться с локальной базой данных реплик и делать все остальное вне этого процесса.

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

У вас уже есть решение с Hibernate кеш уровня 2. Но вы не сказали, каковы реальные требования. У вас нереальная сеть. Это нормально, у вас нереальный источник питания. Тоже норм. Теперь какой уровень сервиса вы хотите достичь? Что приемлемо или нет?

Допустима ли потеря данных? Сколько вы могли бы принять? Какой риск вы принимаете?

Чтобы быть более точным, допустим, у вас есть локальная копия базы данных или, по крайней мере, ее часть. Допустим, вы знаете, как ставить в очередь / сохранять изменения, сделанные локально. Допустим, вы храните эти модификации на жестком диске, чтобы быть в безопасности в случае сбоя питания. Допустим, вы можете объединить изменения с основной базой данных, когда соединение снова станет доступным.

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

Таким образом, вы устанавливаете RAID и добавляете источник бесперебойного питания. Это мило. Вы обнаружите событие сбоя питания от ОС. Завершите текущую транзакцию и корректно завершите работу. Вы RAID защищаете вас от сбоя диска.

Хорошо, но что произойдет, если весь компьютер перестанет работать? Что происходит в случае пожара? Или повреждение водой? Все диски будут управляться, данные не будут восстановлены, а то, что не синхронизировано с центральной базой данных, будет потеряно. Это приемлемо или нет?

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

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

Но если вы хотите работать в автономном режиме (с недоступной базой данных), и вы не единственный, кто может изменять базу данных, конфликты БУДУТ возникать. Это больше не кеш, спящий режим или какая-либо техническая проблема.

Это функциональная проблема. Что делать, если несколько модификаций происходит в автономном режиме и вам нужно объединить? Что приемлемо? Что не является. Это может быть связано с тем, что при повторном подключении применяются самые последние изменения, более старые изменения отменяются. Или же обнаруживаются конфликты и пользователь предлагает их устранить. Вы можете попробовать применить изменения в очереди и применить их все...

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

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

Я рекомендую вам определить набор атомарных операций высокого уровня, а затем определить набор (например) отдыхающих сервисов для них. Или, если хотите, вы можете использовать мыло и посмотреть опции WS-* для надежного обмена сообщениями, чтобы позаботиться о повторных попытках и всех других беспорядочных деталях.

Или вы могли бы исследовать, будет ли что-то вроде cassandra через ссылку работать лучше, чем SQL, или что-то еще большое в репликации.

Как насчет того, чтобы ставить в очередь операции с БД в долговременной / постоянной очереди сообщений и позволить некоторому промежуточному программному обеспечению для обмена сообщениями решить проблему сети?

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

Я не хотел бы использовать EhCache и т. Д. Они не были предназначены для этого, и, следовательно, вам, возможно, придется "растянуть" фреймворк. С другой стороны, очереди сообщений имеют решения, разработанные для таких сценариев.

Hibernate (и кэш второго уровня) действительно не предназначены для этого. Я предполагаю, что вам лучше всего использовать небольшую встроенную СУБД Java (например, H2 или HSQLDB) в качестве локальной временной очереди (в наиболее долговременном доступном режиме), а затем выполнять синхронизацию с фоновым потоком. Затем вы могли бы предоставить пользовательский интерфейс синхронизирующего счетчика, подключенный к фоновому потоку, чтобы обеспечить некоторую степень обратной связи для пользователя.

Между прочим, Hibernate немного жирен для встраивания в встроенную среду. Вы можете рассмотреть myBatis вместо этого.

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

Может быть, вы можете сохранить журнал транзакций сжатым, хотя.

Другие вопросы по тегам