MongoDB和Elasticsearch的各使用場景對比

MongoDB vs Elasticsearch
     MongoDB    ElasticSearch    備註
定位    (文檔型)數據庫    (文檔型)搜索引擎    一個管理數據,一個檢索數據
資源佔用    一般    高    mongo使用c++, es使用Java開發
寫入延遲    低    高    es的寫入延遲默認1s, 可配置, 但是要犧牲一些東西
全文索引支持度    一般    非常好    es本來就是搜索引擎, 這個沒啥可比性
有無Schema    無    無    兩者都是無Schema
支持的數據量    PB+    TB+ ~ PB    兩者支持的量並不好說的太死, 都支持分片和橫向擴展, 但是相對來說MongoDB的數據量支持要更大一點
性能    非常好    好    MongoDB在大部分場景性能比es強的多得多
索引結構    B樹    LSM樹    es追求寫入吞吐量, MongoDB讀寫比較均衡
操作接口    TCP    Restful(Http)     
是否支持分片    是    是     
是否支持副本    是    是     
選主算法    Bully(霸凌)    Bully(霸凌)    相比於Paxos和Raft算法實現更簡單並有一定可靠性上的妥協,但是選舉速度比較快
擴展難度    容易    非常容易    es真的是我用過的擴展最方便的存儲系統之一
配置難度    難    非常容易     
地理位置    支持    支持     
運維工具    豐富    一般     
插件和引擎    有多個存儲引擎供選擇    有大量插件可以使用    -
兩者的定位
MongoDB和Elasticsearch都屬於NoSQL大家族, 且都屬於文檔型數據存儲

所以這兩者的很多功能和特性高度重合, 但其實兩者定位完全不同

MongoDB 是 文檔型數據庫, 提供 數據存儲和管理服務
Elasticsearch 是搜索服務, 提供 數據檢索服務

兩者的很大區別在於源數據的存儲和管理

MongoDB作爲一個數據庫產品, 是擁有源數據管理能力的
Elasticsearch作爲一個搜索引擎, 定位是提供數據檢索服務, 也就是說我只管查, 不管寫 _, Elasticsearch的Mapping不可變也是爲此服務的, 帶來的代價就是es不適合作爲數據管理者, es可以從其他數據源同步數據過來提供查詢, 但是不適合自己對數據進行存儲和管理
es更側重數據的查詢, 各種複雜的花式查詢支持的很好, 相比來說 MongoDB的查詢能力就顯得比較平庸了

由此可見, 對於個人, 如果你有一批數據要看, 但是不經常進行修改, 這個時候毫無疑問可以用es, 但是如果你還打算繼續修改數據, 最好就是使用MongoDB,但其實對大多數人公司來講,這兩者的數據管理能力並沒有多大的影響

ps: es修改Mapping的代價非常高, 所以我們一般都是把新數據重新寫入一份新索引,然後直接切換讀取的別名到新的索引

兩者讀寫數據的異同
MongoDB和ElasticSearch都支持全文索引, 雖然MongoDB的全文索引效果完全無法跟es相比(es畢竟是專業的搜索引擎產品, 着重提供數據的檢所支持, 這方面吊打MongoDB也是可以理解的)

MongoDB雖然在支持的部分查詢功能上稍微弱於es, 但是在大部分場景下性能方面完爆es, 不管是讀性能, 還是寫性能

es的寫入延遲默認爲1s, 這個雖然是寫入延遲的範疇, 但是毫無疑問是一大缺點, 雖然可以配置爲更短的時間, 但是這樣就要犧牲一定的數據吞吐量, 會造成更頻繁的磁盤刷新操作

es底層使用Lucene作爲核心引擎, 很多es的設計就是爲了匹配Lucene中的概念, 其實es可以看成一個lucene的proxy層包裝,將lucene的原生接口封裝的更好用, 同時還實現了很多管理和監控等輔助功能, 但是整體來說es上層的模塊和lucene的隔閡還是挺明顯的, 耦合度上有一定的欠缺

MongoDB則是完整的一個單體數據庫產品, 雖然內部的存儲引擎也是可插拔式的, 整體而言還是更加的渾然一體

MongoDB支持多種存儲引擎, 本文所有涉及mongo存儲引擎的只談默認的WiredTiger引擎, 其實還有某些方面更優秀的其他引擎,例如: MongoRocks等

