Couchbase---一個嘗試做到完美的分佈式 NoSQL數據庫

簡介

官網地址:https://www.couchbase.com/

Couchbase是一個較新的、發展迅速的nosql數據庫技術。2014年,viber宣佈使用Couchbase替換Mongodb,以適應10億級的用戶量,目前,Couchbase已大量運用於生產環境,國內使用的公司主要有新浪,騰訊等。

Couchbase是CouchDB和MemBase的合併。而memBase是基於Memcached的。因此Couchbase聯合了Couchbase的簡單可靠和memcached的高性能,以及membase的可擴展性。

靈活的數據模型:Couchbase中使用json格式存儲對象和對象之間的關係。

Nosql數據庫的一個特性是不需要定義數據結構,在Couchbase中,數據可以存儲爲key-value對或者json文檔,不需要預先定義嚴格的格式,由於這種特性,couchbase支持以 scale out(水平擴展)方式擴展數據量,提升io性能,只需要在集羣中添加更多的服務器就行了。相反,關係數據庫管理系統scale up(縱向擴展),通過加更多的CPU,內存和硬盤以擴展容量。

Couchbase可用於單機環境,也可以和其他服務器一起提供分佈式的數據存儲。

特點

CouchBase是在memcached和redis之類緩存組件的基礎上發展而來的,被稱作爲可能是最好的緩存系統。所其必然能滿足之前的前輩所滿足不了的地方。
傳統的緩存組件包括memcached和redis有着這種或者那種的缺點:

  • Cluster支持完善度不夠或者直接沒有Cluster
  • 沒有良好的高可用性機制,持久化支持的亦不是很完善
  • 擴容和故障恢復能操作維護複雜
  • 其他
    而CouchBase則對上面的一些缺點都有着良好的支持。或者說
    CouchBase所提供的任何單一功能,在市面上基本上都能找到一款數據庫能夠滿足。但是這些數據庫實際使用的話總是會有各種各樣的妥協,性能很好的話,擴展性可能很差之類的。而CouchBase的目標就是建立一個大一統,各種功能都包含可用,所謂接近完美的數據庫。

技術特徵

數據存儲

Couchbase通過使用buckets提供數據管理服務,buckets相當於關係數據庫中的庫,Couchbase中沒有表的概念,保存數據時,先建bucket,然後就直接插入數據了。buckets可以供集羣中的多個客戶端程序訪問。Couchbase通過Buckets組織,管理和分析數據資源。

Couchbase中有兩種類型的數據bucket,當啓動Couchbase服務的時候,可以選擇需要的類型。

1)memcached buckets。只將數據存儲在內存中。提供了一個分佈式的(橫向擴展),純內存的,key-value緩存。Memcached buckets 設計用於關係數據庫的緩存,可以緩存經常訪問的數據,由此減少web程序中數據庫的查詢次數。

2)couchbase buckets。存數據在內存和硬盤。提供高可用性和可動態重新配置的分佈式數據存儲,提供數據持久化和複製服務。couchbase buckets 100% 兼容開源的分佈式緩存memcached

內存分配

Server Quota:

Couchbase服務初始化時會給服務器分配內存限額,表示這個服務器中可用的最大內存,是node級的。初始配置在集羣中的第一臺服務器(node)上,所有服務器的內存配額都是一樣的。例如集羣中有10臺服務器,服務器內存配額是16G,整個集羣中共160G可用內存。如果需要加2個新的服務器,每個新的服務器需要16G的可用內存,集羣中可用的內存數將是192G。

Bucket Quota:

Bucket 內存配額是分配給一個bucket的可用內存。配置在每個節點上,是從server quota中分配出去的。例如,如果你創建了一個新的bucket,限額是1GB,在10個節點的集羣中,彙總後會有10G。如果添加兩個節點,集羣中彙總後會有12G的bucket 限額。

 

從圖上可以看出,增加新的節點就可以擴展總的可用內存,從而增加存儲的數據量。通過bucket限額系統可以判斷數據是否應該調出內存。

vBucket

vBucket相當於一個key的子集,保存的是客戶端存儲對象的key值,vBuckets 用於在集羣的節點間分配數據和備份數據。是 couchbase 實現 auto sharding,在線動態增減節點的重要基礎。不是用戶可訪問的組件,但是至關重要。

通過vbucket,客戶端直接訪問保存信息的服務器,不需要通過中間代理或者其他架構,因此可以從數據中抽象出物理拓撲結構。這種方式使couchbase易擴展。

這種架構不同於memcached使用的架構,memcached的做法是用 key 算出一個 hash,得到服務器列表中的對應服務器。這個列表需要動態維護,還需要一個hash算法用於處理集羣拓撲結構的變化。

如以下代碼所示:

       servers = ['server1:111', 'server2:112', 'server3:113']
       server_for_key(key) = servers[hash(key) % servers.length]

這種算法很簡單,也很容易理解,但也有幾個問題:

1、如果一臺服務器失效,會造成該分片的所有 key 失效。

2、如果服務器容量不同,管理非常麻煩。

3、運維、配置非常不方便。

爲了把 key 跟服務器解耦,couchbase 引入了 vBucket。每個key都屬於一個vbucket,查找對應的value時先用hash函數計算這個key屬於哪個vbucket,再從vBucket 與服務器對應表中查找這個vbucket屬於哪個服務器,映射表保存vbucket和服務器的對應關係,一個bucket一行,一個服務器可以對應多個vbucket。

1、key hash 對應一個 vBucket,不再直接對應服務器。

2、集羣維護一個全局的 vBucket 與服務器對應表。

