聊聊數(shù)據(jù)存儲系統(tǒng)Couchbase與Redis
背景
Redis 和Couchbase都是基于內(nèi)存的數(shù)據(jù)存儲系統(tǒng)。在它們各自的官方描述中,Couchbase是高性能,高伸縮性和高可用的分布式緩存系統(tǒng);Redis是一個開源的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲系統(tǒng)。
Couchbase
介紹
2012年2月,CouchOne與Membase合并,Couchbase基于Membase與CouchDB開發(fā)了一款新產(chǎn)品。 CouchBase是一款開源的、分布式的、面向文檔的NoSQL數(shù)據(jù)庫,主要用于分布式緩存和數(shù)據(jù)存儲領(lǐng)域,Membase 是 NoSQL 家族的一個新的重量級的成員,它是個鍵/值、持久化、可伸縮的解決方案,使用了memcached wire協(xié)議。CouchOne支持CouchDB。CouchDB是個文檔數(shù)據(jù)庫,提供了端到端的復(fù)制方法,這對于移動與分布在不同位置的數(shù)據(jù)中心來說是很有用的。CouchBase能夠通過manage cache提供快速的亞毫米級別的k-v存儲操作,并且提供快速的查詢和其功能強大的能夠指定SQL-like查詢的查詢引擎。Couchbase是一個較新的、發(fā)展迅速的nosql數(shù)據(jù)庫技術(shù)。
特點
couchbase是一個非關(guān)系型數(shù)據(jù)庫,它實際上是由couchdb+membase組成,所以它既能像couchdb那樣存儲json文檔,也能像membase那樣高速存儲鍵值對。主要有以下幾個特點:
- 速度快:由于是內(nèi)存優(yōu)先的高性能設(shè)計,所有的讀寫操作都是直接操作內(nèi)存,因此速度非???。
- 高可用:主要從兩個方面,一個是它自帶集群方案,支持多副本模式,另一個是它自帶持久化方案,可以設(shè)置定時把數(shù)據(jù)異步寫到文件系統(tǒng)上。
- 配置使用方便:安裝后自帶web管理臺,可以在管理臺上對集群、桶、索引、搜索等進行管理和操作,大量減輕運維的工作,使用簡單。
- 快速構(gòu)建:Couchbase 使開發(fā)人員能夠構(gòu)建響應(yīng)迅速且靈活的云、移動和邊緣計算應(yīng)用程序,這些應(yīng)用程序可以輕松擴展。
數(shù)據(jù)模型
Couchbase 數(shù)據(jù)模型基于 JSON,它支持基本的數(shù)據(jù)類型,例如數(shù)字和字符串;和復(fù)雜類型,例如嵌入式文檔和數(shù)組,單個Document通常代表應(yīng)用程序代碼中對象的單個實例。一個Document可能被認(rèn)為等同于關(guān)系型數(shù)據(jù)庫中的一行;每個Document的屬性都相當(dāng)于一列。然而,Couchbase 提供了比關(guān)系數(shù)據(jù)庫更大的靈活性,因為它可以存儲具有不同模式的 JSON 文檔。Document可以包含嵌套結(jié)構(gòu),這允許開發(fā)人員表達多對多關(guān)系,而不需要引用或join表。
buckets
buckets是couchbase中組織數(shù)據(jù)的一種方式,類似于關(guān)系型數(shù)據(jù)庫中的databse,一個集群最多可以創(chuàng)建30個buckets。每個存儲buckets必須指定為以下三種類型之一。
- Couchbase buckets:這些類型數(shù)據(jù)持久存儲在內(nèi)存和硬盤中。它們允許使用DCP(Database Change Protocol) 自動復(fù)制數(shù)據(jù)以實現(xiàn)高可用性;并通過XDCR (Cross Data Center Replication)跨多個集群動態(tài)擴展。
- Ephemeral buckets:這是 Couchbase buckets的替代方案,可在不需要持久性時使用。數(shù)據(jù)僅在內(nèi)存中。
- Memcached buckets:只存儲在內(nèi)存中,遵循Memcached協(xié)議,現(xiàn)在已經(jīng)棄用。
同步協(xié)議
DCP (Database Change Protocol),DCP 協(xié)議是一個高效的二進制協(xié)議,它主要用于集群內(nèi)的數(shù)據(jù)復(fù)制、索引復(fù)制、備份數(shù)據(jù)等等。主要概念有以下幾點:
- 有序復(fù)制,基于每個vbucket存在一個順序序列號,同步時根據(jù)序列號進行更新。
- 重啟恢復(fù),當(dāng)同步連接中斷后,重新連接后,會對沖突數(shù)據(jù)進行恢復(fù)。
- 一致性,使用快照數(shù)據(jù)同步數(shù)據(jù)統(tǒng)一性。
- 內(nèi)存間復(fù)制。
XDCR (Cross Data Center Replication),XDCR提供了多個有效vbucket的數(shù)據(jù)的復(fù)制,主要用于跨數(shù)據(jù)中心的多集群間的復(fù)制,可以跨版本復(fù)制。主要概念有以下幾點:
- 基于bucket復(fù)制,兩個集群的同一個bucket可以實現(xiàn)單向或者雙向復(fù)制。
- 通過DCP協(xié)議保持持續(xù)性復(fù)制,一個XDCR連接中包括多個DCP數(shù)據(jù)流。這些流可以根據(jù)不同的分區(qū)對目的集群進行同步復(fù)制。
- 支持多種集群拓?fù)鋸?fù)制。集群間可以通過單向,雙向復(fù)制。多個集群可以實現(xiàn)1對1,1對多,多對1等的集群復(fù)制拓?fù)鋱D。
- 安全復(fù)制。數(shù)據(jù)中心見傳輸數(shù)據(jù)可以使用SSL進行加密。
- 最終一致性和解決數(shù)據(jù)沖突的能力。當(dāng)出現(xiàn)沖突數(shù)據(jù),會使用元數(shù)據(jù)的序列值,CAS值,文檔標(biāo)簽和過期時間限制對數(shù)據(jù)進行沖突解決。
服務(wù)
Couchbase 服務(wù)器提供以下服務(wù):
- Data service(數(shù)據(jù)服務(wù)):數(shù)據(jù)服務(wù)提供完全集成的內(nèi)存緩存層,提供高速數(shù)據(jù)訪問,支持鍵指定的數(shù)據(jù)項的存儲、設(shè)置和檢索。
- Query service(查詢服務(wù)):類sql查詢語言獲取結(jié)果,還可以針對數(shù)據(jù)定義(定義索引)和數(shù)據(jù)操作(添加或刪除數(shù)據(jù))發(fā)出查詢。
- Index service(索引服務(wù)):創(chuàng)建索引,為Analytics和Query使用,索引服務(wù)支持為存儲在 Couchbase 集群中的項目,創(chuàng)建主索引和二級索引。
- Analytics service(分析服務(wù)):分析服務(wù)提供并行數(shù)據(jù)管理功能,允許運行復(fù)雜的分析查詢,適用于大數(shù)量,運行時間長,資源消耗比較大。
- Search Service (搜索服務(wù)):搜索服務(wù)為集群數(shù)據(jù) 提供全文索引和搜索引擎功能。
- Event Service(事件服務(wù)):支持對數(shù)據(jù)更改的近乎實時的處理:代碼既可以響應(yīng)文檔突變而執(zhí)行,也可以按照計時器的調(diào)度執(zhí)行。
- Backup Service(備份服務(wù)):支持計劃完整和增量數(shù)據(jù)備份,既可以針對特定的單個存儲桶,也可以針對集群上的所有存儲桶。
Redis
介紹
Remote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo寫的key-value存儲系統(tǒng),它 是一個開源(BSD許可)的內(nèi)存型數(shù)據(jù)存儲系統(tǒng),支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的AP以及豐富的數(shù)據(jù)結(jié)構(gòu),它可以用作數(shù)據(jù)庫、緩存和消息中間件。并支持事務(wù)、發(fā)布訂閱、lua腳本、lru驅(qū)動事件、過期機制、自動故障轉(zhuǎn)移等多種功能,由于Redis 是用ANSI C編寫的,可在大多數(shù) POSIX 系統(tǒng)(如 Linux、*BSD 和 OS X)中運行,無需外部依賴。
特點
- 內(nèi)存數(shù)據(jù)庫,速度快,也支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時候可以再次加載進行使用。
- Redis不僅僅支持簡單的key-value類型的數(shù)據(jù),同時還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲。
- Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。
- Redis的所有數(shù)據(jù)存儲在內(nèi)存中,對數(shù)據(jù)的更新將異步地保存到磁盤上。
- 功能豐富。除了支持五種數(shù)據(jù)結(jié)構(gòu)之外,還支持事務(wù)、流水線、發(fā)布/訂閱、消息隊列等功能。
- (服務(wù)架構(gòu))支持高可用和分布式。
持久化
redis 提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。
- RDB,簡而言之,就是在不同的時間點,將 redis 存儲的數(shù)據(jù)生成快照并存儲到磁盤等介質(zhì)上。
- AOF,則是換了一個角度來實現(xiàn)持久化,那就是將 redis 執(zhí)行過的所有寫指令記錄下來,在下次 redis 重新啟動時,只要把這些寫指令從前到后再重復(fù)執(zhí)行一遍,就可以實現(xiàn)數(shù)據(jù)恢復(fù)了。
其實 RDB 和 AOF 兩種方式也可以同時使用,在這種情況下,如果 redis 重啟的話,則會優(yōu)先采用 AOF 方式來進行數(shù)據(jù)恢復(fù),這是因為 AOF 方式的數(shù)據(jù)恢復(fù)完整度更高。如果你沒有數(shù)據(jù)持久化的需求,也完全可以關(guān)閉 RDB 和 AOF 方式,這樣的話,redis 將變成一個純內(nèi)存數(shù)據(jù)庫,就像 memcache 一樣。
集群管理
Redis在3.0版本以后開始支持集群,經(jīng)過中間幾個版本的不斷更新優(yōu)化,最新的版本集群功能已經(jīng)非常完善,Redis 集群是一個提供在多個Redis間節(jié)點間共享數(shù)據(jù)的程序集,集群節(jié)點共同構(gòu)建了一個去中心化的網(wǎng)絡(luò),集群中的每個節(jié)點擁有平等的身份,節(jié)點各自保存各自的數(shù)據(jù)和集群狀態(tài)。節(jié)點之間采用Gossip協(xié)議進行通信,保證了節(jié)點狀態(tài)的信息同步。Redis 集群數(shù)據(jù)通過分區(qū)來進行管理,每個節(jié)點保存集群數(shù)據(jù)的一個子集。數(shù)據(jù)的分配采用一種叫做哈希槽(hash slot)的方式來分配,和傳統(tǒng)的一致性哈希不太相同。Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽。為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,集群使用了主從復(fù)制模型。讀取數(shù)據(jù)時,根據(jù)一致性哈希算法到對應(yīng)的 master 節(jié)點獲取數(shù)據(jù),如果master 掛掉之后,會啟動一個對應(yīng)的 salve 節(jié)點來充當(dāng) master 。在redis3.0以前的版本要實現(xiàn)集群一般是借助哨兵sentinel工具來監(jiān)控master節(jié)點的狀態(tài),如果master節(jié)點異常,則會做主從切換,將某一臺slave作為master,哨兵的配置略微復(fù)雜,并且性能和高可用性等各方面表現(xiàn)一般,特別是在主從切換的瞬間存在訪問瞬斷的情況,而且哨兵模式只有一個主節(jié)點對外提供服務(wù),沒法支持很高的并發(fā),且單個主節(jié)點內(nèi)存也不宜設(shè)置得過大,否則會導(dǎo)致持久化文件過大,影響數(shù)據(jù)恢復(fù)或主從同步的效率。
總結(jié)
其實不論是在大塊數(shù)據(jù)還是大數(shù)據(jù)量的處理上,Couchbase都要優(yōu)于Redis,很多平臺都是采用Couchbase來管理數(shù)千萬熱數(shù)據(jù)。所以,如果緩存大多數(shù)情況下僅僅需要提供數(shù)據(jù)新增和查詢操作,那Couchbase基于文檔類型的存儲結(jié)構(gòu)能夠始終如一地為提供亞毫秒的查詢體驗,對于預(yù)定義的數(shù)據(jù)類型你還可以通過創(chuàng)建索引進一步優(yōu)化性能,這種情況下,Couchbase無疑是你更好的選擇。
- Redis支持服務(wù)器端的數(shù)據(jù)操作:Redis相比Couchbase來說,擁有更多的數(shù)據(jù)結(jié)構(gòu)和并支持更豐富的數(shù)據(jù)操作,通常在Couchbase里,你需要將數(shù)據(jù)拿到客戶端來進行類似的修改再set回去(你需要先先通過get方法從服務(wù)器讀取數(shù)據(jù)文檔,并將文檔反序列化為json對象,之后修改json對象對應(yīng)屬性,再通過set方法將數(shù)據(jù)寫入服務(wù)器,序列化后進行存儲)。這大大增加了網(wǎng)絡(luò)IO的次數(shù)和傳輸中的數(shù)據(jù)體積。在Redis中,這些復(fù)雜的操作通常和一般的GET/SET一樣高效。
- 內(nèi)存使用效率對比:使用簡單的key-value存儲的話,Couchbase的內(nèi)存利用率更高,而Redis采用hash結(jié)構(gòu)來做key-value存儲,由于其組合式的壓縮,其內(nèi)存利用率會高于Couchbase。所以,如果需要緩存能夠支持更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和更頻繁數(shù)據(jù)的部分更新操作,那么Redis會是不錯的選擇。(下文會在關(guān)于數(shù)據(jù)存儲模型來證明這一點)。
- 性能對比:由于Redis只使用單核,而Couchbase可以使用多核,所以平均每一個核上Redis在存儲小數(shù)據(jù)時比Couchbase性能更高。而在100k以上的數(shù)據(jù)中,Couchbase性能要高于Redis,雖然Redis最近也在存儲大數(shù)據(jù)的性能上進行優(yōu)化,但是比起Couchbase,還是稍有遜色。