部署和資源佔用
單機部署的話其實MongoDB和Elasticsearch都十分的方便, 不過es相對來說資源佔用更多一點, 性能也比MongoDB要弱一點

集羣化的部署, 我們一般都會選擇分片+副本的部署方式, 這種方式下, es部署起來比MongoDB方便太多, MongoDB要部署一套完整的分片 + 副本模式還是比較麻煩的, 沒有經驗的人部署起來需要一定的學習成本

資源佔用方面, MongoDB可以支持存儲文件類型的數據, 作爲數據庫也有數據壓縮能力, es則因爲大量的索引存在需要佔用大量的磁盤和內存空間

可用性和容錯
MongoDB和ElasticSearch作爲天生分佈式的代表產品都支持數據分片和副本

兩者都通過分片支持水平擴展, 同時都通過副本來支持高可用(HA)

分片就是一個數據集的數據分爲多份, 同時分佈在多個節點上存儲和管理, 主流分片方式有兩種: hash分片和range分片, 兩種分片方式各有優勢, 適合不同的場景

副本就是一份數據集同時有一個或者多個複製品(有些地方叫主從), 每份複製品都一模一樣, 但是爲了保證數據的一致性, 往往多個副本中只有一個作爲Primary副本(通過選主算法從多個副本中選出Primary), 提供寫服務, 其他副本只提供讀, 或者只提供備份服務

ps:es和MongoDB都可以通過副本增強讀能力, 這與kafka很不一樣(kafka的副本只有備份功能)

兩者分佈式方案的一些不同
MongoDB和Elasticsearch雖然都是分佈式服務, 但是還是有一些不同方案的選擇的

分片和副本單位的劃分
MongoDB是以節點爲單位劃分角色, 一旦一個節點被指定爲副本, 其上面的數據都是副本

Elasticsearch是以分片爲單位劃分角色, 一個節點上即可以擁有某分片的主分片和可以同時擁有另一個分片的副本分片, 同時es還支持自動的副本負載均衡, 如果一個新節點上面什麼數據都沒有, 系統會自動分配分片數據過來

架構模式
MongoDB的副本和分片是兩種不同的模式, 雖然可以同時使用但是依然有各自的架構設計, 用戶可以任意選擇選型進行搭配, 每個節點的職責更加專一, 方便據此調整機器配置和進行優化

Elasticsearch中的分片 + 副本是一套統一的架構設計, 每個節點具有接近同等的地位, 配置使用起來更加簡單, 但是如果要針對節點所負責的功能對機器進一步做定製就不如MongoDB靈活

文檔型數據庫的特點和問題
無schema
文檔型數據存儲既能享受無schema限制帶來的靈活, 又能享受索引查詢的快速和類SQL查詢的便捷

使他們用起來不像傳統的RDBMS那麼麻煩, 又不像 Redis,Hbase這種數據庫查詢功能不夠強大, 處在一個傳統RDBMS和經典K-V存儲之間的比較均衡的位置

我個人很喜歡這個特性, 沒有schema的限制, 存儲數據更方便也更靈活了, 但是有得有失, 很多固定schema的好處就無法享受到了, 比如: 對數據的高效壓縮

雞肋的Collection 和 Type
早期爲了跟傳統rdbms數據庫保持概念一致 ,mongodb和elasticsearch都設計了跟傳統數據庫裏面的庫->表->記錄行對應的概念,具體如下

RDBMS    MongoDB    Elasticsearch
庫    庫    索引
表    集合    類型
記錄    文檔    文檔
其實對於nosql數據庫來講, 集合/類型的意義其實不大, Nosql數據庫幾乎都是k-v類型的存儲結構,完全可以通過key進行業務隔離和區分,真的沒有必要爲了跟傳統數據庫對應強行搞出來一箇中間概念 _

Elasticsearch從6.x版本開始強制只允許一個索引使用一個type, 其實就是意識到這個這個設計的失誤, 不想讓你用這個type類型, 因爲type和傳統數據庫裏面的表概念其實是不一樣的,這種概念類比給人造成了誤解,到了es的7.x版本會默認取消type類型, 就說明這個type字段真的是雞肋的不行

弱事務
MongoDB以前只是支持同一文檔內的原子更新, 以此來實現僞事務功能, 不過Mongo4.0支持Replica Set事務, 大大加強了事務方面的能力

es在這方面倒沒有什麼進展,因爲從應用場景上es對事務的需求不高,不過用戶其實也可以使用同文檔更新或者通過程序自己來實現事務機制

