天天看點

[轉] NoSQL資料庫探讨之一 - 為什麼要用非關系資料庫?

作者:robbin

來源:http://robbin.javaeye.com/blog/524977

随着網際網路web2.0網站的興起,非關系型的資料庫現在成了一個極其熱門的新領域,非關系資料庫産品的發展非常迅速。而傳統的關系資料庫在應付web2.0網站,特别是超大規模和高并發的SNS類型的web2.0純動态網站已經顯得力不從心,暴露了很多難以克服的問題,例如:

1、High performance - 對資料庫高并發讀寫的需求

web2.0網站要根據使用者個性化資訊來實時生成動态頁面和提供動态資訊,是以基本上無法使用動态頁面靜态化技術,是以資料庫并發負載非常高,往往要達到每秒上萬次讀寫請求。關系資料庫應付上萬次SQL查詢還勉強頂得住,但是應付上萬次SQL寫資料請求,硬碟IO就已經無法承受了。其實對于普通的BBS網站,往往也存在對高并發寫請求的需求,例如像JavaEye網站的實時統計線上使用者狀态,記錄熱門文章的點選次數,投票計數等,是以這是一個相當普遍的需求。

2、Huge Storage - 對海量資料的高效率存儲和通路的需求

類似Facebook,twitter,Friendfeed這樣的SNS網站,每天使用者産生海量的使用者動态,以Friendfeed為例,一個月就達到了2.5億條使用者動态,對于關系資料庫來說,在一張2.5億條記錄的表裡面進行SQL查詢,效率是極其低下乃至不可忍受的。再例如大型web網站的使用者登入系統,例如騰訊,盛大,動辄數以億計的帳号,關系資料庫也很難應付。

3、High Scalability && High Availability- 對資料庫的高可擴充性和高可用性的需求

在基于web的架構當中,資料庫是最難進行橫向擴充的,當一個應用系統的使用者量和通路量與日俱增的時候,你的資料庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬體和服務節點來擴充性能和負載能力。對于很多需要提供24小時不間斷服務的網站來說,對資料庫系統進行更新和擴充是非常痛苦的事情,往往需要停機維護和資料遷移,為什麼資料庫不能通過不斷的添加伺服器節點來實作擴充呢?

在上面提到的“三高”需求面前,關系資料庫遇到了難以克服的障礙,而對于web2.0網站來說,關系資料庫的很多主要特性卻往往無用武之地,例如:

1、資料庫事務一緻性需求

很多web實時系統并不要求嚴格的資料庫事務,對讀一緻性的要求很低,有些場合對寫一緻性要求也不高。是以資料庫事務管理成了資料庫高負載下一個沉重的負擔。

2、資料庫的寫實時性和讀實時性需求

對關系資料庫來說,插入一條資料之後立刻查詢,是肯定可以讀出來這條資料的,但是對于很多web應用來說,并不要求這麼高的實時性,比方說我(JavaEye的robbin)發一條消息之後,過幾秒乃至十幾秒之後,我的訂閱者才看到這條動态是完全可以接受的。

3、對複雜的SQL查詢,特别是多表關聯查詢的需求

任何大資料量的web系統,都非常忌諱多個大表的關聯查詢,以及複雜的資料分析類型的複雜SQL報表查詢,特别是SNS類型的網站,從需求以及産品設計角度,就避免了這種情況的産生。往往更多的隻是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能被極大的弱化了。

是以,關系資料庫在這些越來越多的應用場景下顯得不那麼合适了,為了解決這類問題的非關系資料庫應運而生,現在這兩年,各種各樣非關系資料庫,特别是鍵值資料庫(Key-Value Store DB)風起雲湧,多得讓人眼花缭亂。前不久國外剛剛舉辦了 NoSQL Conference,各路NoSQL資料庫紛紛亮相,加上未亮相但是名聲在外的,起碼有超過10個開源的NoSQLDB,例如:

Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable, Riak,Tin, Flare, Lightcloud, KiokuDB,Scalaris, Kai, ThruDB,  ......

