再见 MongoDB,你好 PostgreSQL 已翻译 100%

oschina 投递于 2015/03/11 08:27 (共 19 段, 翻译完成于 03-15)
阅读 38848
收藏 224
14
加载中

Olery 差不多成立于5年前。始于Ruby代理开发的单一产品(Olery Reputation),随着时间的推移,我们开始致力于一系列不同的产品和应用程序。当今,我们的产品不仅有(Olery) Reputation,还有Olery FeedbackHotel Review Data API,widgets ,在不久的将来它可以嵌入到网站和更多产品/服务中。

我们增加了很多应用程序的数量。当今,我们部署了超过25个不同的应用程序(全为Ruby),它们中的一些是web应用程序(Rails或者Sinatra),但大多数的是后台运行程序。

Micooz
Micooz
翻译于 2015/03/11 08:57
2

我们最引以为豪的是迄今为止我们所取得的成就,不过在这些成就的背后总闪现着一样东西,即基础数据库。从Olery成立之日起,我们就安装了数据库,它用MySQL来存储(用户、合同等等)核心数据,用MongoDB来存储评论及其类似的数据(即哪些在数据丢失的情况下很容易恢复的数据)。一开始,这样的安装运行的非常好,然而,随着公司的成长,我们开始遇到了各种各样的问题,尤其是MongoDB的问题居多。其中一些问题是由于应用与数据库的交互方式而引起的,一些则是由数据库本身而产生的。

例如,某个时刻,我们需要从MongoDB中删除一百万个文档,以后再把这些数据重新插入到MongoDB里。这样的处理方法使得整个数据库几乎要被锁定数个小时,自然服务性能就会降低。而且直到对数据库执行修复(即在MongoDB上执行repairDatabase命令)后才会解锁。而且完成修复还要花费数个小时,修复所花的小时数要根据数据库的大小来确定。

几点人
几点人
翻译于 2015/03/11 14:36
2

在另一实例中我们注意到我们的应用程序的性能降低和设法跟踪到的 MongoDB 集群。然而,经过进一步检查,我们无法找到问题的真正原因。无论我们怎么安装,或使用什么工具敲了什么命令我们都找不到原因。直到我们更换了集群的初选,性能才恢复正常。

这只是两个例子,我们已经有过许多这样的情况。这个问题的核心是,这不只数据库在运行,而且无论我们何时察看它都没有绝对的迹象表明是什么原因导致的问题。

Parser7
Parser7
翻译于 2015/03/11 09:24
1

无模式的问题

另外,我们面对的核心问题是mongoDB的重要特征之一:模式的缺乏。模式的缺乏可能听起来是有趣的,并且在一些情况下是有好处的。然而,对于许多无模式存储引擎的用法,其导致了一些模式之间的内部问题。这些模式没有通过你的存储引擎定义而是通过你的应用的行为及其可能的需要而定义的。

例如:你可能有一页存储你的应用需要的字符串类型的title字段的集合。这儿这个模式是非常符合当前情形的,即使它没有被明确的定义。但如果这个数据结果改变超时,尤其是如果原来的数据没有被迁移到新的数据结构,这就成了问题(在一些无模式的存储引擎上是相当有问题的)。例如,你可能有下面这样的Ruby代码:

post_slug = post.title.downcase.gsub(/\W+/, '-')
冬阳1132
翻译于 2015/03/11 17:07
1

这样,针对每一个有“title”字段并返回一个String的文档,它都能正常工作。然而,对于那些使用不同字段名字(例如:post_title)或者根本没有标题字段的文档来说,它将不能正常工作。为了处理这种情况,你需要将代码调整为下面内容:

if post.title
  post_slug = post.title.downcase.gsub(/\W+/, '-')
else
  # ...
end

