hbase是列數據庫,是kv結構的,ES的基於Lucene的搜索引擎的面向文檔數據庫吧
ES是搜索引擎,主要的優勢在於快速搜索,HBase是數據庫,優勢在於存儲數據,側重點不同
MySQL:關系型數據庫,主要面向OLTP,支持事務,支持二級索引,支持sql,支持主從、Group Replication架構模型(本文全部以Innodb為例,不涉及別的存儲引擎)。
HBase:基於HDFS,支持海量數據讀寫(尤其是寫),支持上億行、上百萬列的,面向列的分布式NoSql數據庫。天然分布式,主從架構,不支持事務,不支持二級索引,不支持sql。
ElasticSearch:ES是一款分布式的全文檢索框架,底層基於Lucene實現,雖然ES也提供存儲,檢索功能,但我一直不認為ES是一款數據庫,但是隨着ES功能越來越強大,與數據庫的界限也越來越模糊。天然分布式,p2p架構,不支持事務,采用倒排索引提供全文檢索。
數據存儲方式
假設有這樣一張人員信息表:
![]()
MySQL中要提前定義表結構,也就是說表共有多少列(屬性)需要提前定義好,並且同時需要定義好每個列所占用的存儲空間。數據以行為單位組織在一起的,假如某一行的某一列沒有數據,也需要占用存儲空間。
HBase則是以列為單位存儲數據,每一列就是一個key-value,HBase的表列(屬性)不用提前定義,而且列可以動態擴展,比如人員信息表中需要添加一個新的“address”字段,MySQL需要提前alter表,HBase的話直接插入即可。
ES比較靈活,索引中的field類型可以提前定義(定義mapping),也可以不定義,如果不定義,會有一個默認類型,不過出於可控性考慮,關鍵字段最好提前定義好。(Solr中必須提前定義好schema.xml文件)
![]()
上圖簡單的展示了數據在MySQL和HBase中存儲差異(和真實的情況還有差距),可以看到即使第二條記錄的sex字段為空,MySQL依然會為該字段保留空間,因為后續有可能會有update語句來更新該記錄,補上sex內容。而HBase則是把每一列都看做是一條記錄,row+列名作為key,data作為value,依次存放。假如某一行的某一個列沒有數據,則直接跳過該列。對於稀疏矩陣的大表,HBase能節省空間。
看到這里,大家是否會有一個疑問:使用HBase存儲時,假如此時需要添加第二行的sex內容,如何實現呢,數據是否連續?后面介紹讀寫流程會解釋。
不一樣的ES
說完MySQL、HBase,這里要重點說一下ES,ES的存儲方式和上面兩個都不一樣,MySQL和HBase是將數據按不同的方式進行存儲,好歹它們存的還是數據,而ES則存的是倒排索引。我們先來了解一下什么是倒排索引,以及為什么需要倒排索引(Inverted Index):
我們肯定都會這樣的經歷:偶然看到一段很好的文字,但是卻不知道出處,這時候去圖書館,一個一個翻找,無疑是大海撈針,這個時候腫么辦呢,於是便有了全文檢索這項技術,而它最核心的就是倒排索引。假如有如下文檔:
![]()
我們想要知道有哪些文檔含有you這個關鍵字,首先可以創建一個倒排索引,格式如下:
![]()
我們把前面的部分叫做dictionary(字典),里面的每個單詞叫做term,后面的文檔列表叫做psoting-list,list中記錄了所有含有該term的文檔id,兩個組合起來就是一個完成的倒排索引(Inverted Index)。能夠看出,假如需要查找含有“you”的文檔時,根據dictionary然后找到對應的posting-list即可。
而全文檢索中,創建Inverted Index是最關鍵也是最耗時的過程,而且真正的Inverted Index結構也遠比圖中展示的復雜,不僅需要對文檔進行分詞(ES里中文可以自定義分詞器),還要計算TF-IDF,方便評分排序(當查找you時,評分決定哪個doc顯示在前面,也就是所謂的搜索排名),壓縮等操作。每接收一個document,ES就會將其信息更新在倒排索引中。
從這里我們就可以看出ES和MySQL、HBase的存儲還是有很大的區別。而且ES不僅包含倒排索引,默認同時還會把文檔doc存儲起來,所以當我們使用ES時,也能拿到完整的文檔信息,所以某種程度上,感覺就像在使用數據庫一樣,但是也可以配置不存儲文檔信息,這時只能根據查詢條件得到文檔id,並不能拿到完整的文檔內容。
總結:MySQL行存儲的方式比較適合OLTP業務。列存儲的方式比較適合OLAP業務,而HBase采用了列族的方式平衡了OLTP和OLAP,支持水平擴展,如果數據量比較大、對性能要求沒有那么高、並且對事務沒有要求的話,HBase也是個不錯的考慮。ES默認對所有字段都建了索引,所以比較適合復雜的檢索或全文檢索。
容災
數據庫系統,數據的完整性和一致性是非常重要的問題,數據庫進程掛了,可以恢復,但是數據丟了,就再也找不回來了。下面說說各個系統的容災方式。
MySQL
單節點:
現在的數據庫普遍采用write ahead log策略來避免數據丟失,wal機制簡單的解釋就是:在提交CUD操作,數據寫入內存的同時,也要寫一份到log文件中,而且要保證log數據落盤成功后才能向client返回操作成功,假如此時數據庫宕機,已經提交到內存的數據還沒來得及刷回磁盤,重啟數據庫后可以通過回放log文件來恢復內存中的數據。
問題又來了:寫log的話,對性能影響會不會很大?其實多少還是有點影響的,不過log文件是順序寫入,相對來說為了保證數據完整性,這點性能損失還是可以接受的。
單機情況下,MySQL的innodb通過redo log和checkpoint機制來保證數據的完整性。因為怕log越寫越大,占用過多磁盤,而且當log特別大的時候,恢復起來也比較耗時。而checkpoint的出現就是為了解決這些問題。
checkpoint機制保證了之前的log數據一定已經刷回磁盤,當數據庫宕機時,只需要將checkpoint之后的log回放即可,數據庫會定時做checkpoint,這樣就保證了數據庫恢復的效率。
但是考慮到如果硬件故障時機器無法啟動,或者磁盤故障時數據無法恢復,checkpoint+redo log方案也就不起作用了,為了防止這種故障,MySQL還提供了master-slave和group replication 集群級別的容災方案。
Master-Slave架構主要思路是:master負責業務的讀寫請求,然后通過binlog復制到slave節點,這樣如果主庫因為不可抗拒因素無法恢復時,從庫可以提供服務,這里我們用了“復制“這個詞,而不是”同步“,因為基於binlog復制的方案並不能做到主從數據強一致,這種主從同步方式會導致主庫掛掉之后從庫有可能丟失少量的數據。
正是因為主從架構存在數據不一致的問題,所以MySQL5.7出現了Mysql Group Replication方案,mgr采用paxos協議實現了數據節點的強同步,保證了所有節點都可以寫數據,並且所有節點讀到的也是最新的數據。(原諒本人水平有限,說不清楚主從架構為什么會丟數據,也講不清楚mgr是怎么實現的,但是這里強烈推薦一本前司同事的書:《MySQL運維內參》,里面詳細解釋了Master-Slave和Group Replication 的架構,是深入理解Mysql的不二之選,據說本書的出現拉低了DBA的門檻,沒有任何打廣告的嫌疑^ ^)
HBase:
HBase的容災和MySQL的單機容災有些類似,但具體實現上還是很有自己的特點。在介紹HBase容災前,我們先來了解一下HBase和HDFS的關系:HBase中的數據都是存放在HDFS上,可以簡單理解HBase分為兩層:一層為NoSql service(即提供分布式檢索服務),一層是分布式文件系統(數據真正存放的位置,目前采用HDFS)。HBase中region分布在不同的regionserver上,client端通過meta表來定位數據在在哪個regionserver的region上,然后獲取數據,但是數據有可能並不一定在該regionserver本地保存,每個region都知道自己對應的數據在HDFS的哪些數據塊上,最后通過訪問HDFS來獲取數據,尤其當HBase和HDFS部署在不同的集群上時,數據的讀寫完全是通過RPC來實現,為了減少RPC的開銷,保證服務穩定,往往會將HBase和HDFS部署在同一個集群。同理,當一個regionserver掛了,region可以快速切換到別的regionserver上,因為只涉及到回放Log,並不會移動已經落盤的數據,而且HBase也會控制log的大小,來減少恢復時間。
HBase也是采用寫log的方式防止數據丟失,數據寫內存的同時,同時也會寫入HLog,HLog也是存儲在HDFS上,寫入HLog后才會認為數據寫成功,某個regionserver掛掉之后,master將故障機器上的regions調度到別的regionserver上,regionserver通過回放HLog來恢復region的數據,恢復成功后,region重新上線,由於log是直接寫在HDFS上,所以不用擔心單個節點掛掉log數據丟失的問題。
這里引出一個問題:回放HLog的時候,正在被恢復的region會短時間不可用,直到HLog回放成功。HBase1.0版本中加入了region replicas功能,也就是提供一個slave region,當主region掛掉的時候,依然可以通過slave replicas來讀數據,但是slave不提供write,而且slave replicas和primary region並不是強同步的,並不一定總能讀到最新的數據,所以開啟該功能時,也要考慮自己業務是否必須要求強一致。
HBase也提供了cluster replication,目的是為了做機房級的容災,boss說現在cluster replication功能還有些bug,目前也在積極優化改進,相信以后會cluster replication會越來越完善。
ES:
ES的容災也是采用寫log的方式,與HBase不同的是,ES的節點保存各自的log,這點跟MySQL類似,log是存放在本地的,這也就存在和MySQL一樣的問題,假如機器宕機或硬盤故障,log數據也會丟失,所以index每個shard也有主備,默認配置是一個primary shard,一個replica shard,當然也可以配置多個replica。
默認情況下:primary shard首先接收client端發送過來的數據,然后將數據同步到replica shard中,當replica shard也寫入成功后,才會告知client數據已正確寫入,這樣就防止數據還沒寫入replica shard時,primary掛掉導致的數據丟失。
又到了提問環節,如果有一個replica節點出了問題,比如網絡故障無法寫入,那豈不是數據一直寫入不成功了?所以ES的master維護了一個in-sync set,里面保存了目前存活、且與primary同步的replica集合,只要set中的replica同步完成即認為數據寫入成功。考慮到一種情況:所有的replica因為網絡故障都下線了,in-sync set此時為空,數據只在primary中保留一份,很有可能因primary故障而導致丟數據,所以ES新增了wait_for_active_shards參數,只有當存活的replica數大於該參數時,才能正常寫入,若不滿足,則停止寫服務。
(這是5.X版本的實現,由於ES版本更新過快,這和2.X之前的版本有些差異,5.X中in-sync set的方式和Kafka的容災模式非常類似,但和Kafka有一點區別:ES的primary負責寫服務,但是primary和replica都可以提供讀服務,而Kafka只有primary partition提供讀寫服務,replica只是同步primary上的數據,並不提供讀。具體為什么Kafka不用replica提供讀服務,大家可以思考一下哈。而ES 2.X之前版本的容災更像ZK,采用quorum的方式,如果不對請指正)
讀寫方式
存儲方式和讀寫方式很大程度上決定了系統的吞吐,本節主要介紹MySQL、HBase、ES各自是如何讀寫數據的。
Mysql
先說說MySQL,MySQL的Innodb中的數據是按主鍵的順序依次存放,主鍵即為聚簇索引(對聚簇索引和非聚簇索引不了解同學可以看看這篇文章),索引采用B+樹結構進行組織。
![]()
從圖中可以看出,數據是按聚簇索引順序依次存放,假設下面一些場景:
1.查詢
Innodb中主鍵即為聚簇索引,假如根據主鍵查詢,聚簇索引的葉子節點存放就是真正的數據,可以直接查到相應的記錄。
假如是二級索引查詢,那么需要先通過二級索引找到該記錄的主鍵,然后根據主鍵通過聚簇索引找到對應的記錄,這里多了一個索引查找的過程。
2.插入
順序插入:因為Innodb的數據是按聚簇索引的順序依次存放的,如果是根據主鍵索引的順序插入,即插入的數據的主鍵是連續的,因為是順序io,所以插入效率會較高。
隨機插入:假如每次插入的數據主鍵是不連續的,MySQL需要取出每條記錄對應的物理block,會引起大量的隨機io,隨機io操作和順序io的性能差距很大,尤其是機械盤。
(Kafka官網提到一個機械盤的順序寫能達到600M/s,而隨機寫可能只有100k/s。As a result the performance of linear writes on aJBODconfiguration with six 7200rpm SATA RAID-5 array is about 600MB/sec but the performance of random writes is only about 100k/sec—a difference of over 6000X.這也是為什么HBase、ES將所有的insert、update、delete操作都統一看成順序寫操作,避免隨機io)
note:這也是為什么MySQL的主鍵通常定義為自增id,不涉及業務邏輯,這樣新數據插入時能保證是順序io。另外MySQL為了提高隨機io的性能,提供了insert buffer的功能。
3.更新 & 刪除
update和delete如果不是順序的話,也會包含大量的隨機io,當然MySQL都針對隨機io都進行了一些優化,盡量減少隨機io帶來的性能損失。
HBase
HBase不支持二級索引,它只有一個主鍵索引,采用LSM樹(LSM可以參考這篇博客)。
![]()
HBase是一個分布式系統,這點跟MySQL不同,它的數據是分散不同的server上,每個table由一個或多個region組成,region分散在集群中的server上,一個server可以負責多個region。
這里有一點需要特別注意:table中各個region的存放數據的rowkey(主鍵)范圍是不會重疊的,可以認為region上數據基於rowkey全局有序,每個region負責它自己的那一部分的數據。
1.查詢
假如我們要查詢rowkey=150的這條記錄,首先從zk中獲取hbase:meta表(存放region和key的對應關系的元數據表)的位置,通過查詢meta表得知rowkey=150的數據在哪個server的哪個region上。
2.插入
![]()
上圖粗略的展示了HBase的region的結構,region不單單是一個文件,它是由一個memstore和多個storeFile組成(storeFile上的上限可以配置)。插入數據時首先將數據寫入memstore,當memstore大小達到一定閾值,將memstore flush到硬盤,變成一個新的storeFile。flush的時候會對memstore中的數據進行排序,壓縮等操作。可以看到單個storeFile中的數據是有序的,但是region中的storeFile間的數據不是全局有序的。
這樣有的好處就是:不管主鍵是否連續,所有的插入一律變成順序寫,大大提高了寫入性能。
看到這里大家可能會有一個疑問:這種寫入方式導致了一條記錄如果不是一次性插入,很可能分散在不同的storeFile中,那在該region上面查詢一條記錄時,怎么知道去找哪個storeFile呢?答案就是:全部查詢。HBase會采用多路歸並的方式,對該region上的所有storeFile進行查詢,直到找到符合條件的記錄。所以HBase的擁有很好的寫入性能,但是讀性能較差。
當然HBase也做了很多優化,比如每個storeFile都有自己的index、用於過濾的bloom filter、compaction:按可配置的方式將多個storeFile合並成一個,減少檢索時打開的文件數。
3.更新 & 刪除
HBase將更新和刪除也全部看做插入操作,用timestamp和delete marker來區分該記錄是否是最新記錄、是否需要刪除。也正是因為這樣,除了查詢,其他的操作統一轉換成了順序寫,保證了HBase高效的寫性能。
ES
ES的也是一個分布式系統,與ES類似的還有一個叫Solr的項目,都是基於Lucene的全文檢索分布式框架,有興趣的可以去Lucene官網了解,這里就不做對比了。
![]()
上如展示了ES和傳統數據庫的概念對比。下面的介紹中,統一使用index對應DB中table,doc對應table中的記錄,field對應row中的一列。
ES集群由一個或多個node組成,一個node即為一個ES服務進程。一個index由多個分片shard組成,shard分散在各個node上面,每個shard都采用Lucene來創建倒排索引,維護各自的索引數據。
![]()
圖中的一個小方框即為一個shard,出於容災考慮,每個shard都會有多副本,副本個數可以配置,默認為2,綠色的即為primary shard,灰色的即為replica shard。
1.插入
先來說說寫入吧,由於有多個shard,請求過來時,如何判斷寫入到哪個shard呢,ES中每個doc都會有一個唯一id,默認會對id取hash值,根據shard的個數mode到對應的shard上,默認情況下shard中的數據id不是全局有序的,這點和Mysql、HBase有很大區別。
ES的寫入和HBase有些類似,也是將所有的寫操作變成順序寫,也是先將數據寫入內存,然后一段時間后會將內存數據flush到磁盤,磁盤的索引文件會定時進行merge,保證索引文件不會過多而影響檢索性能。
另外提一點,數據存入ES后並不是立馬就能檢索到,這點跟MySQL和HBase,或者說跟數據庫系統是完全不一樣的。主要是因為由於Inverted Index結構的復雜,需要一個專門的indexReader來查詢數據,但是indexReader是以snapshot的方式打開的索引,也就是說indexReader看不到之后的新數據。所以ES提供了一個refresh功能,refresh會重新打開indexReader,使其能夠讀到最新的數據。默認refresh的間隔是1s,所以ES自稱是近實時檢索功能。
說到順序寫,這時候大家可能會想:那ES的寫入速度和HBase差不多嘍?那,其實不是的,不止不如而且差的還不是一點點,因為ES多了兩個最關鍵的步驟:build index和refresh index!這兩個過程是很耗時的: build index時需要分詞、計算權重等復雜的操作(對inverted index創建,檢索感興趣的,可以參考《信息檢索導論》)。而refresh會重新打開index,這兩個過程加起來導致ES接收文檔的速率並不高(可以通過bulk方式來加快數據導入)。但也正是因為這些過程才使ES有強大的檢索功能。(雖然我insert慢,但是我花樣多呀^ ^)
2.讀取
每個node都可以接收讀request,然后該node會把request分發到含有該index的shard的節點上,對應的節點會查詢、並計算出符合條件的文檔,排序后結果匯聚到分發request的node(所以查詢請求默認會輪循的將發送到各個節點上,防止請求全部打到一個節點),由該node將數據返回給client。(ES也支持指定shard查詢,默認是根據文檔id進行路由,相當於主鍵查詢,但是假如不能確定數據在哪個shard上時,還是需要查詢所有shard)
這里要強調一下,由於ES支持全文檢索,根據Inverted Index的特性,大部分情況下,一個關鍵字對應了很多的doc,如果全部返回,數據量較大,會對集群造成較大壓力,所以ES默認只返回權重最高的前20條記錄(可配置),也可以通過scroll功能獲取全部數據。類似的場景跟我們平時使用baidu、google是一樣的,我們使用搜索引擎時,往往是希望得到關聯性最強的top N文檔,並不關心全部文檔有多少個,這也是為什么要計算權重的原因。
現在的ES的功能越來越豐富,不僅僅包含全文檢索的功能,而且還有統計分析等功能,說它是全文檢索框架吧,它比全文檢索功能要豐富,說它是數據庫吧,但是它不支持事務,只能說現在各個框架之間的界限越來越模糊了。
3.更新 &刪除
ES的更新和刪除和HBase類似,也是全部看做是插入操作,通過timestamp和delete marker來區分。
又到了問題環節 :D :既然這種將更新刪除統一變成順序寫的方式能夠提高寫性能,那它難道沒有什么壞處嗎?
答案是肯定有的呀,這種方式能夠有效的提升寫性能,但是存在一個很大的問題就是后台經常會需要merge,而merge是一個非常耗資源的過程,對於某些穩定性要求較高的業務來說,這是不能接受的,但是不merge的話,又會降低查詢性能(過多的小文件影響查詢性能)。目前通用的做法是盡量選擇業務低峰期進行merge操作。
轉載自:https://www.jianshu.com/p/4e412f48e820使用場景
說了這么多,其實還是希望對MySQL,HBase,ES各自的實現做下對比,方便我們根據業務特點選擇最合適的存儲、檢索方案。下面說一下筆者在工作中使用的經驗:
![]()
MySQL在三款中最為成熟,而且支持事務,支持二級索引,容災備份方案也最為成熟,所以線上核心業務Mysql是不二之選(當然如果不差錢,Oracle也挺不錯,而且出問題自己解決不了的話,打電話就可以了,手動斜眼)。
HBase因為其強大的寫入能力和水平擴展能力,比較適合存儲日志,用戶行為等數據量比較大的數據,這種數據一般不涉及事務級別的讀寫,對二級索引的需求也不是很高。而且HBase的主鍵不像Mysql,往往是涉及到業務邏輯的,如果查詢條件單一的話,可以把直接把需要查詢的字段作為主鍵的一部分,類似MySQL的聯合索引,來提供檢索功能。
ES現在不僅提供全文檢索,還提供統計功能,並且提供的Restful接口非常好用,配上Kibana還可以進行圖形化展示,第三方插件也很豐富。雖然ES可以水平擴展,但是考慮到ES的大部分檢索都會檢索該index的所有shard,如果單個index數據過大,性能多少也會受到影響,所以單個index的大小最好控制在一定的范圍,比如存儲用戶行為日志的index,可以每隔一段時間歸一次檔,創建新的index,做到冷熱分離。而且ES也可以作為MySQL或HBase的索引來使用,雖然Mysql也有索引功能,但是過多的索引往往會拖累MySQL的性能,並且線上MySQL數據庫一般也不允許執行統計類的sql,這時可以用ES輔助實現統計,HBase因為只有主鍵檢索,所以更需要二級索引的功能。
舉一個筆者前司組合使用的場景:trace系統的log數據以HBase作為主要存儲,同時最近三個月的數據也在ES里面保留一份,ES主要用來完成各種復雜檢索、統計。但數據同步需要業務自己實現,當然trace業務對一致性要求不那么高,也可以忽略這個問題。
tip:將數據庫的數據向ES中同步的時候,因為網絡延遲等問題,到達的順序可能會亂序,這時老數據有可能會覆蓋新的數據,ES提供了一個version功能,可以將數據的timestamp作為version值,防止舊version的數據覆蓋新version的數據。
展望
傳統的關系型數據庫有着強大的事物處理能力,滿足了大部分線上業務需求,但是水平擴展性一直是一個頭疼的問題,NoSql數據庫雖然解決了水平擴展問題,但是功能太單一,現在越來越多的公司開始着手研究新一代NewSQL數據庫,結合了關系型數據庫的優點外還擁有水平擴展能力,比如淘寶的Oceanbase,PingCAP的TiDB,國外的CockroachDB,讓我們做好擁抱NewSQL的准備吧。
-------
The most popular ones
Redis (V3.2)
- Written in: C
- Main point: Blazing fast
- License: BSD
- Protocol: Telnet-like, binary safe
- Disk-backed in-memory database,
- Master-slave replication, automatic failover
- Simple values or data structures by keys
- but complex operations like ZREVRANGEBYSCORE.
- INCR & co (good for rate limiting or statistics)
- Bit and bitfield operations (for example to implement bloom filters)
- Has sets (also union/diff/inter)
- Has lists (also a queue; blocking pop)
- Has hashes (objects of multiple fields)
- Sorted sets (high score table, good for range queries)
- Lua scripting capabilities
- Has transactions
- Values can be set to expire (as in a cache)
- Pub/Sub lets you implement messaging
- GEO API to query by radius (!)
Best used: For rapidly changing data with a foreseeable database size (should fit mostly in memory).
For example: To store real-time stock prices. Real-time analytics. Leaderboards. Real-time communication. And wherever you used memcached before.
Cassandra (2.0)
- Written in: Java
- Main point: Store huge datasets in "almost" SQL
- License: Apache
- Protocol: CQL3 & Thrift
- CQL3 is very similar SQL, but with some limitations that come from the scalability (most notably: no JOINs, no aggregate functions.)
- CQL3 is now the official interface. Don't look at Thrift, unless you're working on a legacy app. This way, you can live without understanding ColumnFamilies, SuperColumns, etc.
- Querying by key, or key range (secondary indices are also available)
- Tunable trade-offs for distribution and replication (N, R, W)
- Data can have expiration (set on INSERT).
- Writes can be much faster than reads (when reads are disk-bound)
- Map/reduce possible with Apache Hadoop
- All nodes are similar, as opposed to Hadoop/HBase
- Very good and reliable cross-datacenter replication
- Distributed counter datatype.
- You can write triggers in Java.
Best used: When you need to store data so huge that it doesn't fit on server, but still want a friendly familiar interface to it.
For example: Web analytics, to count hits by hour, by browser, by IP, etc. Transaction logging. Data collection from huge sensor arrays.
MongoDB (3.2)
- Written in: C++
- Main point: JSON document store
- License: AGPL (Drivers: Apache)
- Protocol: Custom, binary (BSON)
- Master/slave replication (auto failover with replica sets)
- Sharding built-in
- Queries are javascript expressions
- Run arbitrary javascript functions server-side
- Geospatial queries
- Multiple storage engines with different performance characteristics
- Performance over features
- Document validation
- Journaling
- Powerful aggregation framework
- On 32bit systems, limited to ~2.5Gb
- Text search integrated
- GridFS to store big data + metadata (not actually an FS)
- Has geospatial indexing
- Data center aware
Best used: If you need dynamic queries. If you prefer to define indexes, not map/reduce functions. If you need good performance on a big DB. If you wanted CouchDB, but your data changes too much, filling up disks.
For example: For most things that you would do with MySQL or PostgreSQL, but having predefined columns really holds you back.
ElasticSearch (0.20.1)
- Written in: Java
- Main point: Advanced Search
- License: Apache
- Protocol: JSON over HTTP (Plugins: Thrift, memcached)
- Stores JSON documents
- Has versioning
- Parent and children documents
- Documents can time out
- Very versatile and sophisticated querying, scriptable
- Write consistency: one, quorum or all
- Sorting by score (!)
- Geo distance sorting
- Fuzzy searches (approximate date, etc) (!)
- Asynchronous replication
- Atomic, scripted updates (good for counters, etc)
- Can maintain automatic "stats groups" (good for debugging)
Best used: When you have objects with (flexible) fields, and you need "advanced search" functionality.
For example: A dating service that handles age difference, geographic location, tastes and dislikes, etc. Or a leaderboard system that depends on many variables.
Classic document and BigTable stores
CouchDB (V1.2)
- Written in: Erlang
- Main point: DB consistency, ease of use
- License: Apache
- Protocol: HTTP/REST
- Bi-directional (!) replication,
- continuous or ad-hoc,
- with conflict detection,
- thus, master-master replication. (!)
- MVCC - write operations do not block reads
- Previous versions of documents are available
- Crash-only (reliable) design
- Needs compacting from time to time
- Views: embedded map/reduce
- Formatting views: lists & shows
- Server-side document validation possible
- Authentication possible
- Real-time updates via '_changes' (!)
- Attachment handling
- thus, CouchApps (standalone js apps)
Best used: For accumulating, occasionally changing data, on which pre-defined queries are to be run. Places where versioning is important.
For example: CRM, CMS systems. Master-master replication is an especially interesting feature, allowing easy multi-site deployments.
Accumulo (1.4)
- Written in: Java and C++
- Main point: A BigTable with Cell-level security
- License: Apache
- Protocol: Thrift
- Another BigTable clone, also runs of top of Hadoop
- Originally from the NSA
- Cell-level security
- Bigger rows than memory are allowed
- Keeps a memory map outside Java, in C++ STL
- Map/reduce using Hadoop's facitlities (ZooKeeper & co)
- Some server-side programming
Best used: If you need to restict access on the cell level.
For example: Same as HBase, since it's basically a replacement: Search engines. Analysing log data. Any place where scanning huge, two-dimensional join-less tables are a requirement.
HBase (V0.92.0)
- Written in: Java
- Main point: Billions of rows X millions of columns
- License: Apache
- Protocol: HTTP/REST (also Thrift)
- Modeled after Google's BigTable
- Uses Hadoop's HDFS as storage
- Map/reduce with Hadoop
- Query predicate push down via server side scan and get filters
- Optimizations for real time queries
- A high performance Thrift gateway
- HTTP supports XML, Protobuf, and binary
- Jruby-based (JIRB) shell
- Rolling restart for configuration changes and minor upgrades
- Random access performance is like MySQL
- A cluster consists of several different types of nodes
Best used: Hadoop is probably still the best way to run Map/Reduce jobs on huge datasets. Best if you use the Hadoop/HDFS stack already.
For example: Search engines. Analysing log data. Any place where scanning huge, two-dimensional join-less tables are a requirement.
Hypertable (0.9.6.5)
- Written in: C++
- Main point: A faster, smaller HBase
- License: GPL 2.0
- Protocol: Thrift, C++ library, or HQL shell
- Implements Google's BigTable design
- Run on Hadoop's HDFS
- Uses its own, "SQL-like" language, HQL
- Can search by key, by cell, or for values in column families.
- Search can be limited to key/column ranges.
- Sponsored by Baidu
- Retains the last N historical values
- Tables are in namespaces
- Map/reduce with Hadoop
Best used: If you need a better HBase.
For example: Same as HBase, since it's basically a replacement: Search engines. Analysing log data. Any place where scanning huge, two-dimensional join-less tables are a requirement.
Graph databases
OrientDB (2.0)
- Written in: Java
- Main point: Document-based graph database
- License: Apache 2.0
- Protocol: binary, HTTP REST/JSON, or Java API for embedding
- Has transactions, full ACID conformity
- Can be used both as a document and as a graph database (vertices with properties)
- Both nodes and relationships can have metadata
- Multi-master architecture
- Supports relationships between documents via persistent pointers (LINK, LINKSET, LINKMAP, LINKLIST field types)
- SQL-like query language (Note: no JOIN, but there are pointers)
- Web-based GUI (quite good-looking, self-contained)
- Inheritance between classes. Indexing of nodes and relationships
- User functions in SQL or JavaScript
- Sharding
- Advanced path-finding with multiple algorithms and Gremlin traversal language
- Advanced monitoring, online backups are commercially licensed
Best used: For graph-style, rich or complex, interconnected data.
For example: For searching routes in social relations, public transport links, road maps, or network topologies.
Neo4j (V1.5M02)
- Written in: Java
- Main point: Graph database - connected data
- License: GPL, some features AGPL/commercial
- Protocol: HTTP/REST (or embedding in Java)
- Standalone, or embeddable into Java applications
- Full ACID conformity (including durable data)
- Both nodes and relationships can have metadata
- Integrated pattern-matching-based query language ("Cypher")
- Also the "Gremlin" graph traversal language can be used
- Indexing of nodes and relationships
- Nice self-contained web admin
- Advanced path-finding with multiple algorithms
- Indexing of keys and relationships
- Optimized for reads
- Has transactions (in the Java API)
- Scriptable in Groovy
- Clustering, replication, caching, online backup, advanced monitoring and High Availability are commercially licensed
Best used: For graph-style, rich or complex, interconnected data.
For example: For searching routes in social relations, public transport links, road maps, or network topologies.
The "long tail"
Couchbase (ex-Membase) (2.0)
- Written in: Erlang & C
- Main point: Memcache compatible, but with persistence and clustering
- License: Apache
- Protocol: memcached + extensions
- Very fast (200k+/sec) access of data by key
- Persistence to disk
- All nodes are identical (master-master replication)
- Provides memcached-style in-memory caching buckets, too
- Write de-duplication to reduce IO
- Friendly cluster-management web GUI
- Connection proxy for connection pooling and multiplexing (Moxi)
- Incremental map/reduce
- Cross-datacenter replication
Best used: Any application where low-latency data access, high concurrency support and high availability is a requirement.
For example: Low-latency use-cases like ad targeting or highly-concurrent web apps like online gaming (e.g. Zynga).
Scalaris (0.5)
- Written in: Erlang
- Main point: Distributed P2P key-value store
- License: Apache
- Protocol: Proprietary & JSON-RPC
- In-memory (disk when using Tokyo Cabinet as a backend)
- Uses YAWS as a web server
- Has transactions (an adapted Paxos commit)
- Consistent, distributed write operations
- From CAP, values Consistency over Availability (in case of network partitioning, only the bigger partition works)
Best used: If you like Erlang and wanted to use Mnesia or DETS or ETS, but you need something that is accessible from more languages (and scales much better than ETS or DETS).
For example: In an Erlang-based system when you want to give access to the DB to Python, Ruby or Java programmers.
Aerospike (3.4.1)
- Written in: C
- Main point: Speed, SSD-optimized storage
- License: License: AGPL (Client: Apache)
- Protocol: Proprietary
- Cross-datacenter replication is commercially licensed
- Very fast access of data by key
- Uses SSD devices as a block device to store data (RAM + persistence also available)
- Automatic failover and automatic rebalancing of data when nodes or added or removed from cluster
- User Defined Functions in LUA
- Cluster management with Web GUI
- Has complex data types (lists and maps) as well as simple (integer, string, blob)
- Secondary indices
- Aggregation query model
- Data can be set to expire with a time-to-live (TTL)
- Large Data Types
Best used: Any application where low-latency data access, high concurrency support and high availability is a requirement.
For example: Storing massive amounts of profile data in online advertising or retail Web sites.
RethinkDB (2.1)
- Written in: C++
- Main point: JSON store that streams updates
- License: License: AGPL (Client: Apache)
- Protocol: Proprietary
- JSON document store
- Javascript-based query language, "ReQL"
- ReQL is functional, if you use Underscore.js it will be quite familiar
- Sharded clustering, replication built-in
- Data is JOIN-able on references
- Handles BLOBS
- Geospatial support
- Multi-datacenter support
Best used: Applications where you need constant real-time upates.
For example: Displaying sports scores on various displays and/or online. Monitoring systems. Fast workflow applications.