非關係型數據庫(NoSql)

正文html

最近了解了一點非關係型數據庫,剛剛接觸,以爲這是一個很好的方向,對於大數據 方面的處理,非關係型數據庫能起到相當重要的地位。這裏我主要是整理了一些前輩的經驗,僅供參考。node

關係型數據庫的特色

  1.關係型數據庫 

關係型數據庫,是指採用了關係模型來組織數據的數據庫。 簡單來講,關係模型指的就是二維表格模型,而一個關係型數據庫就是由二維表及其之間的聯繫所組成的一個數據組織。常見 的關係型數據庫有Oracle、Mysql、sql server等等。

2. 關係型數據庫瓶頸 
高併發讀寫需求 
網站的用戶併發性很是高,每每達到每秒上萬次讀寫請求,對於傳統關係型數據庫來講,硬盤I/O是一個很大的瓶頸 
海量數據的高效率讀寫 網站天天產生的數據量是巨大的,對於關係型數據庫來講,在一張包含海量數據的表中查詢,效率是很是低的 
高擴展性和可用性 
在基於web的結構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,數據庫卻沒有辦法像web server和app server那樣簡單的經過添加更多的硬件和服務節點來擴展性能和負載能力。對於不少須要提供24小時不間斷服務的網站來講,對數據庫系統進行升級和擴展是很是痛苦的事情,每每須要停機維護和數據遷移。  
對網站來講,關係型數據庫的不少特性再也不須要了: 
事務一致性 
關係型數據庫在對事物一致性的維護中有很大的開銷,而如今不少web2.0系統對事物的讀寫一致性都不高 
讀寫實時性 
對關係數據庫來講,插入一條數據以後馬上查詢,是確定能夠讀出這條數據的,可是對於不少web應用來講,並不要求這麼高的實時性,好比發一條消息以後,過幾秒乃至十幾秒以後纔看到這條動態是徹底能夠接受的 
複雜SQL,特別是多表關聯查詢 
任何大數據量的web系統,都很是忌諱多個大表的關聯查詢,以及複雜的數據分析類型的複雜SQL報表查詢,特別是SNS類型的網站,從需求以及產品階級角度,就避免了這種狀況的產生。每每更多的只是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能極大的弱化了  
在關係型數據庫中,致使性能欠佳的最主要緣由是多表的關聯查詢,以及複雜的數據分析類型的複雜SQL報表查詢。爲了保證數據庫的ACID特性,咱們必須儘可能按照其要求的範式進行設計,關係型數據庫中的表都是存儲一個格式化的數據結構。每一個元組字段的組成都是同樣,即便不是每一個元組都須要全部的字段,但數據庫會爲每一個元組分配全部的字段,這樣的結構能夠便於標語表之間進行連接等操做,但從另外一個角度來講它也是關係型數據庫性能瓶頸的一個因素。 

非關係型數據庫(NoSQL )

2009年初,Johan Oskarsson舉辦了一場關於開源分佈式數據庫的討論,Eric Evans在此次討論中提出了NoSQL一詞,用於指代那些非關係型的,分佈式的,且通常不保證遵循ACID原則的數據存儲系統。Eric Evans使用NoSQL這個詞,並非由於字面上的「沒有SQL」的意思,他只是以爲不少經典的關係型數據庫名字都叫「**SQL」,因此爲了表示跟這些關係型數據庫在定位上的大相徑庭,就是用了「NoSQL「一詞。 
注:數據庫事務必須具有ACID特性,ACID是Atomic原子性,Consistency一致性,Isolation
 var script = document.createElement('script'); script.src = 'http://static.pay.baidu.com/resource/baichuan/ns.js'; document.body.appendChild(script);
