高扩展性网站的50条原则

A.化简方程

一.不要过度设计
目的:防止设计中出现复杂的解决方案。

适用情形:适用于任何项目,所有大型的或复杂的系统和项目都应该采用该原则。

应用方式:让同行来检查解决方案是否好理解,抵制过度设计的强烈欲望。

应用理由:复杂的解决方案实施成本高,而且会产生大量长期成本。

要点:过度复杂的系统会限制扩展能力。简单的系统更容易维护和扩展,且成本更低。

过度设计有7类:

1.设计与实现超出有用需求

2.开发过于复杂的产品或使用系统过于复杂而且让用户感觉使用起来很吃力

3.软件复杂得让其他开发人员难于理解难于维护。

4.软件复杂得难于向其它人陈述清楚过度设计的方案

5.过度设计的方案既浪费金钱又浪费时间,浪费资源,增加扩展成本,且会限制整 个系统的整体扩展能力

6.过度设计的方案让你无从加入新 程序员或者难于给系统增加新功能

7.反思应如何做才能让系统越来越简单化

伟大程序员特征:快速将复杂问题简单化;快速开发出一个易理解易维护的解决方案。

二AKF模式:设计时就考虑扩展性(D-I-D方法)

目的:提供JIT(Just In Time)扩展性能力。

适用情形:适用于所有项目;此方法是确保可扩展性的成本(资源和时间)最低的方法。

应用方式:

设计(Design)20倍的容量;

实现(Implement)3倍的容量;

部署(Deploy)约1.5倍的容量。

应用理由:D-I-D给产品扩展提供了成本最低的JIT方法。

要点:提前考虑如何扩展解决方案,在实际需要前大概一个月(编程)实现它,或者在客户急需时提前几天实现它,会给开发团队节省很多金钱和时间。

三.把方案一简再简

目的:在设计复杂系统时使用此原则简化方案的范围、设计和实施。

适用情形:在(编程或者计算)资源有限的情况下设计复杂系统或产品时使用。

应用方式:

用帕累托法则简化范围;

从成本效率和可扩展性出发简化设计;

利用他人的经验简化实施。

应用理由:只是着重于"不要复杂"不能解决需求、故事及事件编排和真正的实施带来的各种问题。

要点:在产品开发的各个方面都要简化需求。

1.去除产品中不必要的功能,提倡“最小可行性产品“

2.在系统设计阶段就用一种 “易理解,低成本,可扩展”的方式来完成工作

3.先看有没有开源或第3方解决方案,没有这样的方案就在公司内部问问是否有人已开发了能解决该问题的可扩展方案;还没有就从外部寻找是否有人描述过或发表过文章描述该问题。facebook的原则:不核心的功能就优先采用开源的,核心的功能就算有成熟稳定的开源解决方案也必须要公司内部自己开发。

四.减少DNS查找

目的:从用户角度减少DNS查找。

适用情形:所有性能至关重要的Web页面。

应用方式:减少下载页面所需的DNS查找,不过要权衡考虑浏览器对同时连接的限制。

应用理由:DNS查找需要花费大量的时间,大量的DNS查找会影响用户体验。

要点:减少对象、任务、计算等都可以加速页面载入,但同时也要考虑工作分解。

尽量把所有的css,js,image对象放在一个域中,但要考虑浏览器最大同时连接数的问题

五.尽可能减少对象

目的:尽可能减少页面上的对象。

适用情形:所有性能至关重要的Web页面。

应用方式:

减少或合并对象,但要与最大同时连接数进行平衡;

测试修改过的页面,确保性能提高了。

应用理由:对象数量会影响下载时间。

要点:对象和提供它们的方法之间的平衡是一门学问,需要适时调整。这是客户的可用性、有用性和性能之间的平衡。

减少,合并并压缩对象(css, image, js)

六.使用同一品牌的网络设备

目的:不要混用供应商的网络设备。

适用情形:在设计和扩展网络时使用。

应用方式:

不要混用不同供应商的网络设备(交换机和路由器);

其他网络设备(防火墙、负载均衡器等)要买品牌最好的。

应用理由:不应该为了省点钱,就去应付时不时出现的互操作性和可用性问题。

要点:不同品牌的网络设备可能会造成可用性和扩展性问题。最好只选择一个供应商。

不要混用不同供应商的网络设备(交换机和路由器);其它网络设备(防火墙,负载均衡器等)要买品牌最好的。

B.分布工作,采用AKF扩展立方模式

七.横向复制(X轴原则)

目的:横向扩展,即复制服务或数据库来分散事务负载。

适用情形:

具有非常高读写比例(5:1或更高,越高越好)的数据库

事务增长大于数据增长的系统。

应用方式:

只需克隆服务并实施负载均衡;

对于数据库,要确何访问代码能够区分读写操作

应用理由:复制数据和功能可以使事务更快地扩展