另一种处理方法是,在你的模型中定义一个模式。例如 Mongoid,一个流行的针对Ruby的MongoDB ODM,就能让你做到这一点。然而,当使用这些工具定义一个模式时,你可能会好奇为什么它们不在数据库内定义该模式。实际上,这样做可以解决另一个问题:可重用性。如果你只有一个应用程序,那么在代码中定义模式并不是什么大问题。然而,如果你有许多应用程序的话,这将很快会成为一个大麻烦。

ScriptKid
ScriptKid
翻译于 2015/03/11 16:57
1

无模式存储引擎希望通过删除对模式的限制的方式,让你的工作变得更简单。但现实的情况是,确保数据一致性的责任推到了用户自己的身上。有时候无模式引擎可以工作,但我打赌,更多的时候是事与愿违。

好数据库的需求

Olery有了更多的特殊需求后,迫使我寻求一款更好的数据库来解决问题。对于系统,特别是数据库,我们非常注重以下几点:

  1. 一致性

  2. 数据和系统行为的可视化

  3. 正确性和明确性

  4. 可拓展

一致性是重要的在于它有助于帮助我们对系统设定明确的期望。如果数据总是按照同样的方式存储,那么系统可以很方便的使用这些数据。如果在数据库层面要求表的莫一列必须存在,那么在应用层面就不用检查这列数据是否存在。数据库即使实在高压情况下,也必须保证每一次操作的完整性。没有什么事情比单纯的插入数据,过了几分钟后却找不到数据的事更让人沮丧了。

zhenmao
zhenmao
翻译于 2015/03/12 15:24
2

可见性包含了两点:系统本身以及从中获取数据的容易程度。如果一个系统出错那么应该易于调试。反过来,用户应很容易查到想要查询的数据。

正确性是指系统的行为如我们所期望的那样。如果某个字段定义为一个数值型,没有人可以像其中插入文本。这方面MySQL是臭名昭著,一旦你这样做你将得到伪结果。

可扩展性不仅针对性能而言,而且也涉及金融方面和系统能够多么好地应对不断变化的需求。一个系统在没有大量资金成本或减缓系统所依赖的开发周期情况下,很难表现得非常好。

Parser7
Parser7
翻译于 2015/03/12 13:49
1

搬离MongoDB

上面的需求牢记于心后,我们就开始寻找一个取代MongoDB的数据库。上面提到的特性通常是传统RDBM特征的一组核心集,所以我们锁定了两个候选者:MySQL和PostgreSQL。
本来,MySQL是第一候选,因为我们的一些关键数据已经在使用它存储。然而,MySQL也有一些问题。例如,当将一个字段定义为int(11)时,你却可以轻松地向该字段插入文本数据,因为MySQL会试图对它进行转换。下面是一些例子:

mysql> create table example ( `number` int(11) not null );
Query OK, 0 rows affected (0.08 sec)

mysql> insert into example (number) values (10);
Query OK, 1 row affected (0.08 sec)

mysql> insert into example (number) values ('wat');
Query OK, 1 row affected, 1 warning (0.10 sec)

mysql> insert into example (number) values ('what is this 10 nonsense');
Query OK, 1 row affected, 1 warning (0.14 sec)

mysql> insert into example (number) values ('10 a');
Query OK, 1 row affected, 1 warning (0.09 sec)

mysql> select * from example;
+--------+
| number |
+--------+
|     10 |
|      0 |
|      0 |
|     10 |
+--------+
4 rows in set (0.00 sec)

值得注意的是,MySQL在这些情况下会发出警告。但是,仅仅是警告而已,它们通常(若非总是)会被忽略。

ScriptKid
ScriptKid
翻译于 2015/03/11 15:46
1

此外,MySQL的另一个问题是,任何表的修改操作(例如:添加一列)都会导致表被锁,此时将无法进行读或写操作。这就意味着,使用这种表的任何操作都不得不等待修改完成之后才能进行。对于包含有大量数据的表,这可能会花费几个小时才能完成,很可能会导致应用程序宕机。这已经导致一些公司(例如SoundCloud)不得不自己开发工具(例如lhm)来解决该问题。