隔離性,Durability持久性。  
非關係型數據庫提出另外一種理念,例如,以鍵值對存儲,且結構不固定,每個元組能夠有不同的字段,每一個元組能夠根據須要增長一些本身的鍵值對,這樣就不會侷限於固定的結構,能夠減小一些時間和空間的開銷。使用這種方式,用戶能夠根據須要去添加本身須要的字段,這樣,爲了獲取用戶的不一樣信息,不須要像關係型數據庫中,要對多表進行關聯查詢。僅須要根據id取出相應的value就能夠完成查詢。但非關係型數據庫因爲不多的約束,他也不可以提供像SQL所提供的where這種對於字段屬性值狀況的查詢。而且難以體現設計的完整性。他只適合存儲一些較爲簡單的數據,對於須要進行較複雜查詢的數據,SQL數據庫顯的更爲合適。 
關係型數據庫與非關係型數據庫的區別 
關係型數據庫的最大特色就是事務的一致性:傳統的關係型數據庫讀寫操做都是事務的,具備ACID的特色,這個特性使得關係型數據庫能夠用於幾乎全部對一致性有要求的系統中,如典型的銀行系統。 
可是,在網頁應用中,尤爲是SNS應用中,一致性卻不是顯得那麼重要,用戶A看到的內容和用戶B看到同一用戶C內容更新不一致是能夠容忍的,或者說,兩我的看到同一好友的數據更新的時間差那麼幾秒是能夠容忍的,所以,關係型數據庫的最大特色在這裏已經無用武之地,起碼不是那麼重要了。 相反地,關係型數據庫爲了維護一致性所付出的巨大代價就是其讀寫性能比較差,而像微博、facebook這類SNS的應用,對併發讀寫能力要求極高,關係型數據庫已經沒法應付(在讀方面,傳統上爲了克服關係型數據庫缺陷,提升性能,都是增長一級memcache來靜態化網頁,而在SNS中,變化太快,memchache已經無能爲力了),所以,必須用新的一種數據結構存儲來代替關係數據庫。 
關係數據庫的另外一個特色就是其具備固定的表結構,所以,其擴展性極差,而在SNS中,系統的升級,功能的增長,每每意味着數據結構巨大變更,這一點關係型數據庫也難以應付,須要新的結構化數據存儲。 
因而,非關係型數據庫應運而生,因爲不可能用一種數據結構化存儲應付全部的新的需求,所以,非關係型數據庫嚴格上不是一種數據庫,應該是一種數據結構化存儲方法的集合。 必須強調的是,數據的持久存儲,尤爲是海量數據的持久存儲,仍是須要一種關係數據庫。 
非關係型數據庫簡介 
SQLite 
1. ACID事務 
2. 零配置 – 無需安裝和管理配置 
3. 儲存在單一磁盤文件中的一個完整的數據庫 
4. 數據庫文件能夠在不一樣字節順序的機器間自由的共享
 5. 支持數據庫大小至2TB 
6. 足夠小, 大體3萬行C代碼, 250K 
7. 比一些流行的數據庫在大部分普通數據庫操做要快8. 簡單, 輕鬆的API 
9. 包含TCL綁定, 同時經過Wrapper支持其餘語言的綁定10. 良好註釋的源代碼, 而且有着90%以上的測試覆蓋率 11. 獨立: 沒有額外依賴 
12. Source徹底的Open, 你能夠用於任何用途, 包括出售它 13. 支持多種開發語言,C, PHP, Perl, Java, ASP .NET,Python

下面介紹下key相關的命令 
exits key 測試指定key是否存在,返回1表示存在,0不存在 
del key1 key2 ....keyN  刪除給定key,返回刪除key的數目,0表示給定key都不存在 
type key 返回給定key的value類型。返回 none 表示不存在key,string字符類型,list 鏈表類型 set 無序集合類型... 
keys pattern 返回匹配指定模式的全部key,下面給個例子 redis> set test dsf OK 
redis> set tast dsaf OK 
redis> set tist adff OK 
redis> keys t* 1. "tist" 2. "tast" 3. "test" 
redis> keys t[ia]st 1. "tist" 2. "tast" 
redis> keys t?st 1. "tist" 2. "tast" 3. "test"  
randomkey 返回從當前數據庫中隨機選擇的一個key,若是當前數據庫是空的,返回空串  rename oldkey newkey 原子的重命名一個key,若是newkey存在,將會被覆蓋,返回1表示成功,0失敗。多是oldkey不存在或者和newkey相同 
renamenx oldkey newkey 同上,可是若是newkey存在返回失敗 dbsize 返回當前數據庫的key數量 
expire key seconds 爲key指定過時時間,單位是秒。返回1成功,0表示key已經設置過過時時間或者不存在 
ttl key 返回設置過過時時間的key的剩餘過時秒數 -1表示key不存在或者沒有設置過過時時間 
select db-index 經過索引選擇數據庫,默認鏈接的數據庫全部是0,默認數據庫數是16個。返回1表示成功,0失敗 
move key db-index  將key從當前數據庫移動到指定數據庫。返回1成功。0 若是key不存在,或者已經在指定數據庫中 
flushdb 刪除當前數據庫中全部key,此方法不會失敗。慎用 
flushall 刪除全部數據庫中的全部key,此方法不會失敗。更加慎用  
2. string 類型 
string是redis最基本的類型,並且string類型是二進制安全的。意思是redis的string能夠包含任何數據。好比jpg圖片或者序列化的對象 

 