要点:X轴拆分方法能够快速实现,但是只能提高事务的扩展性,不能提高数据的扩展性

八:拆分不同的东西(Y轴原则)

目的:有时该原则被称为通过服务或资源进行扩展,重点是扩展数据集合,事务和程序员小组。

适用情形:

非常大的数据集合,数据间关系并不重要;

大型的复杂系统,需要特别扩展编程资源。

应用方式:

用动词拆分操作,用名词拆分资源,或者兼而有之;

根据动词/名词方法的定义,拆分服务和数据。

应用理由:不仅能有效地扩展事务,还能有效地扩展与事务有关的大型数据集合

要点:Y轴拆分,或者说面向数据/服务的拆分,能够有效地扩展事务,大型数据集合,并且有助于故障隔离。

九.拆分相近的东西(Z轴原则)

目的:通常可以利用用户特有的属性进行拆分,如用户ID,姓名,所在地等。

适用情形:非常大的相似数据集合,如快速增长的大型用户群。

应用方式:标识你所知道的客户属性,如用户ID,姓,所在地或设备,根据这些属性拆分数据和服务。

应用理由:用户信息的增长速度超过了其它所有数据的增长,或者你需要在要扩展的某些用户群之间执行故障隔离。

要点:Z轴拆分除了有助于扩展用户群,还适用于其他不能采用Y轴拆份方法的大型数据集合。

C横向扩展设计

十.设计横向扩展方案

目的:所谓横向扩展,就是通过复制服务或数据库来分散事务负载,而纵向扩展即购买更大的硬件。前者可以替代后者。

适用情形:适用于任何预计会快速增长的系统,服务和数据库。

应用方式:利用AKF扩展立方确定环境的正确拆分方法。通常,横向拆分(克隆)是最简单的方法。

应有理由:只需要复制数据和功能就可以快速扩展事务。

要点:为成功做好计划,把系统设计为能够横向扩展的。不要让自己陷入如此困境:要进行纵向扩展时,却发现已经没钱购买更快更大的系统了。

十一.采用经济型系统

目的:尽可能采用小的,便宜的系统。

适用情形:在超高速发展阶段,在生产环境中采用该方法。

应用方式:在生产环境不要采用非常大的系统。

应用理由:允许低成本的快速发展。

要点:采用经济型硬件构建系统,不要让自己陷入高利润,高端服务器的陷阱。

十二.横向扩展数据中心

目的:设计具有三个或更多实时数据中心的系统,以减少整体成本,提高可用性以及实现灾难恢复。

适用情形:适用于任何考虑加入一个灾难恢复(冷备份)数据中心的超高速发展的公司。

应用方式:采用“多个实时数据中心”的配置,拆分你的数据,分散到这些数据中心,把事务负载也分散到这些数据中心。利用多余的容量来应对每年的高峰期。

应用理由:对你的业务来说数据中心出现故障是灾难性的打击。通常设计为三个或更多个数据中心,因为这样成本比只有两个数据中心低。在高峰期利用闲置的容量,而不是降低处理事务的速度。

要点:在实施灾难恢复时,利用三个或更多个实时数据中心的设计,可以降低灾难恢复的成本。在必要时,可以得用闲置容量满足高峰期的需求。

采用3个数据中心, 站点A:存100%A数据,备份50%B数据,50%C数据。站点B:存100%B数据,备份50%A数据,50%B数据;站点C:存100%C数据,备份50%A数据,50%B数据。任何一数据中心出现故障,那么该数据中心50%数据和相关事务都会被转移到其它两个数据中心。

多个实时站点注意事项:

多个实时站点的好处包括:

1.与热/冷站点配置相比,具有更高可用性;

2.与热/冷站点配置相比,成本更低;

3.对于动态调用,如果把用户路由到最近的数据中心,那么用户响应时间更短;

4.把产品分布到SaaS环境中,会得到更大的灵活性;

5.与冷/热站点配置相比,实施起来信心更足;

6.利用每个数据中心的空闲容量可以轻松迅速地应对尖峰时刻激增的需求。

多个实时站点的缺点或问题在于:

1运维复杂度更高;

2.人员数量可能会稍微增加;

3.出差成本和网络成本有所增加。

迁移到多个实时站点环境中有关架构方面的考虑:

1.尽量减少对状态和关联性的需求;

2.尽可能把用户请求路由到最近的数据中心,从而减少动态调用的次数;

3.必要时要研究数据库和状态的复制技术。

十三.利用云技术进行设计

目的:有目的地利用云技术应对突发的扩展。

适用情形:临时的,激增的或者间歇性的需求,或者产品响应时间并非关键因素的情况。

应用方式:对于临时需求,如大型的批量作业或者测试阶段所需的QA环境,可以利用第3方云环境;

设计应用,使其能够在需求激增到一定水平时接受来自第3方云设备的请求。

