当前位置

Scale Fail (part 1)

http://lwn.net/Articles/441790/
By Josh Berkus
May 6, 2011
翻译:王鑫

让我告诉你们一个秘密:我从来不去修正数据库,我去修正程序。

许多公司总是请我去“修正数据库”,因为他们总是认为造成他们性能和宕机的问题是出在数据库上。其实,数据库很少出现问题。可伸缩性糟糕的应用总是由一系列错误的管理决策所造成的。事实上,这些错误的决策是如此常见以致于可被称之为反面模式。

  1. 译者注:所谓“模式”,是指遵从某种规则或规律所反复出现的思维方式或表现。Alexander把模式的集合称为模式语言(Pattern Language)。构成模式语言的各模式是针对某一特定前提的求解,记述频繁发生的现实问题及其基本解法。这些解法可以反复使用,只要出现同类问题就可以使用同一解法,而不必总是一切从头做起。
  2. 反面模式(Anti-Patterns)的概念产生于1996年,是米切尔•阿克鲁在研究软件开发的既存问题及其解法时归纳产生。反面模式主要研究最常见的拙劣软件模式特征及其识别方法,以及反面模式“再构”的改善方法。
  3. 具体参考:<a href="http://www.job108.com/App/show_article.aspx?m=00276AEAA000058F6

">www.job108.com/App/show_article.aspx?m=00276AEAA000058F6[/geshifilter-code]
 
我在上一次的MySQL会议上做了一点关于反面模式的讨论,先去看看再继续来讨论。当你已经看过了这个五分钟的小短片(希望你笑了),下面介绍几个解释怎样识别和避免反面模式的细节。

Trendiness

  1. “现在,你们为什么还要去迁移数据库呢?你们三个月没有出过问题,而且我们计划在未来两年内继续延长这个时间。迁移数据库可能会导致服务中断或者混乱。”
  2.  
  3. “好吧……我们的CTO是每周CTO午餐会中唯一使用PostgreSQL的。其他的CTO总是在这个上面开他玩笑。”

这是不是听起来就好像你的CTO一样?这可是源于一次我真实的对话。它说明了越来越多的技术负责人开始思考一个问题:比起站点是否仍在运营或者公司正常运转而言,他们更关注个人形象和职业。如果你开始在一些基础会议上听到诸如“流行”、“热点”、“前沿”、“最新技术”或者“流行产品”,那么你就得当心了。频频引用杂志上的调查结果或者产业趋势是另外一个危险信号。

Scaling 应用本质上就是关于资源管理和重复性的日常工作。这意味着使用你的员工熟悉的,已经被证实为可靠的,并且就是按照你所想的而设计的技术。热门新特性不如无人值守的可靠运营。web世界里总把一个个崭新的技术推到前台,尽管它们匮乏文档、不稳定、不能同其它组件集成,并且充满各种漏洞。

还有另一种趋势值得被注意,常常听到这样的言论,“如果Google或者Facebook在做某件事情,那它一定就是正确的选择。”首先,除非你的应用程序或平台同他们的非常类似,那么对他们而言是正确选择的事情不一定对你也是正确的选择。

此外,并不是每件Google和Facebook做的事情,如果让他们从来一遍他们还会去做。像其他的公司一样,这些顶级的互联网公司也做过错误的技术决策。所以当你将要模仿那些巨头们的行为时,请首先确定一下他们的员工对这个技术的看法。

No metrics

  1. “我们确实检查过了网络延迟吗?”
  2.  
  3. “我确信问题是出现在HBase中。”
  4.  
  5. “恩,但是我们检查过没有呢?”
  6.  
  7. “我告诉你,我们根本不必检查。这个总是HBase的问题。”
  8.  
  9. “给个面子,告诉我。”
  10.  
  11. “或许吧。恩……哦!我想网络可能是有点问题。”

 
Scaling 应用是一个数学问题。如果一个用户在web服务器上消耗X个CPU时间,那么你想支持100,000个用户的并发访问时,你需要多少个web服务器呢?如果数据库每天增长Y,而其中Z%的数据是“active”,那么这些常用数据的大小超过RAM的容量需要多少时间?

