挑选正确的架构约等于选择正确的战斗并做好权衡
- 明确系统边界
- 用户案列 (描述哪些业务,事件,组合在一起会产生什么样的效果)
- 谁使用这个系统?
- 他们怎么使用这个系统?
- 约束条件
- 主要在规模上识别流量和数据处理的约束。
- 系统规模(例如:每秒请求数,请求类型,数据读写等情况)
- 特殊系统要求,如多线程、读或写。
- 高层次架构设计 (抽象设计)
- 绘制出下面各个组件间的连接(不需要具体细节)
- 应用服务层(处理请求)
- 不同的业务
- 数据存储层
- 可扩展系统通常包括Web服务器(负载均衡器)、服务(服务分区)、数据库(主/从数据库集群)和缓存系统。
- 组件设计
- 每个组件都需要: 组件 + 特定的 APIs
*面向对象设计的功能。
- 将特性映射到模块:一个场景对应一个模块。
- 考虑模块之间的关系:
- 某些函数必须具有单例模式
- 核心对象可以由许多其他对象组合而成.
- 一个对象继承自另一个对象
- 数据库表结构设计.
- 明确瓶颈
- 你的系统是否需要负载均衡以及许多机器用于处理用户请求?
- 数据是否非常大以至于需要分布存储到多台机器?这样做会带来什么样的负面影响?
- 数据库查询太慢,是否需要内存缓存?
- 扩容 你的抽象设计
- 垂直扩容
- 通过给当前机器增加更多的CPU/RAM等硬件进行扩容
- 横向扩容
- 通过添加更多的计算机进行扩容
- 缓存
- 负载平衡可以帮助您在不断增加的服务器上横向扩展,但是缓存将使您能够更好地利用现有资源,并使无法达标的结果变的可行。
- 应用层缓存 需要在程序代码中显式集成。通常它会检查值是否在缓存中;如果不在,则从数据库中检索该值。
- 数据库缓存 倾向于“自由”。使用数据库时将得到某种级别的默认配置,它将提供一定程度的缓存和性能。这些最初的默认设置是针对通用情况进行的优化,通过对这些设置的调整往往可以大幅提高性能。
- 内存缓存 将整个数据存储在内存中是最原始且有效的方式。这是因为对RAM的访问比对磁盘的访问要快几个数量级。例如memcached或redis。
- 例如,预计算结果(例如前一天来自每个参考域的访问次数)
- 例如,预生成的索引(例如,基于用户点击历史记录的故事建议)
- 例如,将频繁访问的数据在后端做一份复制(例如memcache而不是postgresql)
- 负载均衡
- 公共web服务藏在负载均衡器之后,这个负载均衡器将来自用户的请求平均分配到您的应用程序服务器组/集群上。
- 可伸缩Web服务的公共服务器隐藏在负载均衡器后面。
- 类型:智能客户端(难以完美实现)、硬件负载均衡器($$$ 昂贵但可靠)、软件负载均衡器(混合-适用于大多数系统)
-
数据库复制
- 数据库复制是指从一台计算机或服务器上的数据库向另一台计算机或服务器上的数据库进行频繁的电子复制,以便所有用户共享相同级别的信息。其结果是一个分布式数据库,用户可以在其中访问与其任务相关的数据,而不会干扰其他人的工作。为了消除用户之间的数据模糊性或不一致性而实现的数据库复制称为规范化。
-
数据库分区
- 关系数据的分区通常是指按行(水平)或按列(垂直)分表。
-
Map-Reduce
- 对于足够小的系统,你通常可以避开对数据库的即席查询(用户根据自己的需求,灵活的选择查询条件),但是,一旦存储或写入负载的数据量需要切分数据库,这种方法可能不会小幅度地扩展。为了执行这些查询,通常需要专用的从系统(此时你可能更乐意使用一个分析大数据的系统,而不是与数据库本身斗争)
- 添加一个map-reduce层可以在合理的时间内执行数据和(或)处理密集型操作。你可以使用它来计算社交图中的推荐用户,或者生成分析报告。例如: Hadoop,hive或hbase
-
平台层 (Services)
- 分离平台和Web应用程序允许你可以独立地缩放各个部分。如果添加新的API,则可以只需要添加平台服务,而不必为Web应用层添加不必要的容量??。
- 添加一个平台层是一种将基础结构重用到多个产品或接口(Web应用程序、API、iPhone应用程序等)的方法,而不必编写太多用于处理缓存、数据库等的冗余代码。
- 并发
- 你明白线程、死锁和饥饿吗?你知道如何并行算法是怎么运行的吗?你理解一致性和连贯性吗?
- 网络
- 你是否知道IPC和TCP/IP的大概工作方式?你知道吞吐量和延迟之间的区别吗?以及何时有哪些相关的因素?
- 抽象
- 你是否了解你所建立的系统?例如,你是否知道操作系统、文件系统和数据库是大概工作方式?现代操作系统中各种级别的缓存?
- 线上性能
- 你应该熟悉计算机一切的性能,包括RAM的相对性能、磁盘、SSD和网络等
- 评估
- 评估是非常重要的,尤其是在back-of-the-envelope(粗略计算,介于猜测和铁证之间)的计算方式下。因为它可以帮助你将可能的解决方案列表缩小到只有可行的解决方案。然后只需要编写几个原型或微基准(micro-benchmarks)。
- 可用性 & 可靠性
- 是否在考虑事情会为什么会失败,尤其是在分布式环境中?是否知道如何设计一个系统来应对网络故障?了解耐久性吗?
- 安全 (CORS)
- 使用CDN
- 内容分发网络(CDN)是一个用于根据用户的地理位子,网页来源和内容向用户交付网页和其他web内容的分布式(网络)系统。
- CDN服务可以有效地加速高流量网站以供全球访问。cdn服务器在地理位置上离用户越近,向用户传递内容的速度就越快。
- CDN同时提供了流量激增的保护(DDOS)
- 全文搜索
- 使用 Sphinx/Lucene/Solr - 通过搜索索引而不是直接搜索文本来达到快速响应
- 离线支持/Progressive enhancement
- Service Workers
- Web Workers
- 服务端渲染
- 异步加载 (延迟加载项)
- 最小化网络请求(Http2 + bundling/sprites etc)
- 开发生产力工具
- 可达性
- 国际化
- 响应式布局
- 浏览器兼容性
- 代码
- HTML5/WAI-ARIA
- CSS/Sass 标准规范
- 面向对象方法 (物体是如何分解并组合在一起的)
- JS 框架/组织/性能优化技巧
- 资产交付 - Front-end Ops
- 文档
- 新员工文档(Onboarding Docs)
- Styleguide/Pattern Library
- 架构图 (code flow, tool chain)
- 测试
- 性能测试
- 快照测试
- 单元测试
- 端到端测试
- 工作流
- Git 工作流
- 依赖管理 (npm, Bundler, Bower)
- 构建系统 (Grunt/Gulp)
- 发布流程
- 持续集成 (Travis CI, Jenkins)
Links
How to rock a systems design interview
Introduction to Architecting Systems for Scale
Scalable System Design Patterns
Scalable Web Architecture and Distributed Systems
What is the best way to design a web site to be highly scalable?