隨着互聯網web2.0網站的興起,非關係型的數據庫如今成了一個極其熱門的新領域, 非關係數據庫產品的發展很是迅速。而傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不 從心,暴露了不少難以克服的問題,例如:

一、High performance – 對數據庫高併發讀寫的需求 
web2.0網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,因此基本上沒法使用動態頁面靜態化技術,所以數據庫併發負載很是高,每每要達到 每秒上萬次讀寫請求。關係數據庫應付上萬次SQL查詢還勉強頂得住,可是應付上萬次SQL寫數據請求,硬盤IO就已經沒法承受了。其實對於普通的BBS網 站,每每也存在對高併發寫請求的需求,例如像JavaEye網站的實時統計在線用戶狀態,記錄熱門帖子的點擊次數,投票計數等,所以這是一個至關廣泛的需 求。mysql

二、Huge Storage – 對海量數據的高效率存儲和訪問的需求 
相似Facebook,twitter,Friendfeed這樣的SNS網站,天天用戶產生海量的用戶動態,以Friendfeed爲例,一個月就達到 了2.5億條用戶動態,對於關係數據庫來講,在一張2.5億條記錄的表裏面進行SQL查詢,效率是極其低下乃至不可忍受的。再例如大型web網站的用戶登 錄系統,例如騰訊,盛大,動輒數以億計的賬號,關係數據庫也很難應付。git

三、High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求 
在基於web的架構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,你的數據庫卻沒有辦法像web server和app server那樣簡單的經過添加更多的硬件和服務節點來擴展性能和負載能力。對於不少須要提供24小時不間斷服務的網站來講,對數據庫系統進行升級和擴展 是很是痛苦的事情,每每須要停機維護和數據遷移,爲何數據庫不能經過不斷的添加服務器節點來實現擴展呢?github

在上面提到的「三高」需求面前,關係數據庫遇到了難以克服的障礙,而對於web2.0網站來講,關係數據庫的不少主要特性卻每每無用武之地,例如:web

一、數據庫事務一致性需求 
不少web實時系統並不要求嚴格的數據庫事務,對讀一致性的要求很低,有些場合對寫一致性要求也不高。所以數據庫事務管理成了數據庫高負載下一個沉重的負 擔。redis

二、數據庫的寫實時性和讀實時性需求 
對關係數據庫來講,插入一條數據以後馬上查詢,是確定能夠讀出來這條數據的,可是對於不少web應用來講,並不要求這麼高的實時性,比方說發一條消息之 後,過幾秒乃至十幾秒以後,個人訂閱者纔看到這條動態是徹底能夠接受的。sql

三、對複雜的SQL查詢,特別是多表關聯查詢的需求 
任何大數據量的web系統,都很是忌諱多個大表的關聯查詢,以及複雜的數據分析類型的複雜SQL報表查詢,特別是SNS類型的網站,從需求以及產品設計角 度,就避免了這種狀況的產生。每每更多的只是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能被極大的弱化了。數據庫

所以,關係數據庫在這些愈來愈多的應用場景下顯得不那麼合適了,爲了解決這類問題的非關係數據庫應運而生,如今這兩年,各類各樣非關係數據庫,特別是鍵值 數據庫(Key-Value Store DB)風起雲涌,多得讓人眼花繚亂。前不久國外剛剛舉辦了NoSQL Conference,各路NoSQL數據庫紛紛亮相,加上未亮相可是名聲在外的,起碼有超過10個開源的NoSQLDB,例如:json

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

