某人发了一篇 Don’t use MongoDB 的血泪控诉,我把原文翻译如下,你可以看看。不过,我想我们还要去看看10gen CTO 的对此事的回复,我们还要去在 Reddit 上看看大家的说法,10gen CTO 的对此事的回复后面也有一堆人在讨论这个事,还有一些程序员开始去读 MongoDB 的源码了,呵呵。看样子,说 MongoDB 的这些事并不是真的。
10gen CTO 对此事的并不完全知道,其在回复,对些文中的每一条都做了回复。我把其回复的大体意思也放在原文中。不过,很有意思的是那些程序员的讨论。建议大家看看。
正文
因为各种政治原因,我这段时间没有说什么,但是现在我觉得因为要对社会负责,所以我要阻止大家不要把你们的业务放在 MongoDB 上。
我的团队在一个有巨大用户量(一个有千万用户级的大型的公司)系统上使用的 MongoDB,这个系统上让 MongoDB 有非常大的负载。早期,我们以为使用 MongoDB 会像10gen 公司(MongoDB 背后的公司)宣扬其在长期性能扩展有很多好处。但是,我们错了,而这个 rant (长篇抱怨)就是为了让你不要相信那些所谓的成功经验,而和我们一样犯了大错。如果有人能避免你上当,那么就得我写这么多。希望能警醒更多的人。
注意,对于和10gen 打交道的经历来说,他们给予了我们充分了热情和帮助,而且非常地好。但是这并不能成为我不告诉大家他们的产品失败的理由。
为什么这么说?
数据库应该是正确的,或是尽可能的正确,因为数据库的错误会比其它错误危害更大。不仅仅是因为其对运行,性能,开销,和其价值影响巨大,还因为其连带的东西。匆忙去去移植 TB 级的数据相比起去修改代码中的一个逻辑错误来说是一个很巨大的工作。而在系统出问题后需要恢复 TB 级的数据,你会被硬盘的速度所限制,你会有一种绝望的感觉。
数据库是一个很复杂的系统,对于开发者来说就像一个黑盒一样。你需要对你所采用的数据库持绝对信任的态度,信任它会做正确的事,并会保持一致性和可用性。
为什么 MongoDB 会流行?
说句公道话,我们必需承认 MongoDB 是流行的,因为下面这些原因让其流行变得很合理:
现在,你可能正在开发一个随便玩一玩的网站,或是一个原型,或是那种只考虑开发速度不考虑别的的项目。老实说,对于这种项目,无所谓你用什么样的技术,只要搞定工作就行了。
但是,如果你想要在 MongoDB 上搞一个大规模的系统,在上面运行真实的业务,那么,请不要用 MongoDB。
为什么不?
1)MongoDB 为了赢得 Benchmark 测试而默认使用了不安全的写方式
如果你不调用 getLastError (),MongoDB 就不会在确认数据库写操作完成就返回了,这会引入至少两种问题:
10gen CTO 回复: 这和 Benchmark 没有任何关系,并说这个就是 API 的设计,其交给用户自己去选择,因为写的方式也有很多种。
2)MongoDB 会以令人震惊的方式丢失数据
下面是一个我们所经历过的它丢数据的列表:
10gen CTO 逐一回复:1)从来没有一个数据丢失的 BUG 我们没有马上 fix 的事情。你能告诉我你报给我们的问题号吗?我们至少要明白是怎么一回事。如果是我们的问题,我们会马上 fix 的。2)从损坏了的数据库中不能完全恢复数据 ,这不挺正常的吗?但是如果有主从服务器互为备份应该会好一些。3)请告诉我你的问题号,我们从来没有接到过这样的错误报告。如果有,的确很严重。4)如果是说错误条件发生的时候没有通知,这有可能。另外,你可以监控数据复制的写操作,你可以使用 w=2 为 getLastError 的参数。
3)MongoDB 需要全局写锁来请求写操作
在写操作频繁的时候,这等同于杀了你。如果你运行一个 blog,你也许不会关心这个事,因为你的读写操作不高。
10gen CTO 回复:读写锁永远都是问题,但是2.0会好很多,2.2会解决得更好一些。
4)MongoDB 的 Sharding (分区) 在高负载下会停止工作
在高负载下加一个 shard 是一场恶梦。Mongo 要么会移动其数据块太快而导致 DOS 攻击产生很多流量占用带宽,要么就完全地拒绝更多的数据块。这会使一个高流量的网站承受着沉重地写操作。
10gen CTO 回复:如果系统已经超过了其负载,那么移动数据当然会变得很难。我每一次的演讲都说得很清楚,不要在系统性能不行的时候才去加 shard,这不行的。
5)Mongo 不可靠
Mongod/配置服务器/mongos 的架构确实合理且聪明。不幸的是,mongos 完全就是垃圾。在有负载的情况下,它时不时就都会崩溃,有时几个小时,有时几天。进程重启监控有时也不管用,因为它会抛出一些断言伪造出一个关键线程,导致进程还在运行。Double Fail。
最坏的是,唯一可行的方式是在一堆 mongos 实例前放一个 HaProxy (一种负载均衡器),运行一个作业缓慢地轮着访问这些 mongos 实例,并定期 kill 掉他们,以便可以重新启动新的实例。我没有在开玩笑。
10gen CTO 回复:不可能有这种事,你能不能告诉我更多的细节?
6)MongoDB 有一次甚至删除了整个数据库
MongoDB 1.6,在数据同步配置中,有时会配置了一个错误的结点(经常是一个空结点)作为一个最新的数据结点。于是其它同步数据的结点上的数据就这样被干掉了(我说的是700GB 的好数据),因为其把这个空结点的数据同步回有数据的结点上。数据库永远永远都不应该干这个。如果出现这种问题,数据库应该抛出一个错误而让 DBA 来选择合理的操作,或是强制使用正确的配置。而不应该删除所有的数据(那天真是太糟糕了)。
他们在1.8中修复了这个问题,偶滴神啊。
10gen CTO 回复:找不到这样的事,也找不到相应提交的代码,你能多给点信息吗?
7)发布了一些不应该发布东西
众所周知,在稳定版里能找到一些尴尬的 bug 会导致数据问题——而我们总是在出了问题后他们才告诉我们这些问题,这是因为我们购买了 10gen 他们那超级诈骗的白金技术支持。他们回应是,发给我们一个 hot patch,他们内部叫 RC 的玩意,然后让这个 hot patch 运行在我们的数据上。
10gen CTO 回复:关于白金的技术支持,我们所接手的所有问题都会公开,fix 也会公开。没有特定的情景,这种事很难讨论。我们会根据不同的情况作出不同的反应。我们希望我们的用户的问题能尽快得到解决。
8)复制器在繁忙的服务器上黯然失色
复制器经常性的向 Master 发起 DOS 攻击,或是复制非常慢,花了巨长无比的时间,而 oplog 几乎被耗尽(就算是 50GB 的 oplog)。
我们有一个繁忙的,大的数据集,我们不会复制它,因为它是动态的。那是令人痛苦的一个月,或是我们需要在选择不同的数据库系统前交叉双指(注:好运的手势)
10gen CTO 回复:这看起来像上服务器负载过重了。我前面提到过了。
但是最糟糕的问题是:
你可能会说,我这些问题都是过去式了;他们修复了所有这些问题或是他们会在下一版本中修复这些问题;X问题可以用Y实践来减轻。等等,等等。
不幸的是,你说这些东西一点用也没有。
真正的问题是,这么多的问题都是首要的问题。 数据库开发者要能 hold 住比一般程序员更高的标准。也就是说,你的优先级应该像下面这个样子:
10gen 的顺序好像是 #5 为第一,其它项随便,#1 并不在前3位。
10gen CTO 回复:这明显不是真的。看一看我们提交的代码,看一看我们的 fix。 我们从来不会在 release 版中隐藏一个 bug。如果我们非常在乎性能的 benchmark 的话,我们会花精力解决那些锁的问题,这样一来,多线程并发会更快一些。
MongoDB 是一个新生的东西,还有很多东西需要打磨。如果你想来认识一下我们,我们欢迎你来认识一下我们。
这些失败,还有那所暗示的公司的优先级,指出了一个最基本的企业文化的问题,其会让问题出现在任一发布版中:因为他们缺乏尊守必要的数据库系统的设计律条。
请慎重考虑这些警告。