MongoDB vs Elasticsearch

JAVA日知录 一个关注| Java | Spring Boot | Spring Cloud | 干货分享的博客网站 本文由博客端 http://www.javadaily.cn 主动推送
本贴最后更新于 279 天前,其中的信息可能已经事过景迁

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 是搜索服务, 提供 数据检索服务

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

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 仅作为数据检索服务和数据分析平台, 不直接作为源数据管理者

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

总结

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

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

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

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

MongoDB和Elasticsearch的对比

  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    106 引用 • 99 回帖 • 427 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    85 引用 • 58 回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...