应用理由:准备云环境中的硬件只需要几分钟,而在你自己的数据中心准备物理服务器则需要几天或几周。对于临时应用,这种 方法非常划算。

要点:利用虚拟化和云技术进行设计,以应对突然激增的需求。

D.使用正确的工具,锤子定律:“如果你只有一把锤子,没有其它工具,那么你自然会把每个问题都看成钉子”,它的含义是:1解决问题时总是选择自己熟悉的工具;2.公司中员工应该既掌握相同的关键技术和工具,又必须要有人掌握不同的工具和技术。

十四.合理使用数据库

目的:当你需要ACID属性来维护数据间的关系时,可以用关系型数据库。对于其它的数据存储,需要考虑更合适的工具。

适用情形:适用于在系统架构中引入新数据或数据结构时。

应用方式:在选择最合适的存储工具时,要考虑数据量,存储空间,响应时间的要求,关系以及其它多种因素。

应用理由:RDBMS提供了最好的事务完整性,但相对于其他存储选择,这种数据库很难扩展且成本高,可用性低。

要点:为数据选择正确的存储工具。不要因为你习惯用数据库访问数据,就总用关系数据库存储数据。

只有要求事务完整性或数据间有关系的数据,才需要使用RDBMS,否则最好采用其它存储系统。“一次写,多次读”情况下文件系统是个很好的选择(注意文件读写锁冲突)。还有一种策略叫NoSQL(写过之后需要更新),另外根据“成本-数据价值”我们可以不停地把老数据切割到便宜的访问较慢的媒体上。

十五. 防火墙,到处都是防火墙

目的:只有当防火墙能够显著减少风险,并且你能认识到它们会引发扩展性和可用性问题时,才使用防火墙。

适用情形:无论何时都适用。

应用方式:只对遵从PII和PCI等法则的重要数据采用防火墙。对价值低的静态数据,不要采用防火墙。

应用理由:防火墙会降低可用性,造成不必要的扩展瓶颈。

要点:虽然防火墙很有用,但它们通常会被滥用,如果设计或实施不当,可用性和扩展性都会受影响。

根据经验,造成站点故障停工的首要原因是数据库故障,其次就是防火墙故障。像css, image, js这种资源文件不应经过防火墙。

十六. 积极利用日志文件

目的:利用应用的日志文件诊断问题并防止问题出现。

适用情形:落实监控日志文件的流程,强制人们对发现的问题采取措施。

应用方式:利用各种监控工具,如定制的脚本或者Splunk,观察应用的日志,找出错误。导出这些错误,指派人员识别并解决相关的问题。

应用理由:日志文件是很好的信息源,可以了解应用是如何执行的。不要对它置之不理。

要点:好好利用日志文件,可以减少系统的生产问题。

监控日志文件工具:Cricket, Cacti, Splunk(集合监控日志工具)

E.不要重复工作:不要重复你自己DRY,不要反复做一些表面看起来很小的事。

十七. 不要立即检查刚做过的工作

目的:不要立即检查刚做过的事情,也不要立即读刚写过的数据。

适用情形:一直适用(后面会解释原则冲突的问题)。

应用方式:绝对不要为了验证而立即读刚写过的数据。为了近期内的运维需要,可以把数据存储在本地或分布式的缓存中。

应用理由:验证工作相对于不太可能出现的故障来说成本更高。这种活动有悖于有效扩展的需求。

要点:绝对不要为了验证数据而立即读刚写入的数据,而要读并处理与写操作相关的错误。把数据存储在本地可以避免对刚写入的数据的其他读操作。

十八. 停止重定向

目的:尽可能避免重定向,必要时采用正确的方法。

适用情形:尽可能少使用重定向。

应用方式:如果必须使用重定向,可以考虑使用服务器配置,而不是HTML或其他基于代码的解决方案。

应用理由:一般说来,重定向都会造成延迟,消耗计算资源,且容易发生错误。

要点:正确使用重定向,且只在必要使用。

Post/Redirect/Get(PRG)模式,可避免重复提交表单,但这种模式不能滥用。

Http 3xx一类的状态码是重定向相关的代码

十九. 放松时序约束

目的:尽可能减少系统中的时序约束。

适用情形:当你想添加一个约束,使某个物品或对象在用户的两个动作之间维持某个状态时,该原则都适用。

应用方式:放松业务原则中的约束。

应用理由:由于大多数RDBMS的ACID属性,扩展具有时序约束的系统非常困难。

要点:在需要添加约束时,例如让物品从用户看到它们直到用户购买它们都存在,要认真考虑。虽然某些特殊情况可能会令客户失望,但是弥补客户比起不能扩展来说容易得多。

用BASE方案解决CAP架构问题,BASE代表基本可用(Basic Available),软状态(Soft state), 最终一致性(Eventually Consistent)。BASE架构通过放松一致性的ACID属性,在扩展性方面可得到更大的灵活性。