這些NoSQL資料庫,有的是用C/C++編寫的,有的是用Java編寫的,還有的是用Erlang編寫的,每個都有自己的獨到之處,看都看不過來了, 我(robbin)也隻能從中挑選一些比較有特色,看起來更有前景的産品學習和了解一下。這些NoSQL資料庫大緻可以分為以下的三類:

一、滿足極高讀寫性能需求的Kye-Value資料庫:Redis,Tokyo Cabinet, Flare

高性能Key-Value資料庫的主要特點就是具有極高的并發讀寫性能,Redis,Tokyo Cabinet, Flare,這3個Key-Value DB都是用C編寫的,他們的性能都相當出色,但出了出色的性能,他們還有自己獨特的功能:

1、 Redis

Redis是一個很新的項目,剛剛釋出了1.0版本。Redis本質上是一個Key-Value類型的記憶體資料庫,很像memcached,整個資料庫統統加載在記憶體當中進行操作,定期通過異步操作把資料庫資料flush到硬碟上進行儲存。因為是純記憶體操作,Redis的性能非常出色,每秒可以處理超過10萬次讀寫操作,是我知道的性能最快的Key-Value DB。

Redis的出色之處不僅僅是性能,Redis最大的魅力是支援儲存List連結清單和Set集合的資料結構,而且還支援對List進行各種操作,例如從List兩端push和pop資料,取List區間,排序等等,對Set支援各種集合的并集交集操作,此外單個value的最大限制是1GB,不像memcached隻能儲存1MB的資料,是以Redis可以用來實作很多有用的功能,比方說用他的List來做FIFO雙向連結清單,實作一個輕量級的高性能消息隊列服務,用他的Set可以做高性能的tag系統等等。另外Redis也可以對存入的Key-Value設定expire時間,是以也可以被當作一個功能加強版的memcached來用。

Redis的主要缺點是資料庫容量受到實體記憶體的限制,不能用作海量資料的高性能讀寫,并且它沒有原生的可擴充機制,不具有scale(可擴充)能力,要依賴用戶端來實作分布式讀寫,是以Redis适合的場景主要局限在較小資料量的高性能操作和運算上。目前使用Redis的網站有github,Engine Yard。

2、 Tokyo Cabinet和Tokoy Tyrant

TC和TT的開發者是日本人Mikio Hirabayashi,主要被用在日本最大的SNS網站mixi.jp上,TC發展的時間最早,現在已經是一個非常成熟的項目,也是Kye-Value資料庫領域最大的熱點,現在被廣泛的應用在很多很多網站上。TC是一個高性能的存儲引擎,而TT提供了多線程高并發伺服器,性能也非常出色,每秒可以處理4-5萬次讀寫操作。

TC除了支援Key-Value存儲之外,還支援儲存Hashtable資料類型,是以很像一個簡單的資料庫表,并且還支援基于column的條件查詢,分頁查詢和排序功能,基本上相當于支援單表的基礎查詢功能了,是以可以簡單的替代關系資料庫的很多操作,這也是TC受到大家歡迎的主要原因之一,有一個Ruby的項目 miyazakiresistance将TT的hashtable的操作封裝成和ActiveRecord一樣的操作,用起來非常爽。

TC/TT在mixi的實際應用當中,存儲了2000萬條以上的資料,同時支撐了上萬個并發連接配接,是一個久經考驗的項目。TC在保證了極高的并發讀寫性能的同時,具有可靠的資料持久化機制,同時還支援類似關系資料庫表結構的hashtable以及簡單的條件,分頁和排序操作,是一個很棒的NoSQL資料庫。

