欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

CouchDB 實現原理

系統 1735 0

特性

  1. RESTFul API
  2. 基于文檔存儲,無表固定結構,數據之間沒有關系范式要求
  3. 多版本并發控制模型
  4. 用戶自定義查詢結構(map/reduce)
  5. 增量索引更新機制
  6. 多master復制模式
  7. 用Erlang編寫

CouchDB 能夠適應非常廣泛的應用場景,在某些偶爾連接網絡的應用中,我們可以用CouchDB暫存數據,隨后進行同步。也可以在Cloud環境中,作為大型的分布 式的數據存儲。CouchDB提供了基于 HTTP的API的訪問方式,這樣,保證了所有的常見的語言都可以使用CouchDB。

底層存儲結構

CouchDB是一個"面向文檔"的數據庫,文檔的格式是一個JSON字符串(也可包含二進制附件)。 底層結構是由一個"存儲"(storeage) ,以及多個"視圖索引"(view indexs)。 "儲存"用來儲存文件, "視圖索引"用于查詢處理。

CouchDB落實到最底層的數據結構就是兩類B+Tree 。

第一類B+Tree,by_id_index (使用document的id為key)。常用來通過document的id來查找document的位置,實際上,他是指向的一個reversion列表集合。

第 二類B+Tree, by_seqnum_index (使用序列號來作為key,說得具體點就是記錄最新的reversion來作為key) 。當document進行更新的時候,就會產生一個新的序列號。 (值得注意的是,所有更新操作都是一個串行的方式,因此序列號反映了序列的非同步更新)。 同步復制的追蹤,數據的顯示以及更新與它都密不可分。

?


?

一切皆追加

所 有的更新操作(包括document的創建,修改和刪除)都是以在couch文件尾部追加的方式(即Append方式)進行。而不是修改現有的文件。在此 之后, B+樹節點也修改為指向新的文件的位置。修改操作實際上就是在現有的B+樹的末尾附加一個新的文件。這反過來又引發修改父節點的B+樹節點,造成一個新的 副本父節點...直到所有的方式回到根B+樹節點。最后修改文件頭以指向新的跟節點。

這意味著所有更新將觸發1次寫入文件(除刪除)和logN寫入每個B +樹節點的頁面。 因此,復雜度為O ( logN )。

一 切皆最佳的操作提供了一個有趣的MVCC (多版本并發控制)模型,因為該文件保存了所有以前的歷史文件版本信息。 只要客戶端持有先前根節點的B +樹索引,它就可以得到的快照視圖。即便是更新不斷發生,客戶將不會看到任何的最新變化。這種一致性快照在在線備份以及在線"瘦身"方面是非常有用的。

值得注意的是,讀操作是并行的,寫操作是串行的。 換句話說,在任何時候只有一個文件可以進行更新操作(但是,如果是寫入附件的話,可以在一個文件中進行并行操作。)

GET document

當客戶端向CouchDB的發出的HTTP的REST的GET請求,DBServer將做如下操作...

  1. 查找文件頭,找到by_id B +樹索引的根節點
  2. 在B +樹中找出該文件的位置
  3. 閱讀了該文件,并返回到客戶端

PUT document(修改操作)

當客戶端向CouchDB的發出的HTTP的REST的PUT請求,DBServer將做如下操作...

  1. 查找文件頭,找到by_id B +樹索引的根節點
  2. 在B +樹中找出該文件的位置
  3. 讀取該文件。對比reversion,如果他們不匹配就拋出一個錯誤。
  4. 如果它們匹配,生成一個新的reversion。
  5. 尋找末尾的一個區域(region),看看該文件的容量是否可以容納,如果不能就另外開辟一個region。
  6. 寫文件(新reversion)到新的區域(region)
  7. 修改by_id B +樹以指向新的文件位置
  8. 修改by_seqnum B +樹添加新實體(新seqnum ) ,并刪除舊的條目(舊seqnum ) 。

請注意, by_seqnum B +樹索引總是指向最新版本,以前的修改會自動被覆蓋。

PUT/POST document(創建)

當客戶端向CouchDB的發出的HTTP的REST的PUT請求,DBServer將做如下操作...

  1. 生成一個新的seqnum及一個新的文件編號和修訂
  2. 尋找末尾的一個區域(region),看看該文件的容量是否可以容納,如果不能就另外開辟一個region。
  3. 寫文件(新reversion)到新的區域(region)
  4. 修改by_id B +樹以指向新的文件位置
  5. 修改by_seqnum B +樹添加新項目(新seqnum )

刪除文件(修改)

當客戶端向CouchDB的發出的HTTP的REST的DELETE請求,DBServer將做如下操作...

  1. 查找文件頭找到根節點的by_id B +樹索引
  2. 在B +樹找出葉節點以及該文件的位置
  3. 讀取該文件。 對比修訂,如果他們不匹配就拋出一個錯誤。
  4. 如果它們匹配,找出找到這個reversion。
  5. 生成一個新的reqnum
  6. 修改by_id B +樹的reversion 歷史,將這個路徑的reversion標記為被刪除
  7. 修改by_seqnum B +樹添加新實體(新seqnum ) ,并刪除舊的條目(舊seqnum )。

Online Compation(刪除舊的Document)

作為一個一切皆追加的存儲方式,存儲文件會隨著時間的推移與日俱增。 因此,我們需要對其進行"瘦身",刪除那些舊的Document數據。這個過程稱為 Compaction。

打開一個新的存儲文件
從by_seqnum B +樹索引中找到最新reversion的document
復制document到新的存儲文件中(在新的存儲文件中自動更新相應的B +樹索引)。

