系统设计黄金法则:简单之美

发表于:2012-05-14来源:不祥作者:包云岗点击数: 标签:系统设计
最近多次看到系统设计与实现的文章与讨论,再加上以前读过的其他资料以及自己的一些实践教训,让我觉得应该把这些资料汇总整理一下。如果要从讨论不同系统的众多资料中总结一条黄金法则的话,那只有一个词——“简单”;如果用一个英语单词来表达的话,那就是

  最近多次看到系统设计与实现的文章与讨论,再加上以前读过的其他资料以及自己的一些实践教训,让我觉得应该把这些资料汇总整理一下。如果要从讨论不同系统的众多资料中总结一条黄金法则的话,那只有一个词——“简单”;如果用一个英语单词来表达的话,那就是——KISS (Keep It Simple, Stupid!)。

  麻省理工方法与新泽西方法(MIT Approach vs. New Jersey Approach)【1】【2】

  这个观点来自一篇很经典的文章,Richard Gabriel在1989年写的文章中的一节“The Rise of 'Worse is Better'”。说来惭愧,我是直到2011年5月在IBM T.J. Watson实验室听报告才第一次听说,当时便印象深刻。后来上普林斯顿的高级系统设计课程,发现这篇文章也在Reading List中,要求所有学生阅读然后在课上讨论。

  “The Rise of 'Worse is Better”对比了以LISP系统为代表的麻省理工方法和以Unix/C为代表的新泽西(贝尔实验室)方法。Gabriel发现相比于LISP/CLOS系统完美的设计,Unix/C只是一味追求实现简单,但事实却证明Unix/C像终极计算机病毒那样快速蔓延,奠定了今天计算机系统的基础。

  让我们来看看这两种不同的设计哲学。

  1)MIT Approach

  简单性:设计必须简单,这既是对实现的要求,也是对接口的要求。接口的简单要比实现的简单更加重要。

  正确性:设计在任何值得注意的方面都要保证正确。不正确是绝对不允许的。

  一致性:设计必须保持一致兼容。设计可以允许轻微少量的不简单和不完整,来避免不一致。一致性和正确性同等重要。

  完整性:设计必须覆盖到实际应用的各种重要场景。所有可预料到的情况都必须覆盖到。简单性不能过度的损害完整性。

  2)New Jersey Approach

  简单性:设计必须简单,这既是对实现的要求,也是对接口的要求。实现的简单要比接口的简单更加重要。简单是设计中需要第一重视的因素。

  正确性:设计在任何值得注意的方面都要求正确。为了简单性,正确性可以做轻微的让步。

  一致性:设计不能过度不兼容一致。为了简单,一致性可以在某些方面做些牺牲,但与其允许设计中的这些处理不常见情况的部分去增加实现的复杂性和不一致性,不如丢掉它们。

  完整性:设计必须覆盖到实际应用的各种重要场景。所有可预料到的情况都应该覆盖到。为了保证其它几种特征的品质,完整性可以作出牺牲。事实上,一旦简单性受到危害,完整性必须做出牺牲。一致性可以为实现的完整性作出牺牲;最不重要的是接口上的一致性。

  如果觉得这种哲学描述太抽象的话,原文中有一个关于Unix中断处理的例子,非常生动。一位MIT的教授一直困恼于Syscall处理时间过长出现中断时如何保护用户进程某些状态,从而让用户进程能继续执行。他问新泽西人,Unix是怎么处理这个问题。新泽西人说,Unix只支持大多数Syscall处理时间较短的情况,如果时间太长出现中断Syscall不能完成,那就会返回一个错误码,让用户重新调用Syscall。但MIT人不喜欢这个解决方案,因为这不是“正确的做法”。

  Unix/C开发于1970年前后,那时离1964年刚推出的IBM System/360没几年,软件刚摆脱硬件束缚,能移植到不同的机器上,从而变成了一种可单独出售的产品。就是这样的一个软件产业的萌芽期,这种“实现简单”的理念被证明是更有效的。那么在今天的互联网时代,这种理念还有效吗?我们再来看下一篇文章。

  来自互联网巨头们的教训【3】

  这是最近看到的一篇文章,作者从High Scalability Blog上总结了几大互联网在设计后台数据中心所遇到的教训(这篇文章总结的非常好,强烈推荐大家读一下)。文章开头就总结了七个互联网公司(Google, YouTube, Twitter, Amazon, eBay, Facebook and Instagram)都提到的6点教训:

  Keep it simple - complexity will come naturally over time.

  Automate everything, including failure recovery.

  Iterate your solutions - be prepared to throw away a working component when you want to scale it up to the next level.

  Use the right tool for the job, but don't be afraid to roll your own solution.

  Use caching, where appropriate.

  Know when to favor data consistency over data availability, and vice versa.

  第一点就是“简单”,但和New Jersey Approach的原因和内涵有所不同。不同于Unix时代相对简单的单机系统,互联网时代的大公司的系统往往都是成千上万台机器,在这样的系统上部署、管理服务(软件)是一项非常有挑战的任务。而为大规模用户提供的一项服务往往会涉及到众多模块、若干步骤。此时“简单”就是要求每个阶段、每个步骤、每个子任务尽量采用最简单的解决方案,这是由于大规模系统内在的不确定性导致的复杂性决定的。

  即使做到了每个环节最简单,但由于不确定性的存在,整个系统还是会出现不可控的复杂性。比如,Google的Jeff Dean最近在UC Berkeley有个报告【4】介绍他们努力缓解大规模数据中心中的Long-Tail Latency难题。问题简单描述如下:假设一台机器处理请求的平均响应时间为1ms,只有1%的请求处理时间会大于1s (99th-Percentile)。如果一个请求需要由100个这样的节点一起处理,那么就会出现63%的请求响应时间大于1s,这样的系统完全是不可接受的。面对这个复杂的不确定性问题,Google他们做了很多工作,权衡各种Tradeoff,具体请看这个报告【4】。

  大规模数据中心,看起来似乎和我们普通的开发人员离得比较远。但最近看Paul Graham写的《Hackers and Painters》这本介绍硅谷创业公司的书,发现Graham也在多处强调“简单”。

  Paul Graham的《Hackers and Painters(黑客与画家)》

  Paul Graham被称为“硅谷创业之父”。他在1995年和MIT的Robert Morris教授创办了Viaweb,于1998年被Yahoo!以4900万美元收购。2005年,他又创办了Y Combinator创业孵化器公司,帮助80多家创业公司成长起来,其中包括Dropbox(市值大于40亿美元)、Airbnb(市值大于13亿美元)等。显然,Graham有丰富的创业经验。

原文转自:http://www.ltesting.net