关于复杂度来源,前面的专栏已经讲了高性能、高可用和可扩展性,今天我来聊聊复杂度另外三个来源低成本、安全和规模。
低成本
当我们的架构方案只涉及几台或者十几台服务器时,一般情况下成本并不是我们重点关注的目标,但如果架构方案涉及几百上千甚至上万台服务器,成本就会变成一个非常重要的架构设计考虑点。例如,A方案需要10000台机器,B方案只需要8000台机器,单从比例来看,也就节省了20%的成本,但从数量来看,B方案能节省2000台机器,1台机器成本预算每年大约2万元,这样一年下来就能节省4000万元,4000万元成本不是小数目,给100人的团队发奖金每人可以发40万元了,这可是算得上天价奖金了。通过一个架构方案的设计,就能轻松节约几千万元,不但展现了技术的强大力量,也带来了可观的收益,对于技术人员来说,最有满足感的事情莫过于如此了。
当我们设计“高性能”“高可用”的架构时,通用的手段都是增加更多服务器来满足“高性能”和“高可用”的要求;而低成本正好与此相反,我们需要减少服务器的数量才能达成低成本的目标。因此,低成本本质上是与高性能和高可用冲突的,所以低成本很多时候不会是架构设计的首要目标,而是架构设计的附加约束。也就是说,我们首先设定一个成本目标,当我们根据高性能、高可用的要求设计出方案时,评估一下方案是否能满足成本目标,如果不行,就需要重新设计架构;如果无论如何都无法设计出满足成本要求的方案,那就只能找老板调整成本目标了。
低成本给架构设计带来的主要复杂度体现在,往往只有“创新”才能达到低成本目标。这里的“创新”既包括开创一个全新的技术领域(这个要求对绝大部分公司太高),也包括引入新技术,如果没有找到能够解决自己问题的新技术,那么就真的需要自己创造新技术了。
类似的新技术例子很多,我来举几个。
NoSQL(Memcache、Redis等)的出现是为了解决关系型数据库无法应对高并发访问带来的访问压力。
全文搜索引擎(Sphinx、Elasticsearch、Solr)的出现是为了解决关系型数据库like搜索的低效的问题。
Hadoop的出现是为了解决传统文件系统无法应对海量数据存储和计算的问题。
我再来举几个业界类似的例子。
Facebook为了解决PHP的低效问题,刚开始的解决方案是HipHop PHP,可以将PHP语言翻译为C++语言执行,后来改为HHVM,将PHP翻译为字节码然后由虚拟机执行,和Java的JVM类似。
新浪微博将传统的Redis/MC + MySQL方式,扩展为Redis/MC + SSD Cache + MySQL方式,SSD Cache作为L2缓存使用,既解决了MC/Redis成本过高,容量小的问题,也解决了穿透DB带来的数据库访问压力(来源:http://www.infoq.com/cn/articles/weibo-platform-archieture )。
Linkedin为了处理每天5千亿的事件,开发了高效的Kafka消息系统。
其他类似将Ruby on Rails改为Java、Lua + redis改为Go语言实现的例子还有很多。
无论是引入新技术,还是自己创造新技术,都是一件复杂的事情。引入新技术的主要复杂度在于需要去熟悉新技术,并且将新技术与已有技术结合起来;创造新技术的主要复杂度在于需要自己去创造全新的理念和技术,并且新技术跟旧技术相比,需要有质的飞跃。
相比来说,创造新技术复杂度更高,因此一般中小公司基本都是靠引入新技术来达到低成本的目标;而大公司更有可能自己去创造新的技术来达到低成本的目标,因为大公司才有足够的资源、技术和时间去创造新技术。
安全
安全本身是一个庞大而又复杂的技术领域,并且一旦出问题,对业务和企业形象影响非常大。例如:
2016年雅虎爆出史上最大规模信息泄露事件,逾5亿用户资料在2014年被窃取。
2016年10月美国遭史上最大规模DDoS攻击,东海岸网站集体瘫痪。
2013年10月,为全国4500多家酒店提供网络服务的浙江慧达驿站网络有限公司,因安全漏洞问题,致2千万条入住酒店的客户信息泄露,由此导致很多敲诈、家庭破裂的后续事件。
正因为经常能够看到或者听到各类安全事件,所以大部分技术人员和架构师,对安全这部分会多一些了解和考虑。
从技术的角度来讲,安全可以分为两类:一类是功能上的安全,一类是架构上的安全。
1.功能安全
例如,常见的XSS攻击、CSRF攻击、SQL注入、Windows漏洞、密码破解等,本质上是因为系统实现有漏洞,黑客有了可乘之机。黑客会利用各种漏洞潜入系统,这种行为就像小偷一样,黑客和小偷的手法都是利用系统或家中不完善的地方潜入,并进行破坏或者盗取。因此形象地说,功能安全其实就是“防小偷”。
从实现的角度来看,功能安全更多地是和具体的编码相关,与架构关系不大。现在很多开发框架都内嵌了常见的安全功能,能够大大减少安全相关功能的重复开发,但框架只能预防常见的安全漏洞和风险(常见的XSS攻击、CSRF攻击、SQL注入等),无法预知新的安全问题,而且框架本身很多时候也存在漏洞(例如,流行的Apache Struts2就多次爆出了调用远程代码执行的高危漏洞,给整个互联网都造成了一定的恐慌)。所以功能安全是一个逐步完善的过程,而且往往都是在问题出现后才能有针对性的提出解决方案,我们永远无法预测系统下一个漏洞在哪里,也不敢说自己的系统肯定没有任何问题。换句话讲,功能安全其实也是一个“攻”与“防”的矛盾,只能在这种攻防大战中逐步完善,不可能在系统架构设计的时候一劳永逸地解决。
2.架构安全
如果说功能安全是“防小偷”,那么架构安全就是“防强盗”。强盗会直接用大锤将门砸开,或者用炸药将围墙炸倒;小偷是偷东西,而强盗很多时候就是故意搞破坏,对系统的影响也大得多。因此架构设计时需要特别关注架构安全,尤其是互联网时代,理论上来说系统部署在互联网上时,全球任何地方都可以发起攻击。
传统的架构安全主要依靠防火墙,防火墙最基本的功能就是隔离网络,通过将网络划分成不同的区域,制定出不同区域之间的访问控制策略来控制不同信任程度区域间传送的数据流。例如,下图是一个典型的银行系统的安全架构。
从图中你可以看到,整个系统根据不同的分区部署了多个防火墙来保证系统的安全。
防火墙的功能虽然强大,但性能一般,所以在传统的银行和企业应用领域应用较多。但在互联网领域,防火墙的应用场景并不多。因为互联网的业务具有海量用户访问和高并发的特点,防火墙的性能不足以支撑;尤其是互联网领域的DDoS攻击,轻则几GB,重则几十GB。2016年知名安全研究人员布莱恩·克莱布斯(Brian Krebs)的安全博客网站遭遇DDoS攻击,攻击带宽达665Gbps,是目前在网络犯罪领域已知的最大的拒绝服务攻击。这种规模的攻击,如果用防火墙来防,则需要部署大量的防火墙,成本会很高。例如,中高端一些的防火墙价格10万元,每秒能抗住大约25GB流量,那么应对这种攻击就需要将近30台防火墙,成本将近300万元,这还不包括维护成本,而这些防火墙设备在没有发生攻击的时候又没有什么作用。也就是说,如果花费几百万元来买这么一套设备,有可能几年都发挥不了任何作用。
就算是公司对钱不在乎,一般也不会堆防火墙来防DDoS攻击,因为DDoS攻击最大的影响是大量消耗机房的出口总带宽。不管防火墙处理能力有多强,当出口带宽被耗尽时,整个业务在用户看来就是不可用的,因为用户的正常请求已经无法到达系统了。防火墙能够保证内部系统不受冲击,但用户也是进不来的。对于用户来说,业务都已经受到影响了,至于是因为用户自己进不去,还是因为系统出故障,用户其实根本不会关心。
基于上述原因,互联网系统的架构安全目前并没有太好的设计手段来实现,更多地是依靠运营商或者云服务商强大的带宽和流量清洗的能力,较少自己来设计和实现。
规模
很多企业级的系统,既没有高性能要求,也没有双中心高可用要求,也不需要什么扩展性,但往往我们一说到这样的系统,很多人都会脱口而出:这个系统好复杂!为什么这样说呢?关键就在于这样的系统往往功能特别多,逻辑分支特别多。特别是有的系统,发展时间比较长,不断地往上面叠加功能,后来的人由于不熟悉整个发展历史,可能连很多功能的应用场景都不清楚,或者细节根本无法掌握,面对的就是一个黑盒系统,看不懂、改不动、不敢改、修不了,复杂度自然就感觉很高了。
规模带来复杂度的主要原因就是“量变引起质变”,当数量超过一定的阈值后,复杂度会发生质的变化。常见的规模带来的复杂度有:
1.功能越来越多,导致系统复杂度指数级上升
例如,某个系统开始只有3大功能,后来不断增加到8大功能,虽然还是同一个系统,但复杂度已经相差很大了,具体相差多大呢?
我以一个简单的抽象模型来计算一下,假设系统间的功能都是两两相关的,系统的复杂度=功能数量+功能之间的连接数量,通过计算我们可以看出:
3个功能的系统复杂度= 3 + 3 = 6
8个功能的系统复杂度= 8 + 28 = 36
可以看出,具备8个功能的系统的复杂度不是比具备3个功能的系统的复杂度多5,而是多了30,基本是指数级增长的,主要原因在于随着系统功能数量增多,功能之间的连接呈指数级增长。下图形象地展示了功能数量的增多带来了复杂度。

通过肉眼就可以很直观地看出,具备8个功能的系统复杂度要高得多。
2.数据越来越多,系统复杂度发生质变
与功能类似,系统数据越来越多时,也会由量变带来质变,最近几年火热的“大数据”就是在这种背景下诞生的。大数据单独成为了一个热门的技术领域,主要原因就是数据太多以后,传统的数据收集、加工、存储、分析的手段和工具已经无法适应,必须应用新的技术才能解决。目前的大数据理论基础是Google发表的三篇大数据相关论文,其中Google File System是大数据文件存储的技术理论,Google Bigtable是列式数据存储的技术理论,Google MapReduce是大数据运算的技术理论,这三篇技术论文各自开创了一个新的技术领域。
即使我们的数据没有达到大数据规模,数据的增长也可能给系统带来复杂性。最典型的例子莫过于使用关系数据库存储数据,我以MySQL为例,MySQL单表的数据因不同的业务和应用场景会有不同的最优值,但不管怎样都肯定是有一定的限度的,一般推荐在5000万行左右。如果因为业务的发展,单表数据达到了10亿行,就会产生很多问题,例如:
添加索引会很慢,可能需要几个小时,这几个小时内数据库表是无法插入数据的,相当于业务停机了。
修改表结构和添加索引存在类似的问题,耗时可能会很长。
即使有索引,索引的性能也可能会很低,因为数据量太大。
数据库备份耗时很长。
……
因此,当MySQL单表数据量太大时,我们必须考虑将单表拆分为多表,这个拆分过程也会引入更多复杂性,例如:
- 拆表的规则是什么?
以用户表为例:是按照用户id拆分表,还是按照用户注册时间拆表?
- 拆完表后查询如何处理?
以用户表为例:假设按照用户id拆表,当业务需要查询学历为“本科”以上的用户时,要去很多表查询才能得到最终结果,怎么保证性能?
还有很多类似的问题这里不一一展开,后面的专栏还会讨论。
小结
今天我为你分析了低成本给架构设计带来的主要复杂度体现在引入新技术或创造新技术,讨论了从功能安全和架构安全引入的复杂度,以及规模带来复杂度的主要原因是“量变引起质变”,希望对你有所帮助。
这就是今天的全部内容,留一道思考题给你吧。学习了6大复杂度来源后,结合你所在的业务,分析一下主要的复杂度是这其中的哪些部分?是否还有其他复杂度原因?
欢迎你把答案写到留言区,和我一起讨论。相信经过深度思考的回答,也会让你对知识的理解更加深刻。(编辑乱入:精彩的留言有机会获得丰厚福利哦!)
精选留言
2018-05-12 13:33:12
低成本
What:低成本是架构设计中需要考虑一个约束条件,但不会是首要目标。低成本本质上是与高性能和高可用冲突的,当无法设计出满足成本要求的方案,就只能协调并调整成本目标。
How:一般通过“创新”达到低成本的目标。(1)引入新技术。主要复杂度在于需要去熟悉新技术,并且将新技术与已有技术结合;一般中小型公司基本采用该方式达到目标。(2)开创一个全新技术领域。主要复杂度在于需要去创造全新的理念和技术,并且与旧技术相比,需要有质的飞跃,复杂度更高;一般大公司拥有更多的资源、技术实力会采用该方式来达到低成本的目标。
安全
What:安全是一个庞大而又复杂的技术领域,一旦出问题,对业务和企业形象影响非常大。从技术的角度来讲,包括(1)功能安全-“防小偷”,减少系统潜在的缺陷,阻止黑客破坏行为;(2)架构安全—“防强盗”,保护系统不受恶意访问和攻击,保护系统的重要数据不被窃取。由于是蓄意破坏系统,因此对影响也大得多。架构设计时需要特别关注架构安全。
How:(1)功能安全。是一个逐步完善的过程,而且往往都是在问题出现后才能有针对性的提出解决方案,与编码实现有关。(2)架构安全。传统企业主要通过防火墙实现不同区域的访问控制,功能强大、性能一般,但是成本更高。互联网企业更多地是依靠运营商或者云服务商强大的带宽和流量清洗的能力,较少自己来设计和实现。
规模
What:规模带来复杂度的主要原因就是“量变引起质变”,当数量超过一定的阈值后,复杂度会发生质的变化。随着业务的发展,规模带来的常见复杂度有(1)业务功能越来越多,调用逻辑越来越复杂;(2)数据容量、类型、关联关系越来越多。
How:规模问题需要与高性能、高可用、高扩展、高伸缩性统一考虑。常采用“分而治之,各个击破”的方法策略。
是否还有其他复杂度原因?- 可伸缩性
当前大型互联网网站需要面对大量用户高并发访问、存储更多数据、处理更高频次的用户交互。网站系统一般通过多种分布式技术将多台服务器组成集群对外提供服务。伸缩性一般是系统可以根据需求和成本调整自身处理能力的一种能力。伸缩性常意味着系统可以通过低成本并能够快速改变自身的处理能力以满足更多用户访问、处理更多数据而不会对用户体验造成任何影响。
伸缩性度量指标包括(1)处理更高并发;(2)处理更多数据;(3)处理更高频次的用户交互。
其复杂度体现在(1)伸——增强系统在上述三个方面的处理能力;(2)缩——缩减系统处理能力;(3)上述伸缩过程还必须相对低成本和快速。
2018-05-15 02:10:02
2018-05-29 10:36:11
2018-05-14 21:57:25
2018-05-23 19:08:41
2019-08-03 09:51:46
软件领域的成本和硬件领域的成本有很大的不同。在硬件领域随着规模的增大成本会降低,基本上是一次性的技术成本,因为根据摩尔定律,每一美元买到的电脑性能将每隔18~24个月翻一倍。软件领域为什么会不一样呢?归根到底是软件销售模式发生了变化,以前软件的销售模式和硬件的销售模式是一致的,开发出了一个软件产品到处复制销售,每卖出一份软件产品和卖出一块CPU是等同的,卖的多成本就可以持续下降——薄利多销。现在软件的销售模式发生了很大的变化,是账号+充值+移动消费。用户侧的开销很小,只需要一个浏览器就可以了,软件能力基本在服务端,这就导致了服务端规模上升成本就上升的尴尬境地,要想降低成本必须寻找新的技术和方法,而新的方法和技术需要创新,创新后还要引入到现有的生产环节和现有的技术结合,复杂度可想而知,成本的投入是持续的。
云化架构下安全带来的复杂度主要体现在如下两方面:一是物理部署架构的变化,同一个系统的不同子系统部署在不同的安全区域,不同的安全区域需要不同的安全策略和不同的安全技术。另一个是不同的安全区域之间的通信需要选择或研发新的协议。原本简洁的网络通讯变得复杂和难以理解。
2018-05-20 13:10:12
2021-01-15 06:34:53
直接被机房下架。
2018-05-13 11:52:34
2018-10-24 18:08:15
2018-05-12 08:43:22
2018-05-18 08:46:43
老师能否讲课向两个人聊天一样,让人听着不那么累!
2018-05-13 01:25:29
比如脸谱转成java,就少了很多事情。选择对一个技术可以减少很多成本。
低成本与高性能没有直接冲突,比如三十台服务才能支持一万五Tps,但是设计,架构,编码优化只要五台就可以到一万五。
dubbo,打算实现无阻塞,那性能提高一倍,哪得少多少服务。
应该说高性能是降低成本的手段,通过增加服务提高所谓的Tps,那是增加性能。而是高性能。
低成本的确与高可用直接犯冲,优化空间小。
短信系统并发一千五,需要八核服务,要高可用就得两台八核的。解决是两台四核,每台七百五,如果一台挂了,另外一台可用,但是容量少了而已,服务有限流,压力都到一台也没关系。
短信以前就是一百的Tps,一千五十台,技术技术优化就两台。
关于安全,这只会使用大众方案,或者一些微微深入的,这点实在没啥说的。我安全原则就是严,细。
规模,这份问题与低成本其实差不多。
应该分业务规模与性能规模。
深入分析业务,可以解决不少问题。
比如十个模块,只有两三个是核心的,一些并发低,数据小,热点数据缓存把多个模块合在一起,减少复杂度。
多个系统有很多类似的功能或者模块,可以整合在一起座位基础系统。等等
技术,架构,设计,编码是解决低成本,规模,安全的最基础,最重要的手段。
2018-05-12 11:07:56
简述:访问量在升,业务在不断变化
难点:
1. 业务方面,功能无法正常迭代(小公司),旧功能可能重构,新功能有时需要兼容旧功能,技术尚未实现,复杂度就显而易见
2. 技术方面,单体架构,面向过程编程,各个模块之间依赖严重(典型的例子就是一堆left join),重构功能时代码基本全部重写。
3. 部分公用模块(无源码),对修改关闭,对扩展也关闭,导致一些需求无法满足。
我的解决方案:
项目全部重构代价太大,那姑且以当前架构入手:
1. 拒绝不合理需求,拒绝对现有功能的大修改
2. 新功能开发,严格控制模块依赖,做好逻辑分层
3. 针对单个的功能,逐步进行逻辑分离,最后逐步实现服务分离,逐步向分布式发展
请老师批评指正,谢谢
2018-05-15 08:05:07
2020-07-09 09:01:48
个人理解,6个维度是考虑问题的角度,做出分析,但最终还是要将架构扩展后的风险控制下来。从这个意义上讲,需求的理解是核心,离开需求单纯说架构没太大的意义。合适最重要
2018-11-01 10:20:09
从这个角度出发,是不是架构设计之初,先要分业务架构设计和软件架构设计两步走?
2018-05-14 08:09:11
应该是乘法吧?
2022-06-01 17:49:48
2020-09-03 12:05:18
我以前面对的系统可能勉强可以算的上是中等规模,功能比较多,数据量中等,应该还没有到“量变引起质变”的时候,但是应对起来似乎也比较勉强。
顺便回答思考题,这个系统的复杂度主要来源在于高可靠,一般是要求 24 × 7 不停机的,但是实际上估计达不到 4 个 9 的可靠性。
看到留言里面提到了“可伸缩性”,如果是租用数据中心的存储和计算资源,那么可伸缩性可以省钱,是有意义的;如果是自建系统,那么“可伸”类似于“可扩展”,“可缩”的意义就不大了,很难在自建环境中调配使用。