话题讨论 | mongodb 拥有十大核心优势,为何国内知名度远不如 mysql 高?

1. 背景
mongodb 是一款功能完善的分布式文档数据库,在高性能、动态扩缩容、高可用、易部署、易使用、海量数据存储、高压缩比等方面拥有天然优势。虽然 mongodb 有很多优势,但是在国内缺存在不少的误解,影响力有待提升。
2. mongodb 历年数据库得分排名及得分趋势
DB-Engines 是一个对数据库管理系统受欢迎程度进行排名的网站,近年来,MongoDB 在 DB-Engines 数据库流行度排行榜稳居榜单前五。在 DB-Engines 排名可以看出,mongodb 历年得分数据呈现持续增长的趋势,具体如下图所示:
得分趋势图形

近两年得分如下:

从历年得分排名可以看出,mongodb 总体趋势呈现持续增长态势,稳固了它在数据库系统中的使用优势。
mongodb roadmap:不仅仅是文档数据库
mongodb-4.2 版本开始已经支持分布式事务功能,当前对外文档版本已经迭代到 version-4.2.11,分布式事务功能也进一步增强。此外,从 mongodb-4.4 版本产品规划路线图可以看出,mongodb 官方将会持续投入开发查询能力和易用性增强功能,例如 union 多表联合查询、索引隐藏等。mongodb 产品路线图如下:

从 mongodb-4.2 版本分布式事务功能支持以及 4.4 版本 roadmap 规划图可以看出,mongodb 后续发展会持续朝着 NewSQL 方向前行,预计会为用户提供更全面的数据库服务功能。
3. 模式自由-加字段方便快捷
分布式 mongodb 核心优势特性主要如下:
模式自由-加字段方便快捷
在集合中插入一条文档
use test;
db.blog.insert({"Title": "Title1", "Description": "Description1", "Author": "Author1","Content": "Content1", "likes": "100", });

从上面的操作可以看出,mongodb 不需要提前建表,也不需要指定表中各个字段,使用灵活。
在已有文档 Title1 中添加一个不存在的字段(如给博客添加一个 tags 字段)
db.blog.update({"Title": "Title1"}, {$set: {tags: "tagxxx"}})

4. 天然高可用支持
当前开源数据库 Mysql,当同一个分片复制集中(假设一主两从)中的主服务器异常或者实例异常退出后,需要依赖第三方 MHA 插件来实现新主的选举。如果没有第三方 MHA 插件,或者第三方 MHA 插件异常,则无法选举新主节点,最终造成写失败。
相比 Mysql 对第三方 MHA 插件的依赖,mongodb 数据库自带天然高可用选举功能,具体架构图如下:


如上图所示,当主节点异常后,两个 mongod 从节点的保活报文会探测到该异常,然后 2 个从节点会进行一轮新的主节点投票选举(raft 协议)。主节点异常,剩余两个节点可以进行正常投票选举,因为满足 raft 多数派要求,最终会在两个主节点中快速选择一个新的主节点。
5. 分布式弹性扩缩容(解决分库分表及海量数据存储痛点)
扩容过程业务无感知,扩容新分片触发数据 balance 过程如下图所示(假设从 3 分片扩容到 6 分片):

有了分片水平扩容能力,就可以突破前面单分片复制集架构的容量限制、写入能力受限等瓶颈,基本上可以实现数据容量和写入能力成倍增长。
6. 完善的数据均衡机制、不同分片策略、多种片建类型支持
完善的数据 balance 均衡机制


不同分片策略及预分片功能支持
为了满足不同业务查询场景需求,mongodb 支持两种类型的分片策略:hash 分片和范围分片。这两种分片策略再不同业务场景,各自有不同的优缺点,这样业务可以根据实际情况来完成分片策略选择。具体如下:
hash 分片策略:通过对指定 shard key 进行 hash 计算,从而快速实现数据随机散列到不同分片,从而规避数据不均衡问题,适合单条数据查询相关业务场景。
范围分片策略:范围分片方式,比较适合业务有范围查询的场景,如果业务查询中带有范围查询,可以考虑该分片策略实现性能最大化。注意:范围分片策略方式,数据均衡性相比 hash 分片一般稍差。
此外,为了尽量提高性能,mongodb 默认还支持预分片功能,这样可以保证数据写入集群的适合尽量均衡,避免 balance 数据迁移过程对整个集群性能的影响,做到读写性能的最大化。hash 分片策略和范围分片策略都支持预分片,只是 hash 分片策略方式可以支持自动预分片,同时也支持手动预分片方式;范围分片策略方式只支持手动预分片。具体如下:
自动预分片支持:如果分片集群选用 hash 分片策略,则支持 shardCollection 时提前对片建进行自动预备分片。
手动预分片支持:hash 分片策略和范围分片策略都可以通过 mongodb 自有的 splitAt 等接口进行手动人工预分片,分片接口的支持确保预分片更加弹性自由。
此外,除了支持常用的范围分片及 hash 分片策略外,mongodb 还支持 shardTag 分片模式,对一些极端特殊需求做定制化流量转发(例如对带有某种标记的数据转发到指定的节点)。
7. 完善的数据一致性及安全性保证
数据一致性有较高要求场景

数据一致性要求不高场景

8. 高并发、高性能
mongodb 为了满足不同业务链接需求(链接数多少、是否短链接、是否很多空闲链接等),支持两种线程模型:一个链接一个线程和 adaptive 动态线程池模型。
一个链接一个线程