了解到上面的问题后,我们开始调查PostgreSQL。PostgreSQL可以解决很多MySQL不能解决的问题。例如,PostgreSQL中你不能将文本数据插入一个数字字段:

olery_development=# create table example ( number int not null );
CREATE TABLE

olery_development=# insert into example (number) values (10);
INSERT 0 1

olery_development=# insert into example (number) values ('wat');
ERROR:  invalid input syntax for integer: "wat"
LINE 1: insert into example (number) values ('wat');
                                             ^
olery_development=# insert into example (number) values ('what is this 10 nonsense');
ERROR:  invalid input syntax for integer: "what is this 10 nonsense"
LINE 1: insert into example (number) values ('what is this 10 nonsen...
                                             ^
olery_development=# insert into example (number) values ('10 a');
ERROR:  invalid input syntax for integer: "10 a"
LINE 1: insert into example (number) values ('10 a');
ScriptKid
ScriptKid
翻译于 2015/03/11 15:59
2

PostgreSQL 还具有在许多方式中不需要每一个操作都上锁就可以改写表的能力。例如,添加一列没有默认值却可以设置为null的列并能够快速完成无需锁定整个表。

还有其他各种有趣的功能,如在 PostgreSQL 可以:trigram 为基础的索引和检索,全文检索,支持JSON查询,支持查询/存储键-值对,支持发布/订阅等更多。

最重要的是PostgreSQL在性能,可靠性,正确性和一致性之间能够权衡。

Parser7
Parser7
翻译于 2015/03/11 09:33
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(111)

sidney9111
sidney9111
呵呵,文章其实还是不错的,我要抓图片和音频,所以我选择mongodb
tony_卢
tony_卢
表示都还没用过mdb,,
rustacean
rustacean
我竟然无聊到看完了评论,哇咔咔
btpka3
btpka3

引用来自“梅开源”的评论

往int里插文本? 为什么程序不做数据类型校验本身是个问题。。。
赞同,
panmingguang
panmingguang
看了这么久的评论, mongo 的确有不好的地方啊, 我mongo 超过6000W 后 用起来就很烦躁了,只能定期的转移数据
还有那个 无模式的 结构, 果断好坏难辨, 用来抓取 数据 很好, 其他方面 真的很烦躁, 导致开发上的结构混乱,
内存占用也是个问题, 我想做抓取个url 去重的 还是 转了 pgsql 来用了
zhangcjl
zhangcjl

引用来自“Brin想写程序”的评论

好文,作为13年的业余程序员,和5年的专业系统管理员和DBA,表示认同这个结论。
盲目的认为mongodb+node.js能解决一切问题的javascript程序员,太小看数据了。。

引用来自“开源中国匿名会员”的评论

没谁说盲从吧。别一早就把自己挂起来啦。 MEAN一种从前端走到后端的模式而已,不知道你哪里来的优越感。

引用来自“Brin想写程序”的评论

我是被前端人用js的优越感给鄙视了。。。非常不爽。 代码被人推翻了,用node.js给重写了。。

引用来自“开源中国匿名会员”的评论

自己不更新技术被推翻替代是理所当然的,有什么不爽。 你表示同意上述这种结论,那为什么你项目被推翻的时候你拿不出这种结论来反驳?所以你都没资格来不爽人家,对不?

引用来自“Brin想写程序”的评论

只不过不想反驳而已,在日常工作中我会保留自己的意见,大家和气生财。。 作为DBA用脚趾头想想都能明白mongodb这种灵活性的代价是什么。

引用来自“开源中国匿名会员”的评论

最烦你这种人了,说是说和气生财,完了背后议论人家。做技术又不是做政治,有不满的拿数据说话就是了。要不然要你DBA干嘛,一前端都满足公司需求了,该跳槽赶紧跳槽去。所以应该被不爽的人是你,在其位不谋其职,而不是你们公司那些可怜的前端。

引用来自“Brin想写程序”的评论

可惜我们这个地方是讲政治,不讲技术的。 boss都是和事老,我不让前端们所有系统都用mongodb,他们会跟我死磕到底。mongodb处理过程数据还是非常不错的。只要定期清理,或者作业结束后清理就没有问题。 但是运维和开发讲话,基本是鸡同鸭讲。。。

引用来自“开源中国匿名会员”的评论

那就没有什么不爽,说到底是你自己的选择。 在旗鼓相当的时候,能给人方便就给人方便。 真的到要紧的时候,你拿不出数据支持,仅凭你13的想法,你说服得了谁。拿得出性能数据,除非前端是老板的情郎,要不然就是你在公司实在是混得太差,要不然私以为没什么人会不接受的。所以别把自己那么早挂起来,脚踏实地点呗。

引用来自“Brin想写程序”的评论

刚调到现在这个部门不到半年,前端团队跟老板5年了。。 简直如胶似漆。。我不敢得罪。。

引用来自“开源中国匿名会员”的评论

……果然还是不能要老人进队伍,带来的好处比坏处小多了。连讲都不敢讲,然后就下这种结论了,那还有什么意思。调你一个DBA去一个前端为重的队伍不是当吉祥物养着好玩的吧?难不成你是萌妹没事可以调戏一下?

引用来自“Brin想写程序”的评论

这个说的不坚决是我的错。多次因为技术分歧 ,被领导拉去做思想工作。 不过我们公司,其实不能说是一个公司,是一个事业单位。 是一个外行领导内行的地方。 boss非计算机出身,其实都不理解DBA是干嘛的,他们对我们这种人的期望是系统不出问题。 他们只能从界面看到系统的变化,我在这里陪他们玩是我的错。 调到现在这个部门是上上级boss的意思,上上级boss认为现在这个部门工作效率太低,给他们补充人才和技术支援。

引用来自“开源中国首席一失足成千古风流人物以稀为贵”的评论

呵呵~ 凡是出现这种文章必定会出现两派.... 至于选择那种数据库是看业务需要和技术选型,你非得用mongodb存关系数据没人拦着你,但不能说mongodb不好~ 就好比有人说 php会代替java 一样~~ 嚯嚯哈哈.........................

引用来自“Brin想写程序”的评论

我在项目里面更喜欢用关系型数据库存json
+10086
f
felixng
postgresql8.3 以后,性能已经很高。后来,输给MySQL主要是缺乏群集方面的方案(尤其是multi master)。但后来也得到改善。今天的postgresql几乎适合任何项目。如果能灵活配搭mongodb和K/V store。。。就更加完美。
李三乎
李三乎

引用来自“灰度乌鸦”的评论

@李三乎 , @无若 ,请问这篇翻译里的压力测试(图片)的用的是什么软件?
你是说图片怎么画的么?这个不清楚啊也许是Numbers?感觉有点那个的风格。
完颜阿骨再打
完颜阿骨再打

引用来自“myplease”的评论

用mongodb主要是gridfs,有好的替代品吗

引用来自“Brin想写程序”的评论

moosefs
我选择的是FastDFS
完颜阿骨再打
完颜阿骨再打

引用来自“万一实现了”的评论

此外,MySQL的另一个问题是,任何表的修改操作(例如:添加一列)都会导致表被锁,此时将无法进行读或写操作。这就意味着,使用这种表的任何操作都不得不等待修改完成之后才能进行。对于包含有大量数据的表,这可能会花费几个小时才能完成,很可能会导致应用程序宕机。这已经导致一些公司(例如SoundCloud)不得不自己开发工具(例如lhm)来解决该问题。
============
在Mysql5.6版本中,有个online DDL的特性,它允许用户在修改表结构的时候,还可以做行读或写的操作。http://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl.html
就是。其实文章的一些论据站不住脚。
返回顶部
顶部