F.积极利用缓存:缓存为王

二十.利用CDN:CDN和ESI

目的:利用CDN分担站点流量。

适用情形:在成本合理的情况下,再选择哪些内容最适合。

应用方式:大多数CDN利用DNS,从而替站点来提供内容。

应用理由:CDN有助于分流高峰期的流量,通常是扩展站点部分流量的的经济型方法。

要点:总体说来,CDN可以简单快速地分散流量高峰和流量增长。确保做成本效益分析,监控CDN的使用。

二十一: 使用过期头:Cache-Control, Expires,使用Http持续连接Keep-alives重用TCP连接。

目的:使用过期头减少请求,提高系统的可扩展性和性能。

适用情形:适用于所有对象类型。

应用方式:可以在WEB服务器上设置,也可以通过应用代码设置。

应用理由:减少对象请求可以提高页面性能,减少系统必须处理的每个用户的请求数。

要点:要考虑每种对象类型是(图像,HTML, CSS, PHP等)可以缓存多久,从而正确设置过期头。

二十二. 缓存Ajax调用

目的:使用正确的HTTP响应头,确保缓存Ajax调用。

适用情形:除了绝对需要实时更新数据的Ajax调用,其他都适用。

应用方式:正确修改HTTP头Last-Modified, Cache-Control和Expires。

应用理由:减少用户感知的响应时间,提高用户满意度,提高平台或解决方案的可扩展性。

要点:尽可能地利用Ajax和缓存Ajax调用,可以提高用户满意度,提高可扩展性。

像“page=3&item=2"这样相对名字的url可能会造成缓存一致性问题,最好方法是使用“id=123445"这种方法进行缓存(id可为member_id).

二十三. 利用页面缓存

目的:在Web服务之前部署页缓存。

适用情形:任何情形。

应用方式:选择一种缓存系统并部署它。

应用理由:通过缓存和响应之前生成的动态请求,迅速响应静态对象的调用,从而降低Web服务器的负载。

要点:页面缓存是分流动态请求并有效进行扩展的好方法。

页面缓存是安装在web服务器之前的缓存服务器,用于卸载对服务器上静态,动态对请象的请求.

在这原则中有3个关键点:1应在web服务器前实现页面缓存(反向代理nginx /varnish/CDN) 2.使用正确的http头(Cache-control, Last-modified, Expires), 3推荐用ETag.

二十四:利用应用缓存

目的:尽可能减少系统中的时间约束。

适用情形:适用于任何想添加时间约束,要求一个物品或对象在用户动作之间维持某个状态的情况。

应用方式:放松业务原则中的约束。

应用理由:由于大多数RDBMS(关系数据库管理系统)具有ACID属性,要扩展具有时间约束的系统非常困难。

要点:要慎重考虑对于约束的需求,如要求从用户看到物品直到购买它时它一直可用。对于某些边缘情况,补偿用户的失望比不能扩展系统好得多。

什么是应用缓存:从代码层面上,通过代码逻辑和缓存策略根据实际情况选择将数据存放在应用所在服务器的文件系统或者内存中,减少数据库查询或者读写瓶颈,提高响应效率。

1.如果你想以具有成本效益的方式进行扩展,必须采用应用层缓存

2.这种缓存方式必须从系统架构的角度出发,以使其长期有效

3.迭代性地应用帕累托法则和AKF扩展立方(原则7,8,9)来细化和提高缓存命中率

二十五.利用对象缓存:如memcached

目的:实现对象缓存,帮助系统扩展。

适用情形:适用于任何有反复查询或计算的情况。

应用方式:从众多开源方案或供应商支持的解决方案中选择一种,在你的应用代码中调用它。

应用理由:一个简单明了的对象缓存可以节省应用服务器或数据库服务器上的很多计算资源。

要点:在任何要反复执行计算的地方,实现对象缓存,但该方法主要应用于数据库和应用层。

二十六. 把对象缓存放在自己的“层”上:要有1个专用的缓存层.

目的:在架构中为对象缓存单独设置一个层。

适用情形:适用于任何要实现对象缓存的情况。

应用方式:把对象缓存移到自己的服务器上。

应用理由:用一个单独的层放置对象缓存的好处是,能更好地利用内存和CPU资源,并且能够独立于其他层对对象缓存进行扩展。

要点:在实现对象缓存时,把服务放在一个现有的层(如应用服务器)上是最简单的。在专用的层上实现对象缓存或把它移到对象专用的层上,可以得到更好的性能和可扩展性。

对象缓存包括数据库对象缓存(SQL查询结果集)或应用服务器对象缓存(如复杂的中间计算结果或用户推荐信息对象等)

G.从错误中吸取教训

二十七.积极地学习

目的:抓住每个机会学习。

适用情形:持续地从失误和成功中学习。