adaptive 动态线程模型

wiredtiger 高性能存储引擎设计
WT 和 innodb 存储引擎性能比较曲线如下:

WT 和 levelDb 存储引擎性能比较曲线如下:


9. 成本节省-WT 引擎高压缩比支持
mongodb 对数据的压缩支持 snappy、zlib 算法,针对存储层中的数据分类又可以分为以下几种:
普通 collection 数据:对用户写入 collection 的数据是否需要压缩,支持 snappy、zlib 算法,4.2 增加zstd支持。
journal 数据:对 journal 日志数据是否压缩,支持 snappy、zlib 算法,4.2 增加zstd支持。
index 索引数据:对索引数据是否进行压缩,默认只支持前缀压缩,这样相同前缀的索引数据,共同的前缀只会存储一次,这样即可减少内存和磁盘消耗。
在以往线上真实的文本数据空间大小与真实磁盘空间消耗进行对比,可以得出以下结论:
① mongodb 默认的 snappy 压缩算法压缩比约为 2.2-3.5 倍
② zlib 压缩算法压缩比约为 4.5-7.5 倍(本次迁移采用 zlib 高压缩算法)
也就是,如果 collection 数据和 journal 日志数据采用默认的 snappy 压缩算法,当数据量为 3.5T 时,真实的磁盘消耗约为 1-1.5T;如果采用 zlib 算法,3.5T 的数据量,真实的磁盘消耗为 500-700G 左右,不同数据类型会有差别,如下表所示:

说明:1.不同数据类型会有差别;2.最新 4.2 以后版本引入了新的zstd算法,性能会更好,由于没有真实使用过 zstd 算法,因此不做具体数据对比。
10. 天然机房多活容灾支持





11. 完善的客户端均衡访问策略
mongodb 客户端访问路由策略由客户端自己指定,该功能通过 Read Preference 实现,具有如下几个配置方式:
primary :只从 primary 主节点读数据,这个是默认设置,所有读只走主节点。
primaryPreferred :优先从 primary 读取,如果复制集没有主节点则通过从节点读数据。
secondary :只从 scondary 节点读数据。
secondaryPreferred :优先从 secondary 读取,当没有 secondary 从节点成员时,才从 primary 读数据。
nearest :选择离自己最近的节点读数据,也就是就近访问。
通过在客户端 driver 中配置不同的读方式,可以方便实现读写分离、就近读数据等,如果对数据一致性要求高,也可以直接读主节点。我们以复制集 nearest 配置为例,架构图如下:

12. 分布式事务支持
mongodb-4.2 版本开始已经支持分布式事务功能,当前对外文档版本已经迭代到 version-4.2.11,分布式事务功能也进一步增强。此外,从 mongodb-4.4 版本产品规划路线图可以看出,mongodb 官方将会持续投入开发查询能力和易用性增强功能,例如 union 多表联合查询、索引隐藏等。mongodb 产品路线图如下:

从 mongodb-4.2 版本分布式事务功能支持以及 4.4 版本 roadmap 规划图可以看出,mongodb 后续发展会持续朝着 NewSQL 方向前行,预计会为用户提供更全面的数据库服务功能。
13. 最后:mongodb 这么多优势,为何国内影响力不高?
当前 mongodb 已经为我司提供了数万亿级数据库存储服务,从业务场景和业务接入情况来看,当前至少有 90%以上业务场景可以 mongodb 和 mysql 相互替代,这一部分业务使用 mongodb 也非常合适,业务切换到 mongodb 后也得到了一致性的认可,主要为业务解决了如下痛点:
分库分表痛点:业务最大的痛,mongodb 可以理解为无限大的表,彻底解决该痛点。
机房多活痛点:传统 mysql 双向同步具有物理服务器成本高(多副本情况下,又多了一倍)、人力成本高(你得找几个人来开发和运维双向同步系统)、数据一致性很难保证等。mongodb 分片及复制集架构可以天然支持机房多活,包括南北双机房,三机房,甚至更多国内国外机房多活都可解决。
成本高,mysql 官方版本默认没有压缩等功能,同样得数据,默认配置,mongodb 磁盘相比 mysql 就可以节省 60%左右。
分布式弹性扩缩容:有了该功能,除了可以解决分库分表痛点外,对业务容量评估也减轻了很大的工作量。例如如果 mysql,你不知道后续数据量就近多大,一般一次性就申请很多套,造成了资源浪费。
mongodb 分布式事务支持,突破了单机事务的限制。
其他
如上,可以看出 mongodb 确实在部分业务场景有很多的优势,那为什么在国内影响力不高,甚至误解很深,个人理解如下:


个人认为除了上面图形中总结的原因外,还有另外两个很大的原因:
当前国内真正研究 mongodb 内核实现原理的人相比 mysql 确实少很多,遇到问题不知道怎么解决,最终造成不敢大规模使用。
mongodb 生态相比 mysql 不足。
此外,大家更加习惯 SQL,已经养成习惯,其他数据库有个熟悉学习的过程,需要更多成本
以上是我的个人理解,大家可以说说自己的想法,补充为什么这么优秀的文档数据库 mongodb 在国内影响力不足
后续分享出 mongodb 踩过的所有坑到社区,让更多的人学习了解学习 mongodb。
版权声明: 本文为 InfoQ 作者【杨亚洲(专注mongodb及高性能中间件)】的原创文章。
原文链接:【http://xie.infoq.cn/article/180d98535bfa0c3e71aff1662】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论 (6 条评论)