數(shù)據(jù)庫服務為上層 Web 應用提供關系式或結構化的數(shù)據(jù)存儲與查詢支持。取決于具體用例,Web 應用可以使用數(shù)據(jù)庫連接器之類的插件機制來提供對不同數(shù)據(jù)庫服務的訪問支持。在這種架構下,用戶可以靈活地選擇或變更最適合企業(yè)現(xiàn)階段情況的不同數(shù)據(jù)庫產品。例如:用戶可以在原型階段使用 SQLite 之類的嵌入式引擎完成快速部署和功能驗證;而在應用的初期階段切換到廉價的 MySql 數(shù)據(jù)庫解決方案;等到業(yè)務需求不斷上升,數(shù)據(jù)庫負載不斷加重時再向
Clustrix、MongoDB、Cassandra、MySql Cluster、ORACLE 等更昂貴和復雜的解決方案進行遷移。
Memcached 服務作為一個完全基于內存和 <Key, Value> 對的分布式數(shù)據(jù)對象緩沖服務,擁有令人難以置信的查詢效率以及一個優(yōu)雅的,無需服務器間通信的大型分布式架構。對于高負載 Web 應用來說,Memcached 常被用作一種重要的數(shù)據(jù)庫訪問加速服務,因此它不是一個必選組件。用戶完全可以等到現(xiàn)實環(huán)境下的數(shù)據(jù)庫服務出現(xiàn)了性能瓶頸時在部署它。值得強調的是,雖然 memcached 并不是一個必選組件,但通過其在 YouTube、Wikipedia、Amazon.com、SourceForge、Facebook、Twitter
等大型 Web 應用上的多年部署可以證明:memcached 不但能夠在高負載環(huán)境下長期穩(wěn)定地工作,而且可以戲劇性地提升數(shù)據(jù)查詢的整體效率。有關 memcached 的進一步討論,請參考:http://en./wiki/Memcached。
當然,我們也應該注意到:以 memcached 為代表的分布式緩存系統(tǒng),其本質上是一種以犧牲一致性為代價來提升平均訪問效率的妥協(xié)方案——緩存服務為數(shù)據(jù)庫中的部分記錄增加了分布式副本。對于同一數(shù)據(jù)的多個分布式副本來說,除非使用 Paxos、Raft 等一致性算法,不然無法實現(xiàn)強一致性保證。
矛盾的是,memory cache 本身就是用來提升效率的,這使得為了它使用上述開銷高昂的分布式強一致性算法變得非常不切實際:目前的分布式強一致性算法均要求每次訪問請求(無論讀寫)都需要同時訪問包括后臺數(shù)據(jù)庫主從節(jié)點在內的多數(shù)派副本——顯然,這還不如干脆不使用緩存來的有效率。
另外,即使是 Paxos、Raft 之類的分布式一致性算法也只能在單個記錄的級別上保證強一致。意即:即使應用了此類算法,也無法憑此提供事務級的強一致性保證。
除此之外,分布式緩存也增加了程序設計的復雜度(需要在訪問數(shù)據(jù)庫的同時嘗試命中或更新緩存),并且還增加了較差情形下的訪問延遲(如:未命中時的 RTT 等待延遲,以及節(jié)點下線、網絡通信故障時的延遲等)。
與此同時,可以看到:從二十年前開始,各主流數(shù)據(jù)庫產品其實均早已實現(xiàn)了成熟、高命中率的多層(磁盤塊、數(shù)據(jù)頁、結果集等)緩存機制。既然分布式緩存有如此多的缺陷,而數(shù)據(jù)庫產品又自帶了優(yōu)秀的緩存機制,它為何又能夠成為現(xiàn)代高負載 Web App 中的重要基石呢?
其根本原因在于:對于十年前的技術環(huán)境來說,當時十分缺乏橫向擴展能力的 RDBMS(SQL)系統(tǒng)已成為了嚴重制約 Web App 等網絡應用擴大規(guī)模的瓶頸。為此,以 Google BigTable、Facebook Cassandra、MongoDB 為代表的 NoSQL 數(shù)據(jù)庫產品,以及以 memcached、redis 為代表的分布式緩存產品紛紛粉墨登場,并各自扮演了重要作用。
與 MySQL、ORACLE、DB2、MS SQL Server、PostgreSQL 等當時的 "傳統(tǒng)" SQL數(shù)據(jù)庫產品相比,無論 NoSQL 數(shù)據(jù)庫還是分布式緩存產品,其本質上都是以犧牲前者的強一致性為代價,來換取更優(yōu)的橫向擴展能力。
應當看到,這種取舍是在當時技術條件下做出的無奈、痛苦的抉擇,系統(tǒng)因此而變得復雜——在需要事務和強一致性保障,并且數(shù)據(jù)量較少的地方,使用無緩存層的傳統(tǒng) RDBMS;在一致性方面有一定妥協(xié)余地,并且讀多寫少的地方盡量使用分布式緩存來加速;在對一致性要求更低的大數(shù)據(jù)上使用 NoSQL;如果數(shù)據(jù)量較大,同時對一致性要求也較高,就只能嘗試通過對 RDMBS 分庫分表等方法來盡量解決,為此還要開發(fā)各種中間件來實現(xiàn)數(shù)據(jù)訪問的請求分發(fā)和結果集聚合等復雜操作……各種情形不一而足,而它們的相互組合和交織則再次加劇了復雜性。
回顧起來,這是一個舊秩序被打破,新秩序又尚未建立起來的混亂時代——老舊 RMDBS 缺乏橫向擴展能力,無法滿足新時代的大數(shù)據(jù)處理需求,又沒有一種能夠替代老系統(tǒng)地位,可同時滿足大部分用戶需求的普適級結構化數(shù)據(jù)管理方案。
這是一個青黃不接的時代,而 BigTable、Cassandra、memcached 等產品則分別是 Google、Facebook 以及 LiveJournal 等廠商在那個時代進行 "自救" 的結果。這樣以:"花費最小代價,滿足自身業(yè)務需求即可" 為目標的產物自然不太容易具備很好的普適性。
然而今天(2015),我們終于就快要走出這個窘境。隨著 Google F1、MySQL Cluster(NDB)、Clustrix、VoltDB、MemSQL、NuoDB 等眾多 NewSQL 解決方案的逐步成熟以及技術的不斷進步,橫向擴展能力逐漸不再成為 RDBMS 的瓶頸。今天的架構設計師完全可以在確保系統(tǒng)擁有足夠橫向擴展能力的同時,實現(xiàn)分布式的事務級(XA)強一致性保證:
如上圖所示,在 NewSQL 具備了良好的橫向擴展能力后,架構中不再迫切需要分布式緩存和 NoSQL 產品來彌補這方面的短板,這使得設計和開發(fā)工作再次回歸到了最初的簡潔和清晰。而對象存儲(Object Storage)服務則提供了對音頻、視頻、圖片、文件包等海量非結構化BLOB數(shù)據(jù)的存儲和訪問支持。
這樣簡潔、清晰、樸素的架構使一切看起來仿佛回歸到了多年以前,對象存儲服務就像 FAT、NTFS、Ext3 等磁盤文件系統(tǒng),NewSQL 服務則好像當年 MySQL、SQL Server 等 "單機版" 數(shù)據(jù)庫。但一切卻又已不同,業(yè)務邏輯、數(shù)據(jù)庫和文件存儲均已演進成為支持橫向擴展的高可用集群,在性能、容量、可用性、可靠性、可伸縮性等方面有了巨大的飛躍:人類總是以螺旋上升的方式不斷進步——在每一次看似回歸的變遷中,實包含了本質的升華。
隨著 GlusterFS、Ceph、Lustre 等可 mount 且支持 Native File API 的分布式文件系統(tǒng)越來越成熟和完善,也有望于大部分場合下逐漸替換現(xiàn)有的對象存儲服務。至此 Web App 架構的演進才能算是完成了一次重生——這還算不上是涅槃,當我們能夠在真正意義上實現(xiàn)出高效、高可用的多虛一(Single System Image)系統(tǒng)時,涅槃才真正降臨。那時的我們編寫分布式應用與如今編寫一個單機版的多線程應用將不會有任何區(qū)別——進程天然就是分布式、高可用的!
|