在 Compation的過程,數據庫仍然可用,只是請注意,在Compation的時候,是通過遍歷DBName.couch文件, 將最新的數據拷貝到一個DBName.compat文件中, 因此這個過程可能會耗費很大的存儲空間,如果您在系統繁忙(主要是write)的情況下進 行Compation,可能會導致你的硬盤空間耗盡。推薦系統在一個寫操作不是很繁忙的情況下進行Compation。

View Indexs

CouchDB 支持類似數據庫的View的概念。所不同的是CouchDB是采用Map/Reduce的方式來表現的。(請注意,reduce語義與谷歌的Map /Reduce模型有著很大的不同)。Map()是一個用戶定義的函數,它用來將每個文件處理成中間結果。Reduce()是另外的一種用戶定義的函數, 它用戶將Map()函數所產生的中間結果進行收集匯總而生成最終結果。

Map()的中間對象和Reduce()后的結果存儲在View Indexs中。隨著存儲得到更新, 以前的結果也會隨著更新。

每一個View的定義就是一個Map函數和一個可選的Reduce函數。View存儲在design Document中。

            (map函數,必須)
function(doc) {
emit(
            
              null
            
            
, doc);
}
(reduce函數,可選)
function (key, values, rereduce) {
   
            
              return
            
            
 sum(values);
}
          

請注意這里design Document和View Index是不同的。design Document保存的是view的定義,View Index保存的是針對某個Database進行View操作,產生的結果。


?

起初,View文件是空的(View尚未創建) , 當查詢執行的時候會觸發下面一系列的處理。

1.CouchDB將遍歷存儲文件的by_seqnum B +樹索引。
2.在此基礎上, CouchDB獲得所有現有文件的最新reversion
3.CouchDB通過seqnum獲取document,然后將每份document反饋到View Server 上用于進行Map操作。
4.View Server 調用map(doc)函數,遍歷調用emit(key,value),一個中間實體就是被這么創建出來的。
5.最后,將map(doc)函數所產生和結果集返回給CouchDB 。
6.CouchDb將這些實體加入到B +樹索引,Key = emit_key + doc_id 。 遍歷每一個B +樹的葉節點。
7.CouchDB將View Servier所獲得的Map()結果集進行"Reduce" 操作。
8.View Server 調用Reduce(key,value)函數。
9.將reduce計算的結果返回給CouchDB
10.CouchDb將更新葉子上的B +樹節點,將其指向reduce的值。
11.在此之后, CouchDb移動到父節點的葉子上的B +樹節點。 遍歷每個B +樹父節點, CouchDB將相應reduce子節點的數據發送到View Server,再次進行reduce的操作(rereduce)。
12.View Server再次調用 reduce(key, value)函數。
13.最后, 再將rereduce計算出的結果返回給CouchDB 。
14.CouchDB將更新父B +樹節點,將其指向rereduce的值。

CouchDB繼續上升一個等級,并重復計算rereduce結果。 最后,直到更新完根節點的rereduce的結果為止。


?

當處理完成后,View Index 看上去就是下面這種樣子


?

增量視圖更新

CouchDB更新view indexes采用懶加載和增量的方式。 也即是說,當文件被更新了,CouchDB不會立即刷新view index,直到下一次查詢到來的時候才進行更新。

CouchDB刷新index采用如下的方式:

  1. CouchDB將遍歷存儲文件的by_seqnum B +樹索引。
  2. CouchDB從最后一次視圖查詢的結果中抽取出的所有改變的文檔,然后從新進行map操作,并取得一個Map結果集合。
  3. CouchDb更新Map結果到B +樹索引,一些葉子B +樹節點將被更新。
  4. 對于那些已經更新了的葉子B +樹節點, CouchDB重新發送Map生成的所有中間結果到View Server 進行Reduce的操作。 然后reduce的結果保存到B +樹節點。
  5. 所有涉及到這個葉子B +樹節點都需要更新, CouchDB需要再次執行Reduce計算,并且更新相應的父節點。 直到更新完根節點為止。

由于一致的快照的特性,在進行數據更新操作的過程中,view 查詢需要花費較長時間。 查詢需要等待索引更新完成后才能看到一致的結果。 還有一個選擇(開發中) ,立即返回一個陳舊的副本,這對客戶來說是可以容忍的。

CouchDB 實現原理


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 婷婷影音 | 国产精品久久久久久久久久久久久 | 国产日韩精品视频 | 天天爽天天碰狠狠添 | 国产亚洲情侣一区二区无 | 日韩av电影在线播放 | 最近最新中文字幕 | 凤囚凰 电视剧 | 国产99999 | 国产精品久久久久秋霞影视 | 日韩精品一二三区 | 日本一道一区二区免费看 | 国产精品毛片久久久久久 | 成人毛片免费网站 | 成人免费观看在线网址 | 999精品视频 | 久99久视频 | 中文字幕国产一区 | 精品视频www | 久久香蕉国产精品一区二区三 | 亚洲性生活免费视频 | 亚洲国产精品久久 | 韩日在线视频 | 一级毛片免费 | 毛片激情永久免费 | 午夜视频网址 | 婷婷色爱区综合五月激情韩国 | 欧美a级成人淫片免费看 | 一区二区三区无码高清视频 | 久久久久久久国产精品毛片 | 五月婷婷综合在线视频 | 久久极品 | 日本黄大片影院一区二区 | 99久久一香蕉国产线看观看 | 久久精品麻豆 | 大陆黄色网 | 日韩综合 | 国产深夜福利视频在线 | 黄视频网站免费看 | 亚州精品天堂中文字幕 | 久久久亚洲伊人色综合网站 |