探尋關系數據庫和ORM的最佳替代者
原創【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搜索工具一文。
#p#
理想的解決方案
如果你的應用程序只是要維護它的狀態,那將會存在理想的解決方案嗎?
◆重啟之間
◆機群的機器之間
在這樣一個世界里,你根本不認為會存在一個持久性機制。你只是編寫你的應用代碼;設置對象域;機群中某個機器的線程死亡時的恢復處理 。
只是一個夢想?
我們即將迎來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有效地成為了一個日志機器。
#p#
放棄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
【編輯推薦】