1簡介web
2特性數據庫
應用場景json
特點服務器
3實現網絡
4結構併發
5ACID分佈式
6View Serveride
JavaScriptspa
CouchDB是用Erlang開發的面向文檔的數據庫系統,最近剛剛發佈了1.0版本。CouchDB不是一個傳統的關係數據庫,而是面向文檔的數據庫,其數據存儲方式有點相似lucene的index文件格式,CouchDB最大的意義在於它是一個面向web應用的新一代存儲系統,事實上,CouchDB的口號就是:下一代的Web應用存儲系統。
RESTFul API:HTTP GET/PUT/POST/DELETE + JSON
基於文檔存儲,數據之間沒有關係範式要求
每一個數據庫對應單個個文件(以JSON保存),Hot backup
MVCC(Multi-Version-Concurrency-Control),讀寫均不鎖定數據庫
用戶自定義View
內建備份機制
支持附件
使用Erlang開發(更多的特性)
在咱們的生活中,有不少document,好比信件,帳單,筆記等,他們只是簡單的信息,沒有關係的需求,咱們可能僅僅須要存儲這些數據。這樣的狀況下,CouchDB應該是很好的選擇。固然其餘使用關係型數據庫的環境,也可使用CouchDB來解決。
在某些偶爾鏈接網絡的應用中,咱們能夠用CouchDB暫存數據,隨後進行同步。也能夠在Cloud環境中,做爲分佈式的數據存儲。CouchDB提供給予HTTP的API,這樣全部的常見語言均可以使用CouchDB。
使用CouchDB,意味着咱們不須要在像使用RMDBS同樣,在設計應用前首先設計負責數據Table。咱們的開發更加快速,靈活。
在CouchDB中,Database表示一個數據庫,每一個Database對應一個」Storage」(後綴爲.couch)以及多個View Index(用來存儲View結果支持query)。
Database Storage中能夠存儲任意的Document,用戶能夠在Database中自定義View,方便對數據進行查詢, View 默認使用JavaScript進行定義,定義好的相關函數保存在design document 中,而View對應的具體數據是保存在View Index文件中。咱們能夠經過HTTP API請求Database,Document,View,能夠進行簡單的Query,以及其餘各類系統相關的信息。
數據庫文件的後綴爲.couch,由Header和Body組成。
包含兩個徹底相同的Header信息,每一個Header的Size爲2048
Header中前4字節爲magic code:$g, $m, $k, 0
隨後爲header的payload,經過term_to_binary(db_header_record)產生
接下來是填充padding
最後是16字節的摘要信息(md5(payload+padding)產生)
Header總長度爲:單個Header * 2 = 2048
Body
由兩個B+Tree組成,其中一個B+Tree根據Document id進行組織,另外一個B+Tree以 seqnum(CouchDB內部使用的序號,用來指示最新Revision的文檔)爲 key。
fulldocinfo_by_id_btree使用Document id做爲key,經常使用來根據id來查找對應的document,full_doc_info中包含對應document的全部的Revision信息,經過這些信息,咱們能夠獲取指定Revision的document
docinfo_by_seq_btree使用seq做爲key,當document被更新時,對應的seq會增長。
具體的document數據(json格式),以及B+Tree混合存儲與這個.couch文件之中。經過B+Tree,咱們能夠快速的定位到指定的document。
CouchDB全部的更新操做(包括document的建立,修改和刪除)都是以在couch文件尾部追加的方式(即Append方式)進行。咱們進行更新時,首先拷貝原有的數據信息(僅僅針對修改,若是是Create那麼就沒有copy可言了),隨後將其追加到文件的結尾,這個時候就激發 B+Tree從 leaf到root的更新過程,更新的Node信息也是採用Append的方式寫入到文件的結尾,到達根節點時,咱們將根節點信息寫入到Header中。這樣一次更新操做涉及1次數據寫入,以及LogN次節點更新,因此其複雜度爲O(logN)。
所以採用追加的方式,因此在數據庫運行一段時間後,咱們須要對其進行「瘦身」,清理那些舊的Document數據。這個過程稱爲Compaction。在 Compation 的過程當中,數據庫仍然可用,只是請注意,在 Compation 的時候,是經過遍歷 DBName.couch 文件,將最新的數據拷貝到一個 DBName.compat文件中,所以這個過程可能會耗費很大的存儲空間,若是您在系統繁忙(主要是write)的狀況下進行Compation,可能會致使你的硬盤空間耗盡,必定注意哦!
CouchDB支持ACID特性。Document的更新(add,edit,delete)是順序進行的,可是Database的read爲併發執行,其沒必要等待任何其餘的read,write的完成。這樣的特性與CouchDB存儲文件的Append增長方式關係密切。
當CouchDB的文檔更新時,爲了保證數據的一致性,Commit分爲如下兩步:
Document數據和index數據首先寫入到disk數據庫文件
生成兩個連續的頭信息(4kb),隨後寫入數據庫文件
在上面兩個過程當中,若是在過程1,發生異常(系統崩潰或斷電),那麼couch文件的頭信息沒有發生變化,那麼全部Append的數據都會被忽略;若是在過程2發生異常,此時Header可能會發生損壞,咱們驗證第一個Header和第二個Header,若是任意一個Header可用,那麼數據庫文件可用。若是兩個Header都不可用,則對應數據庫文件損壞,拋出異常。
一些數據庫系統,爲了實現 Atomic Commit ,提交數據前,將內容寫入到一個rollback log文件,等提交完成後,刪除log文件。
除了存儲數據,咱們還須要依據咱們的要求展示數據,乃至一些統計,所以CouchDB中引入了View的概念。View的引入讓CouchDB從一個有趣的文件存儲系統,步入了數據庫的殿堂。也使CouchDB可以融入到真正的應用環境中。
CouchDB中全部的Document均可以具備本身不一樣的結構,數據,這和關係型數據庫中,嚴格的表結構,嚴格的關聯徹底不一樣。這樣的特色對於數據的備份同步卻很是有好處!
經過用戶自定義View,咱們能夠聚集,統計數據,採用一個相似Map/Reduce的過程。這裏的Map將原始的Document進行映射處理,Reduce將Map的中間結果進行從新歸併統計,總而生成最終結果。這裏和並行計算中的Map/Reduce有些不一樣。
CouchDB的View針對每一個Database,可是其與Database關聯性不是很大,View是一些用戶自定義函數,處理從數據庫的Document 輸入,產生中間數據(若是沒有reduce過程則爲最終數據),而後再經過Reduce處理中間輸出,產生最終結果。一樣的View可使用在不一樣的Database上。
View存儲在design Document中,請注意這裏design Document和View Index是不一樣的。design Document保存的是view的定義,View Index保存的是針對某個Database進行View操做,產生的結果。
CouchDB內部默認使用JavaScript做爲View的編寫語言,之因此採用Javascript,是和CouchDB面向Web開發相關的。CouchDB使用Mozilla的spidermonkey做爲JavaScript的解析運行平臺,爲了和Erlang進行交互,其使用c書寫了一個Port程序couchjs,/server/main.js做爲View Server服務器。
在啓動CouchDB時,經過Command:couchjs main.js便可啓動基於JavaScript的View Server。
View中包含兩個函數:
(map函數,必須)function(doc) { emit(null, doc);}(reduce函數,可選)function (key, values, rereduce) { return sum(values);}
doc,爲咱們數據庫對應的Document,由於咱們採用JSON格式存儲數據,因此 Document 在 JavaScript 中轉化爲 Object。`emit(null,doc)`用來生成 map 的中間結果,其中第一個參數 null 表示結果的 key,第二個參數爲結果的 value,上面的例子中咱們的結果爲:
null, value1...null, valueN
function (key, values, rereduce)中,根據rereduce變量不一樣這裏有兩種狀況:
1. rereduce爲false
key爲array,element爲:[key,id],key爲map function產生的key,id爲Document對應id
values爲array,elements爲map function產生的結果
好比 reduce([ [key1,id1], [key2,id2], [key3,id3] ], [value1,value2,value3], false)
2. rereduce爲true
key爲null
values爲array,element爲前一次reduce返回的結果
好比reduce(null, [intermediate1,intermediate2,intermediate3], true)
不少時候,咱們一次調用reduce就能夠生成最終結果,咱們會忽略rereduce參數。[1]