本文由云 + 社区发表
作者:磊哥
上期文章我们聊到了 redis。这期我们来说说另一个网红 nosql 数据库:MongoDB。有这么一个介绍 MongoDB 的说法是:MongoDB 是非关系数据库当中功能最丰富,最像关系数据库的。这么说是因为作为一个面向文档存储型、数据结构非常松散自由的的数据库,却拥有着丰富的功能特性如强大灵活的查询语言、支持二级索引等特性,新版本的 MongDB 甚至还支持事务。听小伙伴说 MongoDB 不仅功能丰富,而且读性能强大到远远把 MySQL 甩在后面,今天我就代替大家来动手进行一下数据库测试,揭开 MongoDB 的神秘 “面纱”。
为了进行数据库对比测试,这次我购买了腾讯云 MongoDB 的主从版(1 主 2 从),同时在同样配置的云主机自建 MongoDB 作为对比。
下面给出 CentOS7 64 位上安装 MongoDB 3.6 的实践如下:
vim /etc/yum.repos.d/mongod-org.repo
编辑内容如下:
[mongodb-org]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc
执行指令 yum install mongodb-org -y 安装
vim /etc/mongod.conf
此处根据自己需求修改bindIp: 0.0.0.0 # 监听地址 port: 27017 # 监听端口
systemctl start mongod.service # 开启服务
netstat -anpt | grep 27017 # 检查是否启动
服务开启后可以使用上面的指令测试服务是否启动,如果成功启动的话会看到结果如下图所示:
如果无法启动,需要根据日志分析具体原因。根据笔者的实践,大部分的原因会落在配置和权限上。如果排除错误太难,建议重新安装来的快一点。
接下来需要安装数据库测试工具,这次我们使用 YCSB,雅虎开发的一个很强大的测试工具。
在安装 YCSB 前需要安装 Java 和 Maven,测试前需要在 workloads 文件夹中创建配置文件,配置如下图所示:
考虑到购买的 mongoDB 是副本集配置,一个主节点带两个从节点,我们在本地也配置好副本集群,使用用 ./mongod --replSet amymongo --dbpath /data/27019 --port 27019 --logpath /var/log/mongodb/27019.log --fork 配置从节点,具体配置和初始化方法参考https://cloud.tencent.com/developer/article/1379231(当然部署在本机的方案不能保证高可用)
在 workloads 中防止配置文件,我们选择插入 1 千万条记录,执行 1 千万次操作,测试两种场景:read/update 9:1 和纯 insert 场景。
废话少说,下面就一起来看看测试结果吧。
场景读更新 read/update 9:1,单位 ops/sec:
场景纯写入 insert,单位 ops/sec:
场景读更新 read/update 9:1,单位 us(延时):
场景纯写入 insert,单位 us(延时):
看来 mongodb 真的是一个高性能的数据库,为啥呢,因为 mongo 的延时单位居然是 us 微秒、微秒、微秒。。。16GB 的内存基本上 20 线程之后延时就会大大增加,在 100 线程的时候基本上延时基本在 1000us 以上,而读多场景跟写入场景相比,写入场景的性能略差一点,随着线程数的增大,写入场景的吞吐量和延时表现和读更新场景的差距会扩大。
有读者可能会有疑惑,既然数据库测试是比较云和自建,看起来差距也没有那么大,用自建好像也可以接受啊。这里我要把测试中的发现讲给大家听,听完之后大家就明白了。
第一点,笔者买的是 16G 内存的机器(流下了没有钱的泪水),测试的时候发现 cvm 的内存占用基本到了百分之 60 左右,笔者在建立副本集和加大测试数据量(购买数据量的百分之 80)之后发现,内存占用基本到了百分之 80 以上。看来 mongo 的第一个缺点,就是对内存的消耗真的非常可怕!!如果遇到高并发大数据量读写,恐怕分分钟就存在着存在着 OOM 的风险。
所以这里奉劝各位同学,如果要自建 MongoDB,还是尽量购买超大内存满足业务需求,避免在业务高峰的时候被 “干掉”。如果因为跟笔者一样贫穷不想买那么大的内存,可以考虑使用云数据库,云 MongoDB 具备动态伸缩能力,即使没有买够大的内存,也完全来得及在业务高峰扩容, 即使发生故障,也有完善的数据自动备份和无损恢复机制来恢复数据,在可用性上保障就高多了。
第二点,笔者在后续测试本地副本集的时候,尝试读 secondary 节点的数据,结果遇到了读延迟很高的情况。在网上研究了一下发现是因为,MongoDB 复制集里 Secondary 不断从主上批量拉取 oplog,然后在本地重放,以保证数据与 Primary 一致。这里为了防止脏读,会加一个锁阻塞所有的读请求。
所以如果遇到 Secondary 重放 oplog 占用锁时间长,读取的延时也会对应变长。这个锁最高能锁多久呢,看到有个案例锁了接近一个小时。。。看到的人内心一定是崩溃的,而在云 Mongo 测试的时候没有遇到这个情况,我想这一定是针对这个缺陷做了很大的改进,使用了其他方法实现同步。
总的来说,MongoDB 确实可以不借助其他第三方工具实现高可用和分片功能,具备的高可用的故障切换,分片可以实现数据的分部均衡,大数据量的时候通过路由实现了服务器的负载均衡。所以 MongoDB 自身的可用性较高,也难怪会在短短时间内成为流行的 nosql 数据库。
但是 MongoDB 也存在着一些坑:如对内存的占用过高、对网络的占用过高、存在从节点锁导致读几乎不可用的情况,这些情况在实际业务使用的时候会导致很严重的问题,集群宕机、服务瘫痪、数据丢失无时不刻不是覆盖在运维同学心头的阴影。这个时候云 MongoDB 几乎就是救星,弹性伸缩、随时扩容、真正安全的数据热备以及强大的专业运维架构师团队,才能真的确保业务安全无故障的运行下去。
写到这里,笔者也在思考,云数据库到底是什么,它仅仅是把数据库封装一下,改改内核,提供给使用者吗?不,云数据库应当是一整套专业服务,除了数据库之外,还有监控、安全、迁移、灾备、运维等一系列的服务提供。能让业务开发专注于业务本身,把专业的交给专业的人去做。
此文已由腾讯云 + 社区在各渠道发布
获取更多新鲜技术干货,可以关注我们腾讯云技术社区 - 云加社区官方号及知乎机构号