应用方式:观察用户或者使用A/B测试(还有多元测试)决定哪种方法可行。采用事后分析的方法,从生产环境发生的偶然事件和问题中学习。

应用理由:做事不衡量结果,或者发生了偶然事件却没有从中学到什么,都是浪费机会。而你的竞争对手则正在利用这些机会。

要点:要持续且积极地学习。学习最好,学习速度最快的公司,通常是发展最快,可扩展性最强。

二十八.不要依靠QA发现失误

目的:利用QA降低被交付产品的成本,提高编码生产力,识别质量变化动向,减少缺陷,但不要用QA提高质量。

适用情形:适用于雇用员工通过测试而不是通过编码来提高生产力的情况。总是通过QA从过去的失误中获取经验。

应用方式:当雇用一个QA人员得到的价值大于一个程序员工作的价值时,就应该雇用一个QA人员。

应用理由:可以减少成本,提高交付的总量和速度,减少重复出现的缺陷数量。

要点:QA并不能提高系统的质量,因为不能在系统中测试质量。如果使用正确,QA可以提高生产力,同时降低成本,最重要的是,在组织的高速增长期,QA可以保证缺陷增长的速度比组织发展的速度慢。

二十九.没有回退功能的设计是失败的设计

目的:要一直能回退代码。

适用情形:确保所有的版本都能够回退,在一个阶段或QA环境中,要实践回退功能。在生产环境中,当必须用它解决突发事件时,要使用回退功能。

应用方式:整理代码,制定几个简单的流程,确保能够回退自己的代码。

应用理由:如果你还没有经历过不能回退系统的痛苦,那么如果继续玩火,不停地迅速修复系统,迟早会遇到这种问题。

要点:不要用应用太复杂或者代码发布太频繁作为借口,拒不加入回退代码的功能。一个明智的飞行员,如果没有具备让飞机着陆的能力,就不会让飞机起飞。一个明智的程序员,如果不能让系统在紧急情况下回退代码,就不应该发布代码。

坚持几个简单的原则,所有团队都能进行回退

1.数据库修改只能是增量的

2.DDL和DML必须脚本化且测试过,且其中须包括回退脚本

3.对应用中的SQL查询进行约束(如select具体列而不是select * )

4.数据的语义修改,如票务表中有一列列放状态信号,有这些值:assigned, fixed, closed.在应用的新版本中如果没有发布处理新状态的代码,就不能添加第4个状态。

5.Wire On/Wire Off这相当于一段程序的可执行开关.

三十. 讨论失败并从中吸取教训

目的:利用每一次失败来学习,吸取重要的教训。

适用情形:无论何时都适用。

应用方式:采用事后分析方法,在故障较少的环境中推测故障。

应用理由:我们从失败中才能获得最深刻的教训,而不是从成功中。

要点:不要让任何失败浪费掉。从每次失败中学习,发现需要改正的技术,人员和流程上的问题。

1.关注故障,监控报告要发给每一个相关人员,并且要在每日例会这样的环境中频繁讨论平台的运维

2.拒绝简化解释:对一切都不要掉以轻心,不要以为故障是正常的,因为这个故障很可能是下一故障的早期信号。

3.关注运维:查看分钟级别的详细数据。

4.培训多技能员工,可考虑实行轮岗制

5. 尊重专家,危机事件中要把领导权交给处理该问题最专业的人。

H 数据库原则

三十一 注意代价高的关系

目的:注意数据模型中的关系。

适用情形:在设计数据库模型时,添加表和列时,或者编写查询时,要从长远角度考虑实体间的关系如何影响性和可扩展性的情形。

应用方式:在设计数据模型时,要考虑到将来的数据库分割和其他可能的数据需求。

应用理由:在实现了数据模型后,才发现它有问题,此时修复的成本很高,可能是设计阶段修复它的成本的100倍。

要点:事先考虑好,仔细策划数据模型。要采用范式,考虑将来可能如何分割数据库及应用可能有哪些需求。

三十二 使用类型正确的数据库锁

目的:要认识到使用了显式锁,并监控隐式锁。

适用情形:适用于任何在解决方案中采用关系数据库的情况。

应用方式:在审查代码时,要监控显式锁。监控数据库中的隐式锁,在必要时,将其调整为显式锁,以减少数据库的吞吐量。要选择能够灵活调整锁定类型和粒度的数据库和存储引擎。

应用理由:可以最大化环境中的数据库并发性和吞吐量。

要点:理解每种数据库锁的类型,利用它们最大化数据库的并发性和吞吐量。在发展过程中,改变锁的类型,可以更好地使用数据库,更好地分割模式和分布数据库。在选择数据库时,要确保它具有多种锁类型和多种锁定数据库的粒度,从而最大化并发性。

三十三 不要使用多阶段提交

目的:不要使用多阶段提交协议存储或处理事务。