TC的主要缺點是在資料量達到上億級别以後,并發寫資料性能會大幅度下降, NoSQL: If Only It Was That Easy提到,他們發現在TC裡面插入1.6億條2-20KB資料的時候,寫入性能開始急劇下降。看來是當資料量上億條的時候,TC性能開始大幅度下降,從TC作者自己提供的mixi資料來看,至少上千萬條資料量的時候還沒有遇到這麼明顯的寫入性能瓶頸。

這個是Tim Yang做的一個 Memcached,Redis和Tokyo Tyrant的簡單的性能評測,僅供參考

3、 Flare

TC是日本第一大SNS網站mixi開發的,而Flare是日本第二大SNS網站green.jp開發的,有意思吧。Flare簡單的說就是給TC添加了scale功能。他替換掉了TT部分,自己另外給TC寫了網絡伺服器,Flare的主要特點就是支援scale能力,他在網絡服務端之前添加了一個node server,來管理後端的多個伺服器節點,是以可以動态添加資料庫服務節點,删除伺服器節點,也支援failover。如果你的使用場景必須要讓TC可以scale,那麼可以考慮flare。

flare唯一的缺點就是他隻支援memcached協定,是以當你使用flare的時候,就不能使用TC的table資料結構了,隻能使用TC的key-value資料結構存儲。

二、滿足海量存儲需求和通路的面向文檔的資料庫:MongoDB,CouchDB

面向文檔的非關系資料庫主要解決的問題不是高性能的并發讀寫,而是保證海量資料存儲的同時,具有良好的查詢性能。MongoDB是用C++開發的,而CouchDB則是Erlang開發的:

1、 MongoDB

MongoDB是一個介于關系資料庫和非關系資料庫之間的産品,是非關系資料庫當中功能最豐富,最像關系資料庫的。他支援的資料結構非常松散,是類似json的bjson格式,是以可以存儲比較複雜的資料類型。Mongo最大的特點是他支援的查詢語言非常強大,其文法有點類似于面向對象的查詢語言,幾乎可以實作類似關系資料庫單表查詢的絕大部分功能,而且還支援對資料建立索引。

Mongo主要解決的是海量資料的通路效率問題,根據官方的文檔,當資料量達到50GB以上的時候,Mongo的資料庫通路速度是MySQL的10倍以上。Mongo的并發讀寫效率不是特别出色,根據官方提供的性能測試表明,大約每秒可以處理0.5萬-1.5次讀寫請求。對于Mongo的并發讀寫性能,我(robbin)也打算有空的時候好好測試一下。

因為Mongo主要是支援海量資料存儲的,是以Mongo還自帶了一個出色的分布式檔案系統GridFS,可以支援海量的資料存儲,但我也看到有些評論認為GridFS性能不佳,這一點還是有待親自做點測試來驗證了。

最後由于Mongo可以支援複雜的資料結構,而且帶有強大的資料查詢功能,是以非常受到歡迎,很多項目都考慮用MongoDB來替代MySQL來實作不是特别複雜的Web應用,比方說 why we migrated from MySQL to MongoDB就是一個真實的從MySQL遷移到MongoDB的案例,由于資料量實在太大,是以遷移到了Mongo上面,資料查詢的速度得到了非常顯著的提升。

MongoDB也有一個ruby的項目 MongoMapper,是模仿Merb的DataMapper編寫的MongoDB的接口,使用起來非常簡單,幾乎和DataMapper一模一樣,功能非常強大易用。

2、CouchDB

CouchDB現在是一個非常有名氣的項目,似乎不用多介紹了。但是我卻對CouchDB沒有什麼興趣,主要是因為CouchDB僅僅提供了基于HTTP REST的接口,是以CouchDB單純從并發讀寫性能來說,是非常糟糕的,這讓我立刻抛棄了對CouchDB的興趣。

三、滿足高可擴充性和可用性的面向分布式計算的資料庫:Cassandra,Voldemort

