亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

CouchDB 實(shí)現(xiàn)原理

系統(tǒng) 1661 0

特性

  1. RESTFul API
  2. 基于文檔存儲(chǔ),無(wú)表固定結(jié)構(gòu),數(shù)據(jù)之間沒(méi)有關(guān)系范式要求
  3. 多版本并發(fā)控制模型
  4. 用戶自定義查詢結(jié)構(gòu)(map/reduce)
  5. 增量索引更新機(jī)制
  6. 多master復(fù)制模式
  7. 用Erlang編寫

CouchDB 能夠適應(yīng)非常廣泛的應(yīng)用場(chǎng)景,在某些偶爾連接網(wǎng)絡(luò)的應(yīng)用中,我們可以用CouchDB暫存數(shù)據(jù),隨后進(jìn)行同步。也可以在Cloud環(huán)境中,作為大型的分布 式的數(shù)據(jù)存儲(chǔ)。CouchDB提供了基于 HTTP的API的訪問(wèn)方式,這樣,保證了所有的常見的語(yǔ)言都可以使用CouchDB。

底層存儲(chǔ)結(jié)構(gòu)

CouchDB是一個(gè)"面向文檔"的數(shù)據(jù)庫(kù),文檔的格式是一個(gè)JSON字符串(也可包含二進(jìn)制附件)。 底層結(jié)構(gòu)是由一個(gè)"存儲(chǔ)"(storeage) ,以及多個(gè)"視圖索引"(view indexs)。 "儲(chǔ)存"用來(lái)儲(chǔ)存文件, "視圖索引"用于查詢處理。

CouchDB落實(shí)到最底層的數(shù)據(jù)結(jié)構(gòu)就是兩類B+Tree 。

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

第 二類B+Tree, by_seqnum_index (使用序列號(hào)來(lái)作為key,說(shuō)得具體點(diǎn)就是記錄最新的reversion來(lái)作為key) 。當(dāng)document進(jìn)行更新的時(shí)候,就會(huì)產(chǎn)生一個(gè)新的序列號(hào)。 (值得注意的是,所有更新操作都是一個(gè)串行的方式,因此序列號(hào)反映了序列的非同步更新)。 同步復(fù)制的追蹤,數(shù)據(jù)的顯示以及更新與它都密不可分。

?


?

一切皆追加

所 有的更新操作(包括document的創(chuàng)建,修改和刪除)都是以在couch文件尾部追加的方式(即Append方式)進(jìn)行。而不是修改現(xiàn)有的文件。在此 之后, B+樹節(jié)點(diǎn)也修改為指向新的文件的位置。修改操作實(shí)際上就是在現(xiàn)有的B+樹的末尾附加一個(gè)新的文件。這反過(guò)來(lái)又引發(fā)修改父節(jié)點(diǎn)的B+樹節(jié)點(diǎn),造成一個(gè)新的 副本父節(jié)點(diǎn)...直到所有的方式回到根B+樹節(jié)點(diǎn)。最后修改文件頭以指向新的跟節(jié)點(diǎn)。

這意味著所有更新將觸發(fā)1次寫入文件(除刪除)和logN寫入每個(gè)B +樹節(jié)點(diǎn)的頁(yè)面。 因此,復(fù)雜度為O ( logN )。

一 切皆最佳的操作提供了一個(gè)有趣的MVCC (多版本并發(fā)控制)模型,因?yàn)樵撐募4媪怂幸郧暗臍v史文件版本信息。 只要客戶端持有先前根節(jié)點(diǎn)的B +樹索引,它就可以得到的快照視圖。即便是更新不斷發(fā)生,客戶將不會(huì)看到任何的最新變化。這種一致性快照在在線備份以及在線"瘦身"方面是非常有用的。

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

GET document

當(dāng)客戶端向CouchDB的發(fā)出的HTTP的REST的GET請(qǐng)求,DBServer將做如下操作...

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

PUT document(修改操作)

當(dāng)客戶端向CouchDB的發(fā)出的HTTP的REST的PUT請(qǐng)求,DBServer將做如下操作...

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

請(qǐng)注意, by_seqnum B +樹索引總是指向最新版本,以前的修改會(huì)自動(dòng)被覆蓋。

PUT/POST document(創(chuàng)建)

當(dāng)客戶端向CouchDB的發(fā)出的HTTP的REST的PUT請(qǐng)求,DBServer將做如下操作...

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

刪除文件(修改)

當(dāng)客戶端向CouchDB的發(fā)出的HTTP的REST的DELETE請(qǐng)求,DBServer將做如下操作...

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

Online Compation(刪除舊的Document)