無join支持
文檔型數據庫大多數都不支持join(也有少量支持的), 但是我一般也用不上多表join的功能, 即便真的需要使用join也可以通過應用層或者通過耦合數據來實現(不過據說未來Mongo4.2版本會帶來對join的支持)

不支持join帶來的問題就是我們需要自己對數據進行連接, 但是這在擅長使用分佈式計算的大數據領域不算什麼問題, 相應的缺少join功能可能對善於使用SQL的數據分析師就不大友好

Bully的選主算法的缺陷
elasticsearch和MongoDB選擇的選主算法實現很簡單, 但是代價就是有機率出現腦裂的情況, 當然, 具體情況跟配置也有關係(比如:你有三個es節點但是設置的最小主節點數爲1, 將最小主節點數設置爲2可以避免腦裂情況)

不過腦裂問題一方面發生概率較低,另一方面即使出現了腦裂的情況, 使用重啓大法一般就能解決 _

總體來說, 這方面不如使用Paxos和Raft算法或者使用zk做協調器的其他分佈式系統靠譜

其他
運維工具
兩者背後都有商業公司的支持

MongoDB的很多客戶端和運維工具更豐富, 但是MongoDB作爲一個數據庫產品, 相對應的對運維人員的要求也要更高一點

Elasticsearch則有整套的數據分析和收集工具提供, 配套的kibana就是一個很不錯的管控es的工具

操作接口
es使用Restful來提供統一的操作接口, 屏蔽了各種語言之間的障礙, 但是同樣帶來了表達能力和性能的損失

MongoDB則使用TCP, 降低了序列化和網絡這一層的性能損耗, 並最大程度保留了接口的內容表達能力, 但是相對的使用起來就不如http那麼的方便

適用場景
兩者其實在很多使用場景上有重合之處, 是可以互相替代, 比如日誌收集

但是某些方面兩者又各有特色,比如: 如果打算使用一個文檔型的業務數據庫, 那最好還是選mongodb, 如果你有要求複雜查詢又併發性能要求高的場景,類似搜索服務,那最好的選擇是elasticsearch

除此之外:

MongoDB有多個存儲引擎可以選擇, 而且MongoDB不僅看重數據的分析, 對數據的管理同樣看重, 總的來說MongoDB更傾向於數據的存儲和管理, 可以作爲數據源對外提供, 未來說不定還會有支持join和支持倒排索引的mongo引擎出現

Elasticsearch則有很多插件可以使用, 相對來講Elasticsearch更傾向於數據的查詢, 一般情況下elasticsearch僅作爲數據檢索服務和數據分析平臺, 不直接作爲源數據管理者

MongoDB適合
對服務可用性和一致性有高要求
無schema的數據存儲 + 需要索引數據
高讀寫性能要求, 數據使用場景簡單的海量數據場景
有熱點數據, 有數據分片需求的數據存儲
日誌, html, 爬蟲數據等半結構化或圖片,視頻等非結構化數據的存儲
有js使用經驗的人員(MongoDB內置操作語言爲js)
Elasticsearch適合
已經有其他系統負責數據管理
對複雜場景下的查詢需求,對查詢性能有要求, 對寫入及時性要求不高的場景
監控信息/日誌信息檢索
小團隊但是有多語言服務,es擁有restful接口,用起來最方便
總結
MongoDB和Elasticsearch都是我比較喜歡的存儲產品

兩者的功能特性也存在很多重合的地方, 其實現在很多數據庫產品都在互相借(chao)鑑(xi), 功能和特性都在逐漸變得相似, 這也是未來很多存儲產品的發展趨勢, 大家都希望自己能覆蓋儘量多的場景和用戶羣體

很多產品總是在不斷的從沒有->有->功能豐富,但是功能豐富一定是做了很多的妥協, 於是又有了 功能衆多的單體服務->多個功能單一的子服務 方向的轉變,就像三國裏面說的 “天下大勢, 分久必合合久必分”.

現在NoSQL數據庫產品就在這個路上, NoSQL歸根到底都是 RDBMS的某個方面的妥協, 現在各種NoSQL 也都在加入對經典SQL和傳統RDBMS的 join, 事務的支持, 但是我相信等到兩者區別足夠小的時候, 一定會有放棄了大而全, 而專注於某一場景的新的存儲產品出現,到時候搞不好又是一波新的Nosql潮流
 

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