/ 中存储网

用还是不用MongoDB?悲催用户炮轰10gen CTO

2013-03-15 00:00:00 来源:中存储网

前几天在HackNew上出现了一篇文章,标题很彪悍,叫《Don’t use MongoDB》,其内容也是直接表达了对MongoDB的不满,作者列举了MongoDB使用过程中遇到的种种问题。甚至上升到对其开发团队的质疑,表示他们可能只关心benchmark的数据,不关心用户数据的安全性。真是大叫坑爹啊!

最新消息:这篇文章的作者已经承认文章只是他的一个恶作剧,他称只是想做个实验,以显示控制一个人的思维是多么容易。但是他提到的案例并非完全没有出现过,这样一篇恶作剧的文章,虽然着实唬了我们一把,但是能够让一些盲目的朋友更谨慎一些。还是有好处的。

但很快地,10gen CTO @ehwizard 就看到了这篇文章,并马上对作者提到的各个问题进行了回应。ehwizard表示,他翻遍了1600个用户案例报告,并没有发现出现了文章作者所说这些问题的案例(实际上也是对指责的真实性进行了怀疑。你是哪个单位的?)。随后ehwizard又友好的表示,如果你在使用MongoDB中遇到问题,可以随时到MongoDB的Google Group或者MongoDB相应的IRC中进行报告。

在MongoDB正被炒得火热的今天,相信这样一篇文章也着实向一些同学浇了一头冷水。所以NoSQLFan将二者PK观点都放在这里,大家可以自己看一看,甚至做做实验,在使用NoSQL或者是其它新技术前,也都多了解一些可能出现的问题。

下面绿色部分是原文作者对MongoDB的一些指责和质疑,红色部分为NoSQLFan的无聊演绎,其余为10gen CTO ehwizard的回应。

1. MongoDB为了在benchmark上好看一些,不惜将不安全的方案作为其默认配置。(就差大叫无良奸商了)

ehwizard说,哥们你这个说法有点过份了,MongoDB的默认方案的选择,和benchmark根本就一点关系都没有,而且不仅是默认方案,包括API的设计,以及MongoDB其它的一些功能取舍,都和benchmark没有半毛钱关系。当然,默认配置的设定还是需要和用户主要的使用场景相关,MongoDB在使用上确实已经经历了很多变化,对这些变化做出相应的默认策略调整,确实也有可能。

当然,话说回来,MongoDB的实现策略的实现,本身是可控的。比如你可以选择写操作的安全级别,在你使用了replica sets的时候,你完全可以设定一个写操作同步到一定机器数量后才返回成功。(对作者一大嘴巴子,您这是真不懂呢还是装不懂呢)

2. MongoDB丢数据现象严重,并且导致的情况很多

2.1 MongoDB经常诡异的丢失数据

对此ehwizard的回应是,对于丢数据的问题,我们收到过bug报告,但是我们对MongoDB非常了解,所有的bug在收到后,几乎都在第一时间进行了修复。如果你能够给出你丢数据时的使用场景,我们会尽可能找出原因。ehwizard表示,如果你真的发生了丢数据的问题,请马上联系10gen的工程师进行bug修复。(哥们,有问题,找组织,不丢人)

2.2 在不使用journaling的时候,如果MongoDB崩溃,数据无法恢复

ehwizard解释说,这是正常的情况,对于单机使用MongoDB来说,不使用journaling日志本身就是不推荐的危险做法,在2.0版本后,journaling日志已经是默认开启了。而如果是在replica sets等多机的情况下,你根本不需要进行数据恢复,只需要从另一个同步节点resync数据就可以了。

2.3 主从复制有问题,存在丢失数据的操作,主从之间没有同步校验。并且虽然数据丢了,但是在状态上显示还是同步正常的

ehwizard表示这种情况应该不会发生,如果确实发生了,应该是严重bug。

2.4 主从复制存在不明原因的中断现实,没有任何错误就直接中断了

ehwizard说这确实有可能发生,可能中间确实出错了,只是出错信息并没有返回给客户端而已。因为复制操作本身是异步进行的,如果你希望数据同步复制完后才返回,你可以通过getLastError命令将w参数设定为2。