作為一個(gè)一切皆追加的存儲(chǔ)方式,存儲(chǔ)文件會(huì)隨著時(shí)間的推移與日俱增。 因此,我們需要對(duì)其進(jìn)行"瘦身",刪除那些舊的Document數(shù)據(jù)。這個(gè)過(guò)程稱為 Compaction。

打開一個(gè)新的存儲(chǔ)文件
從by_seqnum B +樹索引中找到最新reversion的document
復(fù)制document到新的存儲(chǔ)文件中(在新的存儲(chǔ)文件中自動(dòng)更新相應(yīng)的B +樹索引)。

在 Compation的過(guò)程,數(shù)據(jù)庫(kù)仍然可用,只是請(qǐng)注意,在Compation的時(shí)候,是通過(guò)遍歷DBName.couch文件, 將最新的數(shù)據(jù)拷貝到一個(gè)DBName.compat文件中, 因此這個(gè)過(guò)程可能會(huì)耗費(fèi)很大的存儲(chǔ)空間,如果您在系統(tǒng)繁忙(主要是write)的情況下進(jìn) 行Compation,可能會(huì)導(dǎo)致你的硬盤空間耗盡。推薦系統(tǒng)在一個(gè)寫操作不是很繁忙的情況下進(jìn)行Compation。

View Indexs

CouchDB 支持類似數(shù)據(jù)庫(kù)的View的概念。所不同的是CouchDB是采用Map/Reduce的方式來(lái)表現(xiàn)的。(請(qǐng)注意,reduce語(yǔ)義與谷歌的Map /Reduce模型有著很大的不同)。Map()是一個(gè)用戶定義的函數(shù),它用來(lái)將每個(gè)文件處理成中間結(jié)果。Reduce()是另外的一種用戶定義的函數(shù), 它用戶將Map()函數(shù)所產(chǎn)生的中間結(jié)果進(jìn)行收集匯總而生成最終結(jié)果。

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

每一個(gè)View的定義就是一個(gè)Map函數(shù)和一個(gè)可選的Reduce函數(shù)。View存儲(chǔ)在design Document中。

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

請(qǐng)注意這里design Document和View Index是不同的。design Document保存的是view的定義,View Index保存的是針對(duì)某個(gè)Database進(jìn)行View操作,產(chǎn)生的結(jié)果。


?

起初,View文件是空的(View尚未創(chuàng)建) , 當(dāng)查詢執(zhí)行的時(shí)候會(huì)觸發(fā)下面一系列的處理。

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

CouchDB繼續(xù)上升一個(gè)等級(jí),并重復(fù)計(jì)算rereduce結(jié)果。 最后,直到更新完根節(jié)點(diǎn)的rereduce的結(jié)果為止。


?

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


?

增量視圖更新

CouchDB更新view indexes采用懶加載和增量的方式。 也即是說(shuō),當(dāng)文件被更新了,CouchDB不會(huì)立即刷新view index,直到下一次查詢到來(lái)的時(shí)候才進(jìn)行更新。

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

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

由于一致的快照的特性,在進(jìn)行數(shù)據(jù)更新操作的過(guò)程中,view 查詢需要花費(fèi)較長(zhǎng)時(shí)間。 查詢需要等待索引更新完成后才能看到一致的結(jié)果。 還有一個(gè)選擇(開發(fā)中) ,立即返回一個(gè)陳舊的副本,這對(duì)客戶來(lái)說(shuō)是可以容忍的。

CouchDB 實(shí)現(xiàn)原理


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产精亚洲视频 | 日本一级成人毛片免费观看 | 久久国产综合尤物免费观看 | 奇米888888 | 欧美成人免费午夜影视 | 久久国产一区二区三区 | 在线观看日本免费视频大片一区 | 亚洲欧美中文日韩综合 | 一区二区免费在线观看 | 欧美一级大片在线观看 | 国产一区二区三区精品视频 | 国产特黄| 欧美又黄又嫩大片a级 | 国产精品揄拍100视频 | 国产欧美另类 | 91久草视频 | 成人网欧美亚洲影视图片 | 国产精品午夜久久 | 日韩毛片久久91 | 九九在线精品视频 | 亚洲区一二三四区2021 | 美女一级大黄录像一片 | 九九精品视频在线免费观看 | 午夜成年人网站 | 亚洲视频区 | 久久福利在线 | 欧美洲大黑香蕉在线视频 | 尤物视频一区二区 | 天天干天天干天天色 | 日本aⅴ在线不卡免费观看 日本aaaa | 九色91精品国产网站 | 久久久精品在观看999 | 国产精品久久久久久久久免费观看 | 在线影院福利 | 亚洲香蕉中文网 | 日日碰日日操 | 欧美高清视频www夜色资源网 | 青青草这里只有精品 | 激情亚州| 深夜福利影院 | 久久不射影院 |