這些NoSQL數據庫,有的是用C/C++編寫的,有的是用Java編寫的,還有的是用Erlang編寫的,每一個都有本身的獨到之處,看都看不過來了,這 些NoSQL數據庫大體能夠分爲如下的三類:

1、知足極高讀寫性能需求的Kye-Value數據庫:Redis,Tokyo Cabinet, Flare

高性能Key-Value數據庫的主要特色就是具備極高的併發讀寫性能,Redis,Tokyo Cabinet, Flare,這3個Key-Value DB都是用C編寫的,他們的性能都至關出色,但出了出色的性能,他們還有本身獨特的功能:

一、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。

二、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主要的缺點是沒有scale的能力,若是單機沒法知足要求,只能經過主從複製的方式擴展,另外有人提到TC的性能會隨着數據量的增長而降低,當數據量 上億條之後,性能會有比較明顯的降低。

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

三、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數據結構存儲。

2、知足海量存儲需求和訪問的面向文檔的數據庫:MongoDB,CouchDB

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

一、MongoDB
MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。他支持的數據結構很是鬆散,是相似 json的bjson格式,所以能夠存儲比較複雜的數據類型。Mongo最大的特色是他支持的查詢語言很是強大,其語法有點相似於面向對象的查詢語言,幾 乎能夠實現相似關係數據庫單表查詢的絕大部分功能,並且還支持對數據創建索引。

Mongo主要解決的是海量數據的訪問效率問題,根據官方的文檔,當數據量達到50GB以上的時候,Mongo的數據庫訪問速度是MySQL的10倍以 上。Mongo的併發讀寫效率不是特別出色,根據官方提供的性能測試代表,大約每秒能夠處理0.5萬-1.5次讀寫請求。

由於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如出一轍,功能很是強大易用。

二、CouchDB
CouchDB如今是一個很是有名氣的項目,彷佛不用多介紹了。可是我卻對CouchDB沒有什麼興趣,主要是由於CouchDB僅僅提供了基於HTTP REST的接口,所以CouchDB單純從併發讀寫性能來講,是很是糟糕的,這讓我馬上拋棄了對CouchDB的興趣。

3、知足高可擴展性和可用性的面向分佈式計算的數據庫:Cassandra,Voldemort

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

一、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多個節點構成的系統,其併發性能取 決於整個系統的節點數量,路由效率,而不只僅是單節點的併發負載能力。

二、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能力方面的需求是多麼殷切。前面提到,web應用的架構當中,web層和app層相對來講都很容易橫向擴展,惟有數據庫是單點的,極難 scale,如今Facebook和Linkedin在非關係型數據庫的分佈式方面探索了一條很好的方向,這也是爲何如今Cassandra這麼熱門的 主要緣由。

補充說明:1.實質。  非關係型數據庫的實質:非關係型數據庫產品是傳統關係型數據庫的功能閹割版本,經過減小用不到或不多用的功能,來大幅度提升產品性能。2.價格。  目前基本上大部分主流的非關係型數據庫都是免費的。而比較有名氣的關係型數據庫,好比Oracle、DB二、MSSQL是收費的。雖然Mysql免費,但它須要作不少工做才能正式用於生產。3.功能。  實際開發中,有不少業務需求,其實並不須要完整的關係型數據庫功能,非關係型數據庫的功能就足夠使用了。這種狀況下,使用性能更高、成本更低的非關係型數據庫固然是更明智的選擇。非關係型數據庫在某些特定的領域很好用,好比redis做爲數據的緩存,數據是存儲在內存中,因此性能很是好,底層只有三萬條代碼,貌似知乎就用到了redis做爲數據庫。 非關係數據庫只實現了關係數據庫一部分的功能,但所以很大程度上擴充了某些功能的性能。通常用關係數據庫就夠了。嚴格說mysql在關係數據庫兄是實現得也不是很完整的一類,從而在某些查詢上,mysql有超出嚴格關係數據庫不少的性能。具體應用須要權衡,特別是關聯條件不少的數據,非關係數據庫通常不合適,有時候甚至mysql也不合適。

相關文章
相關標籤/搜索