3. MongoDB在进行写操作时使用了一个全局的写锁,这样效率很低

这一点上ehwizard也承认这确实是MongoDB长期被诟病的问题,但是目前在2.0版本中已经做了相当大的改进。已经对写操作需要涉及到磁盘IO的情况下进行了优化。而在2.2版本中,这一优化还会进一步推进。(哥们,针对collection的lock啥时候来啊)

4. 大压力比较大的时候,MongoDB的auto-sharding功能会出现问题,在大负载下,添加一个sharding结点绝对是场噩梦。因为这时候MongoDB只要去做chunk的移动,就会影响本身服务,要么就只能不做移动。

ehwizard解释说,如果系统确实已经到达极限,这时候再去做chunk块的移动确实不容易。关于这个话题他自己已经在很多场合说过,他的建议是尽早监测到集群已经快到极限了,不要等到系统已经到了100%负载的时候再去做添加节点的操作。(对自己的业务增长上点心,别跟4sq一样火烧眉毛了才发现)

5. mongos非常不可靠,虽然 mongod/config server/mongos 结合的架构看起来很美,但是mongos确实很不给力。当压力稍大一点,mongos就经常崩溃,少则几天崩溃一次,多则几小时就崩溃一次。有时候会出现抛出断言然后杀掉某个关键线程,但是这时候进程居然还依然运行,所以重启管理进程也不是每次都管用。

ehwizard表示不知道他所谓的关键线程是什么,希望能够多提供一些相关细节。

6. MongoDB曾经出现过一次问题,导致所有数据被删除了。这个情况发生在 MongoDB 1.6版本的replica sets结构中,由于选举策略出现问题,导致选择了一个空数据节点作为新的primary,这样导致那些有数据的节点都把自己的数据给删除了,我们700G的数据就这样没了。还好在1.8版本中修复了这个问题。

ehwizard说查看了相关的报告,并没有发现有所说的问题,希望能够提供更多细节。

7. 10gen的人发布了一些还不能发布的东西。据我们所知,在一些stable版本中居然会有一些导致数据问题的bug,而通常我们在遇到这些bug的时候才会发现。我们购买了10gen的白金级服务,但是得到的结果只是一些被他们称为内部RC版本的热补丁,而我们需要将这些补丁打在我们线上版本上。天哪!

ehwizard表示我们并没有什么白金合同,所有的问题都是通过公开的jira系统来反馈的。从问题的提出和修改,都是在jira上公示的,(比尼玛官员的财产还透明)。如果你不能提供更多的信息,这个真的不好再讨论。我们通常的做法是在修复了问题后会尽快的通知到相应的用户。

8. 在负载比较高的机器上,同步工作相当废柴

感觉应该是负载过高了,跟我之前说的一样,同步默认是异步的,如果你希望确认同步成功,可以通过getLastError命令设置w参数为2。

而上面的问题可能已经有一些修复了,但是我想说的是,作为一个公司,还是应该将服务的可靠性放在第一位。我认为10gen应该按下面的优先级来进行MongoDB的功能开发:

1. 不要丢数据,对数据一定要非常小心2. 多做测试,保证可靠性3. 做到真正的多节点扩展性4. 除低延迟5. 提高对资源的请求性能

而在我看来,10gen眼中可能就在意第5个,而第一点估计在他们眼中连前三都进不了。

看到这个,ehwizard同学不认同了(这是从道德层面上质疑啊),他表示10gen绝不是像作者说的那样,他说你可以看一下我们bug修复的列表,这些都是公开的,我们从来没有说偷偷的改掉某个bug了事,或者说只跟一些特殊用户说明这些bug。如果我们真的那么在意读写性能,我们早就修复了那些浪费CPU的问题了。如果我们真的那么在意benchmark的话,我们早就优化了全局锁的问题了,这东西对多线程的benchmark结果是有非常大的改进的。更何况一般的benchmark都是多线程跑的,我们并不那么在意benchmark的数据。(我的benchmark已经很牛X的好不好)

MongoDB确实还很新,还有很多问题。如果你想来跟我们讨论一些MongoDB相关的问题,我们的的办公室为你敞开,我们会以非常开放的态度对待你提出的问题,所以如果真的有问题,我们非常期待与你的沟通。