适用情形:绝对不要使用多阶段提交协议。

应用方式:不要使用它。用Y轴或Z轴划分分割数据存储和处理系统。

应用理由:多阶段提交协议是一种阻断提议,在它完成之前,其他事务不能执行。

要点:不要将多阶段提交协议作为延长整体数据库生命的简单方式。它很可能降低扩展性,甚至更早地终止系统的寿命。

三十四 不要使用select for update

目的:在SELECT语句中声明游标时,不要使用FOR UPDATE从句。

适用情形:无论何时都适用。

应用方式:审查关于游标的代码,质疑每个SELECT FOR UPDATE语句。

应用理由:使用FOR UPDATE从句会锁定行,从而降低事务处理速度。

要点:游标是一种强大的结构,使用得当,能够使编程更快更容易,同时还能加速事务处理。但FOR UPDATE游标可能会长期锁定数据,降低事务处理速度。参考数据库文档,看是否需要使用FOR READ ONLY从句,最小化锁的数量。

三十五 不要选择所有数据

目的:不要在查询中使用SELECT *.

适用情形:无论何时都适用(或者说,绝对不要选择所有数据)。

应用方式:无论何时,都要在查询中声明要选择或插入的是哪几列数据。

应用理由:在查询中选择所有数据,当表结构发生变化时,容易发生中断,而且会传递不必要的数据。

要点:在选择或插件数据时,不要使用通配符。

I 容错设计与故障控制

三十六 采用隔离故障的“泳道"

目的:在设计中隔离故障点或者说实现泳道。

适用情形:适用于任何为扩展而划分数据库的情况。

应用方式:沿着Y轴或Z轴划分数据库和服务,不允许服务间同步通信和访问。

应用理由:提高了可用性和可扩展性,减少了识别和解决偶然事件的操作,同时减少了投产时间和成本。

要点:隔离故障的方法,包括减少故障隔离域之间的同步调用,限制异步调用,处理同步调用故障以及减少泳道间的服务和数据共享。

泳道间共享信息(如登录证书)可通过数据库副本复制或分式式对象缓存数据来达到目的。 一台物理服务器只服务于同一个泳道的不同虚拟服务器(不同的泳道可以理解为不同集群,不同分片或不同机房)

我们依赖四条定义和设计泳道的原则实现故障隔离。

1.任何泳道之间什么都不共享

2.泳道间不存在发生同步调用

3.限制泳道间的异步调用

4.无论何时想跨泳道进行异步通信时,都需要具备“不在乎”该事务的能力,某些时候事务可以超时且不用管它。在任何时候我们都应该实现一个逻辑开关手动,自动或都两者兼有地关闭这种通信。

三十七 绝对不要信任单点故障(SPOF)

目的:绝对不要实现且一定要减少单点故障。

适用情形:适用于审查架构或进行新设计。

应用方式:在架构图上找出单点实例。尽量采用主动/主动配置。

应用理由:通过多个实例最大化可用性。

要点:尽量采用主动/主动配置,不要采用主动/被动解决方案。利用负载均衡器跨服务实例的流量。对于单例模式,使用主动/被动配置的控制服务。

单个web服务器,单个网络设备,单个数据库都是单点故障。

几个快速修复单点故障的方法是:

1.主动/被动配置,如Master/Slave, 主从配置等。

2.负载均衡,如Nginx, F5

3. 记住一切都会出故障

三十八 避免系统串联

目的:减少以串联方式连接的组件数。

适用情形:无论何时要添加组件都适用。

应用方式:删除不必要的组件或添加它们的多个版本,将影响最小化。

应用理由:串联组件会使故障成倍增加。

要点:避免给系统添加串联组件。如果一定需要,则添加该组件的多个版本,这样一个版本出故障了,其他的版本还可以代替它。

三十九 确保能启用/禁用功能

目的:创建一种结构,以便能够启用和禁用产品或能。

适用情形:适用于有风险的或共享的服务,这种服务可能在响应变慢或不可用起站点故障。

应用方式:开发共享库,允许自动地或根据要求启用和禁用服务。

应用理由:控制事务故障,即使因偶然事件和连带问题需要恢复时,业务仍能保持运行。

要点:只要实现成本比发生故障的风险和发生故障的成本低,就应该实现Wire on/Wire off框架。开发共享库的工作可以在将来的实现中重用,成本较低。

如果采用程序自动决定是否发生故障方法则容易误报故障;如人工干预方式给服务器发一个命令让它停止有故障的服务。比自动标记停用慢且可能由于响应慢或出故障造成TCP端口全部被占用,此时命令可能会失效;采用配置文件形式可能需重启服务器才能生效,且可能因为轮询文件导致响应慢;如果数据库中增加一个控制列来启用/禁用功能,要求那些控制表(列)具有高可用性,且需在每个泳道放置一个副本以确保不会跨泳道访问它们,如果基于事务执行,成本较高;可以开发一个可重用的Wire On/Wire Off共享代码库。

