源地址:http://database.51cto.com/art/200905/123802.htm
【51CTO独家特稿】一个数据库的持久性整体规划通常都是不成套的。各种ORM(对象关系映射)工具都能更容易地进行对象和数据结构之间的转换,但没有一个是完美的。这就是通常所说的“ORM Impedance Mismatch(阻抗不匹配)”。虽然抽象数据库是一个崇高和理想的目标,但没有考虑关系数据库这一事实总是会暴露出来。Joel Spolsky称之为“The Law of Leaky Abstractions(泄露的抽象规律)”。51CTO编者注:Joel Spolsky是一个美国的软件工程师,他的网络日志“Joel谈软件”(Joel on Software)非常有名,读者人数可以排进全世界前100名。
最简单的分离形式是由“映射层次对象到数据库表”所描述。这件事绝对是可以做到的,对于其实现毫无质疑。花费在设计理想映射的大量努力,也许可以更好地用于解决真正的问题,而不是在仔细检查问题之前就考虑解决方案。
更多的根据来自于最近发表在DZone的一篇文章。作者抱怨开发人员胡乱编写代码,使得数据库的使用效率超级低。虽然如此,但这样的问题只有在你了解低层实现的情况下才能暴漏出来。从纯粹的面向对象的角度来看,代码还算可以。
数据库基础
笔者认为关于数据库解决方案的最根本问题来自于这样一个事实,即人们总是默认地拘泥于某一个应用。“我们需要保持持久性。”“那好吧,让我们使用一个数据库吧[和ORM]”。
虽然RDBMS(关系型数据库管理系统)是一个很好的、成熟的解决方案,但它并不总是最理想的。在认真分析领域问题之前就先选择一个解决方案始终是错误的。
核心问题是,我们希望能够保存和恢复应用程序中某些数据结构的状态。需要一些关键点用来在各种机器之间共享这些状态(用于可扩展性)。
尝试删除RDBMS
所有尝试都不外乎建立一个所谓的面向对象数据库,这证明,除了RDBMS我们还有别的选择。我们有了一些很酷的工具,如Apache的CouchDB,它改变了我们考虑数据库的方式。特别是如JCR(针对Java的内容知识库),它提供了存储数据的另一种方法,看起来更像我们真正要涉及的对象。
所有这些方法都有一个很大的缺点,在某些时候,你会映射一些其他的数据格式到你的对象,是否还要映射属性/ xml文件、元数据(注释),或只是代码。各种系统都能简单完成这个任务,但总有某个地方让人觉得有问题。
很多都只是RDBMS的再包装,本质并不脱离RDBMS。暴露出来的问题是一些查询极其缓慢,而其他的速度却极快。直到你能理解数据库是怎样被使用的,你才能明白这是为什么。这会导致代码进行修改,以便能以尽可能最快的方式运行,抽象就被打破了。
几年前,笔者曾经试图用Lucene搜索索引取代只读数据库。它实际上运行得相当出色。使用Lucene搜索索引来查询数据比调用RDBMS要快很多。在特殊情况下,要快2个数量级之多,但还存在其他问题……这个概念从未真正占据主流。无论有多么不方便,都很难打破人们心理上对于数据库解决方案的传统认识。51CTO编者注:有关Lucene搜索的使用方法,可参考用Lucene做一个简单的Java搜索工具一文。
理想的解决方案
如果你的应用程序只是要维护它的状态,那将会存在理想的解决方案吗?
◆重启之间
◆机群的机器之间
在这样一个世界里,你根本不认为会存在一个持久性机制。你只是编写你的应用代码;设置对象域;机群中某个机器的线程死亡时的恢复处理 。
只是一个梦想?
我们即将迎来2010年。你要知道,现在我们已经有了在一组计算机之间分享系统状态的方法。有办法在一个文件系统中保留状态备份,允许在系统重启或崩溃时进行恢复。
你应该能够编写你的应用程序,假设它只能够运行在没有崩溃的单个机器上。
具有串行化的解决方案?
使用串行化来简单地保持应用程序的状态,这种办法怎么样?或者基于图像的持久性,如Smalltalk ?
在使用C / C++ 的日子里,我们可以获得对象在内存中的地址,然后把字节地址写到磁盘。这是一种简单的保存和恢复系统状态的方法。Java提供了一个完整的串行化API (地址不能用于安全方面的考虑)。
可以创建一个线程来不断保持串行化数据文件随着应用程序中对象的更新。然而,这种解决方案在一个机群中可能施行得不太好。透明度将会消失。接口被污染(需要实现串行化的事物)。
虽然简单,串行化可能不会是最好的解决办法,但是,这将会是一个有趣的实验。
共享内存
实现共享内存最明显的方法是建立一个后台进程,保持一组机器内存同步,同时保存一个文件。这将保持各个机器与其他机器同步操作,如果其中一个机器崩溃(如果它不能从邻居机器读取状态),利用该文件可以进行恢复。
看起来似乎一个虚拟机可能会为实现一个解决方案提供最大的成功机会,通过虚拟机,它能让一些不可思议的事情更容易地发生在内存访问背后,而不是发生在直接访问内存空间时。
解决方案
因此,现在都存在哪些解决方案?
Oracle Coherence
Oracle用他们的Coherence产品做出了一个很好的尝试。
这个解决方案的问题在于它的实现。在网络间传送整个对象可以迅速让网络达到饱和(如各种HTTP会话共享模式所表现出来的问题)。Coherence还需要接口,需要对象实现串行化(但这个问题比较小) 。
对于这些问题,Oracle解决方案在某些情况下可能是有用的,并会随着技术的成熟而逐渐改善。风险是,该解决方案被打断到Oracle的数据库集群业务中。改善该项目的驱动力可能不会很高。
Terracotta
Terracotta似乎会提供以下列表内的所有需求:
◆网络间同步
◆用磁盘保留状态同步
◆透明的
◆快速的
Terracotta解决了笔者想要解决的一切问题,而且用一个优化的透明解决方案进行管理。不需要强制对象执行串行化、不需要进行其他任何类型的实现改变,它可以透明地工作于虚拟机之下。它通过发送不同的对象而不是整个对象,来设法优化网络使用率。它甚至保留状态与文件系统的同步。总之,是目前最透明的持久性系统。
唯一需要强调的是,它只支持Java版本,不支持.net。因此,想要使用它,你只能选择Java, Haskell, Scala, Groovy, jRuby, Jython, JavaScript或其他任何可以运行于JVM(Java虚拟机)的语言。
真实的魔术
Terracotta不会进行机器之间不必要的复制。它只做足以提供故障切换保护的工作,其余的事情会按需而做。它甚至会把不使用的数据从一台机器中剔除。
另外,对于每台新添加到机群中的机器,为每台机器增加有效内存。
当笔者看到类似这样的事,笔者就想知道,除此之外,笔者还会需要数据库为笔者做什么事。
笔者唯一可以想到的是,为数据挖掘和商业智能软件包提供可用数据(或数据仓库)。多数这些工具已经围绕数据库进行设计。
因此,RDBMS有效地成为了一个日志机器。
放弃RDBMS
因此,通过使用由Terracotta所提供的公共收藏(集合/列表/映射),完全可以放弃使用RDBMS。其结果是整洁的(具有更好的可维护性)代码,更有效的内存使用,和更快的执行时间。
有什么理由不喜欢Terracotta呢?
是否将概念取消?
是否取消使用共享内存的概念,作为摆脱数据库的一种方式。
笔者希望如此。这是一个人人都想拥抱简单的时代。Ruby on Rails, Grails, Spring, Wicket和其他框架的增加已经表明,大多数开发人员已经受够了过分复杂的解决方案。
他们可能会愿意完全摆脱一个复杂的解决方案。
也许,我只是完全错误的
或许RDBMS仍是一个很难移除的角色,可能是由于这个角色担当着重要的任务,有着重要的目的,例如是针对多个程序的集成点(就像Martin Fowler在他的Database Thaw Post中所说的) 。
Fowler实际上是建议建立一个HTTP包围数据库。这就把它从一个集成点转换成了一个应用程序。笔者已经参与了这种类型的应用,它具有一些非常强大的功能。
本文所说的可能不会适用的另一个领域是数据仓库。但是,把它封装在REST层,将是一个极好的应用。
作为一个针对各种应用的共有方式,不考虑它的实现,为了共享数据,使用RDBMS似乎很难被击败。据笔者所知,Terracotta解决方案可以工作于基于JVM的应用程序之间。但是,对于其他语言(C / C + + / Smalltalk )可能是有点困难。
原文:Best alternative to RDBMS and ORMs : Terracotta by Taranfx