例如,集羣中有3個服務器,客戶端要查找 一個key對應的value值,首先計算key屬於哪個Vbucket,在這個例子中,hash結果是vB8 ,通過查映射表,客戶端確定vB8對應到服務器C,然後get操作直接發送到服務器C。

 

一段時間後,需要加一個新的服務器D到集羣,vbuckets映射表更新爲:

 

 

這時,客戶端再想取key對應的value值,hash算法結果仍爲vB8,但是新的映射表會將vB8映射到服務器D。

由於 vBucket 把 key 跟服務器的靜態對應關係解耦合,基於 vBucket 可以實現一些非常強大有趣的功能,例如:

Replica,以 vBucket 爲單位的主從備份。如果某個節點失效,只需要更新 vBucket 映射表,馬上啓用備份數據。

動態擴容。新增加一個節點後,可以把部分 vBucket 轉移到新節點上,並更新 vBucket 映射表。

緩存管理

Couchbase自動管理緩存層,確保有足夠的內存空間以維持性能。couchbase後臺有個進程,專門把一定時間沒有被訪問的數據移出內存,這個進程的掃描時間和數據的最大無活動時間都是可以設置的。couchbase在對數據進行增刪時會先體現在內存中,而不會立刻體現在硬盤上,從內存的修改到硬盤的修改這一步驟是由couchbase自動完成,等待執行的硬盤操作會以write queue的形式排隊等待執行,也正是通過這個方法,硬盤的I/O效率在write   queue滿之前是不會影響couchbase的吞吐效率的,而write queue的長度是可以設置的。通過write queue執行大量寫數據庫操作時用戶可能會感受到很短時間的內存飆升,但是異步特性和queue的使用使讀寫速度都非常快。

對於所有文檔couchbase都會建立一個額外的56byte的metadata,這個metadata功能之一就是表明數據狀態是否活動在內存中。同時文檔的id也作爲標識符和metadata一起長期活動在內存中。這表示對文檔id不存在的情況服務器可以直接返回‘文檔id不存在。couchbase官方建議bucket申請的內存中,metadata和key所佔用的內存不應超過一半,否則couchbase的性能會顯著下降。爲了保證這個條件,當有效數據佔用超過一定內存時就需要把超額數據移除了。

 

這裏有低水位和高水位的概念,也就是說當移除數據過多以至於內存中有效數據佔用內存低於低水位的時候,couchbase會隨機挑一些文件到內存中以達到低水位。當有效數據內存佔用超過高水位時,couchbase就會移除數據。高低水位都是可以設置的。

隨着內存數據越來越多,會逐漸到達低水位,這時候,系統不會做任何處理。當數據量持續增加,到達高水位時,系統會啓動一個job任務移除數據,當到達低水位時任務停止。如何進入數據的速度大於移除數據的速度,系統會返回空間不足的錯誤提示,直到有足夠的內存爲止。

如果只使用memcached buckets,服務器只提供數據緩存,不會持久化到硬盤。如果服務器內存空間不足,系統會使用LRU算法從內存中Eviction 數據,Eviction表示服務器會移除一個數據項的key,metadata和所有其他信息。Eviction後,數據將無法恢復。

數據持久化

考慮到性能,couchbase服務主要使用緩存爲客戶端保存和返回信息,同時會逐漸將數據保存到硬盤以維持高可靠性。如果有節點fail了可以直接從硬盤恢復數據,數據是逐漸持久化到硬盤的,同時保存到緩存層和硬盤write queue,不會阻塞客戶線程。當客戶端訪問一個不在內存的數據時,持有load queue的進程會將數據讀到內存,在數據返回之前客戶端需要等待。

多線程讀寫:之前的couchbase版本,讀寫硬盤的線程只有一個。爲了提高讀寫硬盤的速度和提高緩存命中率,現在couchbase提供了多線程讀寫。

多線程讀寫需要考慮線程之間的同步問題以避免衝突。爲了維持性能和避免衝突,couchbase對每個線程訪問的資源進行了靜態分配,同時使用了資源鎖。當創建多個讀寫線程時,服務器爲每個線程單獨分配了不同的vbuckets。通過這種靜態協調方式,可以保證同一個vbuckets只有一個讀線程和一個寫線程可以訪問。上圖表示6個線程和兩個數據vbucket。每個線程有預先分配的可讀寫範圍。

負載均衡

Couchbase 服務器上數據的分配方式是通過vbucket結構實現的,如果想增加或減少集羣中的機器,vbuckets中存儲的數據都需要重新分配,vBucket map(映射表)也需要更新以適應新的集羣結構。

Rebalancing 是集羣結構發生變化時的數據調整,需要手動操作,這個過程改變vbuckets到服務器的分配,需要在服務器節點之間遷移數據以適應新的結構。

Rebalancing過程可以發生在集羣運行和提供服務時,客戶端使用現有架構讀寫數據,同時後端在節點之間遷移數據。一旦這個過程完成, 更新vBucket map表,並通知smart clients和代理服務(MOxi).

Rebalancing後數據在集羣中重新分配,因此數據被均勻分配到整個數據庫,這個過程需要考慮數據和數據的副本。

總結

數據存儲:nosql,易水平擴展。

緩存層:低水位和高水位設置,文檔metadata。

vBucket:使系統易於動態管理,自動分片,reblancing。

多線程持久化:預分配每個線程的訪問範圍,保證性能和可靠性。

參考

https://sq.163yun.com/blog/article/189804692240617472

https://www.cnblogs.com/mydeepthink/p/10013368.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章