草庐IT

MongoDB和Elasticsearch的各使用场景对比

寒人病酒 2023-03-28 原文

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真的是我用过的扩展最方便的存储系统之一
配置难度 非常容易
地理位置 支持 支持
运维工具 丰富 一般
插件和引擎 有多个存储引擎供选择 有大量插件可以使用 -

两者的定位

MongoDBElasticsearch都属于NoSQL大家族, 且都属于文档型数据存储

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

MongoDB 是 文档型数据库, 提供 数据存储和管理服务
Elasticsearch是搜索服务, 提供 数据检索服务

两者的很大区别在于源数据的存储和管理

  • MongoDB作为一个数据库产品, 是拥有源数据管理能力的
  • Elasticsearch作为一个搜索引擎, 定位是提供数据检索服务, 也就是说我只管查, 不管写 _, Elasticsearch的Mapping不可变也是为此服务的, 带来的代价就是es不适合作为数据管理者, es可以从其他数据源同步数据过来提供查询, 但是不适合自己对数据进行存储和管理

es更侧重数据的查询, 各种复杂的花式查询支持的很好, 相比来说 MongoDB的查询能力就显得比较平庸了

由此可见, 对于个人, 如果你有一批数据要看, 但是不经常进行修改, 这个时候毫无疑问可以用es, 但是如果你还打算继续修改数据, 最好就是使用MongoDB,但其实对大多数人公司来讲,这两者的数据管理能力并没有多大的影响

ps: es修改Mapping的代价非常高, 所以我们一般都是把新数据重新写入一份新索引,然后直接切换读取的别名到新的索引

两者读写数据的异同

MongoDBElasticSearch都支持全文索引, 虽然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适合
  1. 对服务可用性和一致性有高要求
  2. 无schema的数据存储 + 需要索引数据
  3. 高读写性能要求, 数据使用场景简单的海量数据场景
  4. 有热点数据, 有数据分片需求的数据存储
  5. 日志, html, 爬虫数据等半结构化或图片,视频等非结构化数据的存储
  6. 有js使用经验的人员(MongoDB内置操作语言为js)
  • Elasticsearch适合
  1. 已经有其他系统负责数据管理
  2. 对复杂场景下的查询需求,对查询性能有要求, 对写入及时性要求不高的场景
  3. 监控信息/日志信息检索
  4. 小团队但是有多语言服务,es拥有restful接口,用起来最方便

总结

MongoDB和Elasticsearch都是我比较喜欢的存储产品

两者的功能特性也存在很多重合的地方, 其实现在很多数据库产品都在互相借(chao)鉴(xi), 功能和特性都在逐渐变得相似, 这也是未来很多存储产品的发展趋势, 大家都希望自己能覆盖尽量多的场景和用户群体

很多产品总是在不断的从没有->->功能丰富,但是功能丰富一定是做了很多的妥协, 于是又有了 功能众多的单体服务->多个功能单一的子服务 方向的转变,就像三国里面说的 “天下大势, 分久必合合久必分”.

现在NoSQL数据库产品就在这个路上, NoSQL归根到底都是 RDBMS的某个方面的妥协, 现在各种NoSQL 也都在加入对经典SQL和传统RDBMS的 join, 事务的支持, 但是我相信等到两者区别足够小的时候, 一定会有放弃了大而全, 而专注于某一场景的新的存储产品出现,到时候搞不好又是一波新的Nosql潮流

转载:https://blog.csdn.net/kongliand/article/details/108691847

有关MongoDB和Elasticsearch的各使用场景对比的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