明显地,你至少需要知道X、Y、Z的近似值才能对此类问题作出估计。如果你在做scale,你应该考虑你的应用程序栈的每一个部分,从存储硬件到JavaScript。而那个你忘了监控的东西很有可能就是让你整个站点挂掉的原因。近年来的大多数软件都有一些监控它们性能的方法,软件不应该成为你规避的部分。

尽管这是一个常识,我们的客户中仍然有相当多的一部分仅仅用Nagios监控它们的硬件。这意味着当出现响应时间的问题或者其它一些超过Nagios能力范围内的问题时,他们无法去诊断到底是什么原因引起这种问题的,而且到头来,他们总是去修正错误的部分。

更糟的是,如果你没有你的应用程序实际消耗资源的统计的话,那么你就不知道当你去扩充你的站点时,你需要多少、哪种类型的服务器。那意味着你将对某些组件进行大规模地重建,并且花费两倍的金钱,而其它部分只能缩减。

有多少个公司没有测量数据,或者跳过这个问题,他们是怎么做决策的?呃……

Barn door decision making

  1. “当我在亚马逊的时候,我们使用squid做反向代理。”
  2.  
  3. “Dan,你在亚马逊的时候是一个广告销售经理吧。”

 
缺乏数据的情况下,员工一般都根据他们的经验来排解故障,而这往往是错误的。尤其当出现突发事件时,一般都会去解决上次出过问题的那个部分。当然,上次出问题的地方,不一定是这次造成这次问题的原因。

当你计划扩容的时候,这种思想会更糟糕。我见过许多IT员工依靠他们上一个项目的经验甚至上一份工作的经验来购买设备,提供服务,配置软硬件,部署网络。这意味着,当现有应用程序的可用资源不能够完全匹配应用程序的需求时,你要么为此提供更多,要么挂掉。

当然你应该从你的经验中学习。但是你应该学些合适的教训,比如“不要指望VPN总是连通的”。不要误用知识,比如把应用到图片站点的cache策略应用到在线银行站点上来。反例通常类似如下的格式的断言:

  •  “当我在XXX(原来的公司名)的时候……”
  •  “当我们原来遇到XXX(其实并不是很相似的问题)的时候,我们用XXX(某种软件或技术)”
  •  “XXX(差别很大的项目)使用XXX(某种软件或技术),因此我们也改使用它。”

(For non-native English speakers, "barn door" refers to the expression "closing the barn door after the horses have run away")

下面我们检讨程序设计中的问题

Single-threaded programming

  1. “因此,当我在Rails中monkey-patch一个普通类的时候,什么时候该改动会影响到这个正在运行的并行进程呢?”
  2.  
  3. “立刻就会!那很神奇的!”

 
并行处理的框架对大多数开发者来说都是一个挑战。我见过上百次这样的故事了:一个开发者把他的代码写成了单线程的形式,然后他在自己的笔记本上,在单用户单并发的情况下测试,之后他把这份代码部署到了有200个服务器的站点上,然后这个站点挂了。

单线程是可扩展性的敌人。你的应用程序的任何一部分,如果限制了同一时刻并发执行同样代码的能力,那意味着把你限制在单机单核的吞吐量上。我并不是在这里讲应用程序代码中关于互斥的部分,尽管那也可能很糟糕。我在讨论的是由于等待某个独占锁式的组件而阻塞了整个应用程序的设计问题。

比如,一个入门新手常犯的错误就是把所有的异步任务放到一个单向队列里去。这样整个应用都受限于这个队列处理的速度。其它常见的错误包括:frequently updated single-row "status" table, explicit locking of common resources, and total ignorance of which actions in one's programming language, framework, or database require exclusive locks on pages in memory.

我当前工作的应用是一个分布式的,拥有240台服务器的数据处理集群。然而,把数据分块交给服务器运算的部分是一个只跑在一台服务器的单进程程序。于是整个云每分钟只能处理4000个任务,75%的时间是空闲的

更糟糕的例子是我以前咨询过的一个很流行的体育站点。赛事信息是从互联网上其它的服务获取的,更新信息的时候它会在数据库事务里保持一个独占锁,然后等待远程服务器响应。客户无法明白为什么增加的应用服务器越多,用户的超时就越严重。

设计可伸缩的应用之前,问问自己:"how would this work if 100 users were doing it simultaneously? 1000? 1,000,000?"。学习一门函数式语言或者 map/reduce. 这会训练你思考并行的能力

=============
等待下集

Topic: