我正在寻找Hibernate的系统,它需要在不可靠的网络中工作。我们需要一个单一的中央数据库进行读写访问,但它可以在一个非常不完整的Wi-Fi网络上使用。此外,可能存在功率损耗,这些功率损耗不会干净地关闭应用程序,因此任何解决方案都必须具有可以在电源循环中存活的持久高速缓存。最后,这是一个只有适度内存和磁盘空间的嵌入式系统,例如对数据库进行全面复制并不是一种可行的策略。
我对Hibernate二级缓存有一个基本的了解,我想知道是否有可能用Ehcache这样的东西配置来解决这个问题,但是主要的推力似乎是性能不可用,所以我是不知道陷阱可能是什么。
我也非常愿意考虑其他涉及复制到本地数据库的策略。我宁愿不必为实现这一点而做太多繁重的工作。
寻找一些经验或可能的替代方案。
答案 0 :(得分:3)
“此外,可能存在功率损耗,不会干净地关闭应用程序,因此任何解决方案都必须具有可以在电源循环中存活的持久缓存。”
你已经有了Hibernate二级缓存的解决方案。但你没有说出真正的要求是什么。你有一个不可思议的网络。没关系,你有不可靠的电源。那也没关系。现在您希望达到什么级别的服务?什么是可以接受的?
数据丢失是否可以接受?你能接受多少?你接受什么风险?
为了更明确,假设您拥有数据库的本地副本或至少部分数据库。假设您知道如何排队/保存本地修改。假设您将这些修改存储在硬盘驱动器上,以便在发生电源故障时安全。假设您可以在连接再次可用时将更改与主数据库合并。
这已经有很多假设。好吧但是如果一个硬盘在电力故障后失败会发生什么?您知道硬盘驱动器不喜欢电源故障并且在电源故障时会损坏甚至可能会损坏吗?
所以你戴上了RAID,并添加了不间断电源。真好。您从OS检测到电源故障事件。完成当前事务并正确关闭。您可以RAID保护您免受磁盘故障的影响。
好的,但如果整台电脑停止运行会怎样?发生火灾时会发生什么?还是水损坏?将管理所有磁盘,数据不可恢复以及与中央数据库不同步的内容将丢失。是否可以接受?
即使打开wifi,电源也能完美运行......无论如何,中央数据库的可靠性是多少?你有定期备份吗?还是一个集群解决方案?你确定你的中央数据库是否可靠?
从数据库的角度来看,很容易使用集群或备份并使用事务来确保数据一致性。您仍然可以丢失数据(如果不是特别使用群集),但您应该能够恢复到最后一次备份为例。
但是如果您想脱机工作(数据库不可用),并且您不是唯一可以修改数据库的人,则会发生冲突。这不再是缓存,休眠或任何技术问题。
这是功能问题。当多个修改脱机并且您必须合并时该怎么办?可以接受什么?什么不是。这可能是在重新连接时,最近的更改适用,旧的更改将被丢弃。或者检测到可能的冲突并提示用户处理它们。您可以尝试应用排队更改并应用所有这些更改...
我倾向于认为您可以提供“离线模式”,但您的用户必须知道他们处于脱机状态,并且应该在中央数据库上永久更改并最终解决冲突时发出通知。但那是我的观点。
答案 1 :(得分:2)
你不能指望在hibernate和数据库之间建立这样的网络。
我建议您定义一组高级原子操作,然后为它们定义一组(例如)restful服务。或者,如果您愿意,可以使用soap并查看WS- *选项以获得可靠的消息传递,以处理重试和所有其他混乱的细节。
或者,您可以调查链接中的cassandra之类的内容是否比SQL更好,或者是其他重要的复制内容。
答案 2 :(得分:2)
如何在持久/持久消息队列上排队数据库操作,让一些消息中间件处理网络问题?
根据你的工作方式,可能会出现一致性问题(好吧,“异常”这个词我认为是正确的),但是如果你有不可靠的网络并且仍然需要不错的性能,那么解决放松的一致性可能是通往走。
我会犹豫是否使用EhCache等。它们不是为此设计的,因此您可能需要“拉伸”框架。另一方面,消息队列具有针对此类场景设计的解决方案。
答案 3 :(得分:1)
如果只是两台机器之间偶尔连接的情况,我建议保留一个可以播放的事务日志,并将每个条目标记为已处理。然而,有限的记忆可能会使这很困难。
但是,您可以存储压缩的事务日志。
答案 4 :(得分:1)
Hibernate(以及二级缓存)真的不是为此而设计的。我的猜测是你可能最好使用小规模嵌入式Java RDBMS(例如H2或HSQLDB)作为本地临时队列(在最耐用模式下可用),然后与后台线程进行同步。然后,您可以提供连接到该后台线程的同步微调器UI,以便为用户提供一定程度的反馈。
顺便说一句,Hibernate在转换到嵌入式环境时有点胖。你可能想要考虑myBatis。
答案 5 :(得分:0)
Daffodil Replicator(http://enterprise.replicator.daffodilsw.com/index.html)允许在JDBC源之间进行复制。它支持双向更新,合并和冲突解决以及部分副本。
这可用于将主数据库与本地(部分)副本同步。您可以使用hibernate与本地副本数据库通信,并在该过程之外完成所有其他操作。