面向scale能力的資料庫其實主要解決的問題領域和上述兩類資料庫還不太一樣,它首先必須是一個分布式的資料庫系統,由分布在不同節點上面的資料庫共同構成一個資料庫服務系統,并且根據這種分布式架構來提供online的,具有彈性的可擴充能力,例如可以不停機的添加更多資料節點,删除資料節點等等。是以像Cassandra常常被看成是一個開源版本的Google BigTable的替代品。Cassandra和Voldemort都是用Java開發的:

1、 Cassandra

Cassandra項目是Facebook在2008年開源出來的,随後Facebook自己使用Cassandra的另外一個不開源的分支,而開源出來的Cassandra主要被Amazon的Dynamite團隊來維護,并且Cassandra被認為是Dynamite2.0版本。目前除了Facebook之外,twitter和digg.com都在使用Cassandra。

Cassandra的主要特點就是它不是一個資料庫,而是由一堆資料庫節點共同構成的一個分布式網絡服務,對Cassandra的一個寫操作,會被複制到其他節點上去,對Cassandra的讀操作,也會被路由到某個節點上面去讀取。對于一個Cassandra群集來說,擴充性能是比較簡單的事情,隻管在群集裡面添加節點就可以了。我看到有文章說Facebook的Cassandra群集有超過100台伺服器構成的資料庫群集。

Cassandra也支援比較豐富的資料結構和功能強大的查詢語言,和MongoDB比較類似,查詢功能比MongoDB稍弱一些,twitter的平台架構部門上司Evan Weaver寫了一篇文章介紹Cassandra: http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/,有非常詳細的介紹。

Cassandra以單個節點來衡量,其節點的并發讀寫性能不是特别好,有文章說評測下來Cassandra每秒大約不到1萬次讀寫請求,我也看到一些對這個問題進行質疑的評論,但是評價Cassandra單個節點的性能是沒有意義的,真實的分布式資料庫通路系統必然是n多個節點構成的系統,其并發性能取決于整個系統的節點數量,路由效率,而不僅僅是單節點的并發負載能力。

2、 Voldemort

Voldemort是個和Cassandra類似的面向解決scale問題的分布式資料庫系統,Cassandra來自于Facebook這個SNS網站,而Voldemort則來自于Linkedin這個SNS網站。說起來SNS網站為我們貢獻了n多的NoSQL資料庫,例如Cassandar,Voldemort,Tokyo Cabinet,Flare等等。Voldemort的資料不是很多,是以我沒有特别仔細去鑽研,Voldemort官方給出Voldemort的并發讀寫性能也很不錯,每秒超過了1.5萬次讀寫。

從Facebook開發Cassandra,Linkedin開發Voldemort,我們也可以大緻看出國外大型SNS網站對于分布式資料庫,特别是對資料庫的scale能力方面的需求是多麼殷切。前面我(robbin)提到,web應用的架構當中,web層和app層相對來說都很容易橫向擴充,唯有資料庫是單點的,極難scale,現在Facebook和Linkedin在非關系型資料庫的分布式方面探索了一條很好的方向,這也是為什麼現在Cassandra這麼熱門的主要原因。

如今,NoSQL資料庫是個令人很興奮的領域,總是不斷有新的技術新的産品冒出來,改變我們已經形成的固有的技術觀念,我自己(robbin)稍微了解了一些,就感覺自己深深的沉迷進去了,可以說NoSQL資料庫領域也是博大精深的,我(robbin)也隻能淺嘗辄止,我(robbin)寫這篇文章既是自己一點點鑽研心得,也是抛磚引玉,希望吸引對這個領域有經驗的朋友來讨論和交流。

從我(robbin)個人的興趣來說,分布式資料庫系統不是我能實際用到的技術,是以不打算花時間深入,而其他兩個資料領域(高性能NoSQLDB和海量存儲NoSQLDB)都是我很感興趣的,特别是Redis,TT/TC和MongoDB這3個NoSQL資料庫,是以我接下來将寫三篇文章分别詳細介紹這3個資料庫。