写点什么

系统设计中的简单法则

  • 2012-05-06
  • 本文字数:1878 字

    阅读完需:约 6 分钟

最近,包云岗在自己的博客中总结了系统设计中的基本法则——简单之美,列举了不少经典观点和案例。

他首先总结了麻省理工方法(MIT Approach)和新泽西方法(New Jersey Approach)的异同:

  • 简单性:两种方法都强调设计必须简单,这既是对实现的要求,也是对接口的要求。但是,MIT 方法认为接口的简单要比实现的简单更加重要,而 NJ 方法认为实现的简单要比接口的简单更加重要。
  • 正确性:设计在任何值得注意的方面都要保证正确。但是,MIT 方法认为不正确是绝对不允许的,而 NJ 方法认为,为了简单性,正确性可以做轻微的让步。
  • 一致性:MIT 方法认为,设计必须保持一致兼容。设计可以允许轻微少量的不简单和不完整,来避免不一致。一致性和正确性同等重要。而 NJ 方法认为,设计不能过度不兼容一致。为了简单,一致性可以在某些方面做些牺牲,但与其允许设计中的这些处理不常见情况的部分去增加实现的复杂性和不一致性,不如丢掉它们。
  • 完整性:设计必须覆盖到实际应用的各种重要场景。所有可预料到的情况都必须覆盖到。MIT 方法认为,简单性不能过度的损害完整性。NJ 方法则认为,为了保证其它几种特征的品质,完整性可以作出牺牲。事实上,一旦简单性受到危害,完整性必须做出牺牲。一致性可以为实现的完整性作出牺牲;最不重要的是接口上的一致性。

包云岗还引用了一个案例来证明两种方法的差异:

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

对于现在的互联网企业,是否还需要遵从这些法则呢?国外有篇博文《 Scalability lessons from Google, YouTube, Twitter, Amazon, eBay, Facebook and Instagram 》总结了各大公司的经验教训,其中第一条就是“保持简单”。但是包云岗认为,这和 New Jersey Approach 的原因和内涵有所不同。不同于 Unix 时代相对简单的单机系统,互联网时代的大公司的系统往往都是成千上万台机器,在这样的系统上部署、管理服务(软件)是一项非常有挑战的任务。而为大规模用户提供的一项服务往往会涉及到众多模块、若干步骤。此时“简单”就是要求每个阶段、每个步骤、每个子任务尽量采用最简单的解决方案,这是由于大规模系统内在的不确定性导致的复杂性决定的。

无独有偶,包云岗发现硅谷创业之父 Paul Graham 也推崇简单法则,Paul 在《黑客与画家》的“设计者的品味”一章中写到,“好的设计是简单的”、“简单就是美,正如漂亮的数学证明往往是简短而巧妙的那种”。他提到,有些创业者希望第一版就能推出功能齐全的产品,满足所有的用户需求,但这种想法是致命的。在硅谷创业最忌讳的就是“Premature Optimization”。因为一方面用户需求是多样的,不同人群都有不同的需求;另一方面开发者想象的需求往往和真实的用户需求有偏差。所以,Graham 推崇那种有用户参与反馈的迭代优化的方式。

包云岗还与普林斯顿大学计算机系的李凯教授有过简单法则的交流和讨论:

李凯老师的做事方式是——只抓住大方向,其他问题尽量简化。但真正要做到 KISS 原则其实并不容易。我在遇到问题时,往往会从各个方面去考虑问题,其中难免包含了各种细枝末节,这种方式导致问题经常会变得非常复杂。之前讲过这个例子,在移植 TCP/IP 协议栈到用户态时,我觉得有约 10 个功能需要考虑。和李老师讨论,他让我把那些功能分成两类:“必须有 (Must Have)”和“可以有 (Nice-to-Have)”。当我试了这种方法,发现原来 Must-Have 的功能其实也不过 2~3 个而已。而最近的例子则是在要设计一个功能让 TCP/IP 连接的 Server 在模拟器中、Client 在真实机器。我考虑是尽量减少模拟器上 OS 的开销,所以打算采用自己写一个设备、然后让用户态程序 Bypass Kernel 直接访问该设备的方案。但李凯老师在了解 OS 开销以后,认为容忍开销、尽量直接使用模拟器自己带的功能,让开发更简单。

这些教训也让我不断地去思考为什么要用 KISS 原则。慢慢地我体会到,KISS 原则目的其实是——“快速推进、逐步优化”。我们设计一个算法,往往可以在大脑中预先思考好,然后直接编程写出来。但是,我们设计实现一个系统,当系统的复杂度超出我们大脑的工作记忆容量时,就无法在大脑中去“模拟”每一个细节。此时,我们应该用最快的速度去把系统建起了,然后再对各个环节进行优化。

读者朋友对系统设计的简单法则有何看法?欢迎大家发表自己的意见。

2012-05-06 02:504670
用户头像

发布了 501 篇内容, 共 238.5 次阅读, 收获喜欢 55 次。

关注

评论

发布
暂无评论
发现更多内容

探测mysqldump详细过程

Simon

MySQL

Istio微服务治理笔记(一)

雪雷

istio 服务治理 server mesh

一文带你检查Kubernetes应用是否为最佳实践

雪雷

k8s k8s最佳实践

微服务API网关-Kong详解

雪雷

kong api 网关

Serverless初探

雪雷

Serverless Lambda 无服务器云函数

玩K8S不得不会的HELM

雪雷

k8s Helm

微服务注册发现配置中心-consul

雪雷

Consul 服务注册与发现 配置中心

Guacamole实战

雪雷

guacamole 远程登录 堡垒机

Linux系统检查脚本

雪雷

Shell 系统检测

Kubernetes-学习必备(awesome-kubernetes-notes)

雪雷

学习 k8s入门 k8s文档 k8s知识

Gitlab Pipeline+Supervisor 实战Python项目CI/CD

雪雷

gitlab jenkins CI/CD Supervisor

Jenkins 详解

雪雷

jenkins

记一次混合云API发布的反思

雪雷

iptables API api发布

Docker+Jenkins+Gitlab+Django应用部署实践

雪雷

DevOps jenkins CI/CD

RabbitMQ实践

雪雷

RabbitMQ 消息队列

Ceph集群部署

雪雷

分布式存储 Ceph rdb pvc

业务容器化改造

雪雷

Docker 容器 微服务 服务化改造

Jenkins部署Python项目实战

雪雷

Python jenkins CI/CD

Prometheus + Grafana详解

雪雷

监控 Grafana Prometheus 告警

Python利用sphinx构建个人博客

雪雷

sphinx Blog

Linux自定义快捷工具

雪雷

Linux Shell tools scripts

Golang领域模型-开篇

奔奔奔跑

微服务 后端 领域驱动设计 架构设计 Go 语言

支付宝蜻蜓刷脸支付

诸葛小猿

支付宝 蜻蜓 刷脸支付

Flink高可用性设置-4

小知识点

scala 大数据 flink 流计算

JVM-技术专题-GCViewer调优GC

洛神灬殇

JVM

Apache常用配置指北

亻尔可真木奉

Apache 代理 跨域

Elasticsearch安装

北漂码农有话说

API统一管理平台-YApi

雪雷

YAPI API接口管理

SonarQube集成gitlab/jenkins

雪雷

jenkins sonar gitlab ci 代码扫描

Docker Web管理工具

雪雷

Docker shipyard dockerui

记一次混合监控的反思

雪雷

监控 zabbix redis监控 监控宝

系统设计中的简单法则_架构_崔康_InfoQ精选文章