J 避免或分发状态

四十 努力实现无状态(SNA)

目的:设计和实现无状态系统。

适用情形:适用于设计新系统或重新设计已有系统时。

应用方式:尽可能选择无状态实现。如果出于业务需求,合理地实现了状态,请参阅原则41和原则42.

应用理由:实现状态会限制可扩展性,增加成本。

要点:在任何系统中,都要抵制对状态的需要。使用业务指标和多元(或A/B)测试,判断应用中的状态是否真的实现了用户预期的行为和业务价值。

四十一 尽可能在浏览器端维护会话

目的:尽量完全避免会话数据,必要时,可以考虑把数据放在用户的浏览器中。

适用情形:适用于任何需要会话数据来实现最佳用户体验的情形。

应用方式:采用Cookie在用户的浏览器中存放会话数据。

应用理由:把会话数据存放在用户的浏览器中,可以使服务器池中的任何一个WEB服务器都能为该用户的请求提供服务,而且你的系统也不必再为它提供存储空间了。

要点:用Cookie存放会话数据是种常见的方法,而且具有易于扩展的优点,但也有一些缺点。最关键的缺点就是未加密的Cookie可以被轻易捕获,用于登录用户的账号。

缺点是每一个请求都往返地移动cookie数据,这样成本很高,尤其是数据量逐渐变大的情况下成本更高。另一个严重坏处是由firefox插件FireSheep暴露出恶意登录别人的账号,这种攻击叫“会话劫持”。怎么避免会话劫持?:利用https加密;至少利用两个cookie, 一个用于授权,在每个http页面上使用js调用通过https请求,如括号内所示的代码(<script type="text/javascript" src=https://verify.aicai.com/authenticate.jsp></script>)。这样就会使用大部分数据(内容,css, js等)都通过未加密的http协议传送,而只有授权cookie才通过https传送。另外必须严格控制cookie的大小,大量的会话数据会降低页面载入的性能以及系统中的web服务器的性能。

四十二 利用分布式缓存存放状状态

目的:在系统中存储会话数据时,使用分布式缓存。

适用情形:适用于任何需要存储会话数据但又不能将其存放在用户浏览器中的情况。

应用方式:小心一些常见的错误,如会话管理系统要求关联用户和WEB服务器。

应用理由:认真考虑如何存储会话数据可以确保系统能够持续扩展。

要点:许多Web服务器或语言都提供了简单的基于服务器的会话管理方法,但这些方法通常有一些问题,例如把用户关联到了特定的服务器。实现分布式缓存,就可以在系统中存放会话数据,使系统能够持续扩展。

利用memcached-session-manager框架或采用自“混合缓存和数据库持久会话数据”的方案,由数据库提供持久性,由缓存提供高性价比的扩展性,这很适合需要持久性又想成本低的情况。

K 异步通信和消息总线

四十三 尽可能使用异步通信

目的:尽可能使用异步通信,而不是同步通信。

适用情形:适用于服务和各个层之间的所有调用。

应用方式:使用程序设计语言专有的调用,确保发出了请求,且没有在等待。

应用理由:同步调用会使用整个程序执行停止来等待一个响应,从而把所有的服务和各个层维系在一起,造成级联性的故障。

要点:使用异步通信技术可以确保每个服务和层是独立的,这样系统的可扩展程度比所有部件都耦合在一起的系统大得多。

四十四 确保消息总线能够扩展

目的:消息总线会像其他物理或逻辑系统一样,由于需求过大发生故障。它们也需要扩展。

适用情形:适用于任何以消息总线作为架构一部分的情况。

应用方式:采用AKF扩展立方中的Y轴和Z轴扩展。

应用理由:确保消息总线能够根据需求进行扩展。

要点:把消息总线作为系统的关键组件对待。在需求过大之前,用Y轴或Z轴方法对它进行扩展。

四十五 避免让消息总线过度拥挤

目的:让总线流量仅限于价值高于处理成本的数据。

适用情形:适用于任何消息总线。

应用方式:价值和成本是调整消息流量的标准。要减少低价值高成本的流量。对低价值/低成本和高价值/高成本的流量进行采样,以减少成本。

应用理由:消息流量并非“免费的”,对系统是有成本需求的。

要点:不要所有东西都发布。对流量进行采样可以在成本和价值之间取得平衡。

L 其它原则

四十六 慎用第3方解决方案扩展

目的:自己扩展你的系统,不要依靠供应商的解决方案实现扩展。

适用情形:适用于考虑是否使用供应商提供的新功能或产品时。

应用方式:根据本书提到的原则,了解如何扩展,如何用最简单的方式使用供应商提供的产品和服务。

应用理由:遵循该原则的原则有三点:主宰自己的命运,保持架构简单,减少在所有权方面的成本。

要点:不要依赖供应的产品,服务或功能来扩展系统。保持架构简单,把命运掌控在自己手中,自己控制成本。而如果使用供应商的专有扩展方案,可能就做不到这三点了。

如果你使用一个供应商的专用集群服务,就不能切换到另一个供应商的解决方案

四十七 清除,归档和成本合理的存储

目的:让存储成本与数据价值相匹配,删除那些价值比存储成本低的数据。

适用情形:适用于设计讨论阶段,对于数据及其存储基础设施的考量,也适用于相应数据的整个生命周期。

应用方式:分析数据的近度,频度和值度,确定数据的价值,使存储成本与数据价值相匹配。

应用理由:并非所有的数据都具有相同的价值,事实上,数据的价值经常改变。那么我们为什么还要采用单一的存储方案而让所有数据的存储成本都相同呢。

要点:了解和计算数据的价值非常重要,要使存储成本与数据价值相匹配。不要为没有为股东带来任何回报的数据付钱。

采用市场营销概念RFM, 即分析近度(Recency 最近访问时间),值度(frequency价值),频度(monetization)。我们可把这个概念扩展到我们的存储需求上。如高价值总是访问的数据应条带化/镜像式SSD存储。低价值从不访问的数据或文件应该清除掉。其它的情况可考虑放在云,mfs,硬盘,缓存里。

四十八 删除事务处理中的商业智能

目的:把业务系统和产品系统分开,删除数据库系统中的产品智能。

适用情形:适用于考虑公司的内部需求以及在产品内或产品间传输数据的情形。

应用方式:从数据库中删除存储过程,把它们放在应用逻辑中。不要在企业系统和产品系充之间进行同步调用。

应用理由:把应用逻辑放在数据库中成本很高且难以扩展。把企业系统和产品系统绑定在一起,成本也很高,不仅难以扩展,可用性也令人担忧。

要点:由于许可和单一系统的特性,数据库和内部企业系统的扩展成本会很高。因此,我们希望它们能专注于执行特定的任务。就数据库而言,我们希望它们能够专注于事务而不是产品智能。就后台办公系统(商业智能)而言,我们不希望产品与系统的扩展能力联系在一起。对于业务系统的数据,采用异步传输模式。

四十九 设计能监控的应用

目的:在设计阶段就考虑需要如何监控应用。

适用情形:适用于任何给代码库添加或修改模块的时候。

应用方式:在系统中添加钩子,记录交易时间。

应用理由:了解应用如何执行,有助于在发生问题时回答许多问题。

要点:把应用必须能被监控作为一条架构设计原则。此外,考虑一下你的全局监控策略,确保你能第一个答出下面的问题:“发生问题了吗?“ “哪里发生问题了?“ ”是什么问题?“

监控工具如 cacti, ntop, nagios, zabbix等,可检查网络流量,服务器的cpu和内存用量,然后安装警报功能;还需从业务指标角度来监控系统(用户角度监控系统),如监控购物车的数量和每个时间段的购买总值。

最后一个监控能回答的问题是:“会发生问题吗”,这类监控需结合业务监控数据,应用监控数据和硬件监控数据,可使用图形统计工具或神经网络或贝叶斯分类这类的机器学习算法来分析数据,以便预测是否会发生问题,最后一步必杀技:监控到预测将要发生问题时,系统能自我修复(自动故障切换监控)

五十 要能胜任

目的:要能胜任,或者为架构中的每个组件购买能胜任的解决方案。

适用情形:适用于任何因特网服务或电子商务解决方案

应用方式:为基础设施中的每个组件,标识出团队对它应付的责任以及应该具备的能力水平。

应用理由:对用户来说,每个问题都是你的问题。你不能责备供应商。你提供的是服务,不是软件。

要点:不要把能否胜任与自己开发还是外部购买或者与核心决策还是上下文决策的问题相混淆。你可以购买解决方案,但仍然要能胜任去部署和维护它们。事实上,用户也要求你如此做。

M 原则回顾和优先级划分
评估扩展项目和主动权的风险-收益模型

风险=发生问题的可能性*影响(%)*(停机时间*数据损失(%) * 对响应时间的影响)

影响(%) = 受影响的用户(%) + 受影响的功能(%)

如果有一天损失了预计收益的10%,则可用性只有90%。

R-C = P。R即风险减少-C即成本(开发人员成本),P即优先级。

P分H(高), M(中), L(低)三级。P为0即为M级。总之,利用越低成本将风险降至最小的项目或解决方案是我们的首选方案,这种可扩展方案的优先级最高。即收益-优先级为“非常高-1”。运维人员可以有“可用性可扩展性”的KPI以及SLA(服务水平协议)的指标。

参考:

1.《高扩展性网站的50条原则》

猜你喜欢

转载自huyumin.iteye.com/blog/1867700
今日推荐