从0开始学架构
李运华
资深技术专家
立即订阅
38968 人已学习
课程目录
已完结 59 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 照着做,你也能成为架构师!
免费
基础架构 (13讲)
01 | 架构到底是指什么?
02 | 架构设计的历史背景
03 | 架构设计的目的
04 | 复杂度来源:高性能
05 | 复杂度来源:高可用
06 | 复杂度来源:可扩展性
07 | 复杂度来源:低成本、安全、规模
08 | 架构设计三原则
09 | 架构设计原则案例
10 | 架构设计流程:识别复杂度
11 | 架构设计流程:设计备选方案
12 | 架构设计流程:评估和选择备选方案
13 | 架构设计流程:详细方案设计
高性能架构模式 (8讲)
14 | 高性能数据库集群:读写分离
15 | 高性能数据库集群:分库分表
16 | 高性能NoSQL
17 | 高性能缓存架构
18 | 单服务器高性能模式:PPC与TPC
19 | 单服务器高性能模式:Reactor与Proactor
20 | 高性能负载均衡:分类及架构
21 | 高性能负载均衡:算法
高可用架构模式 (10讲)
22 | 想成为架构师,你必须知道CAP理论
23 | 想成为架构师,你必须掌握的CAP细节
24 | FMEA方法,排除架构可用性隐患的利器
25 | 高可用存储架构:双机架构
26 | 高可用存储架构:集群和分区
27 | 如何设计计算高可用架构?
28 | 业务高可用的保障:异地多活架构
29 | 异地多活设计4大技巧
30 | 异地多活设计4步走
31 | 如何应对接口级的故障?
可扩展架构模式 (6讲)
32 | 可扩展架构的基本思想和模式
33 | 传统的可扩展架构模式:分层架构和SOA
34 | 深入理解微服务架构:银弹 or 焦油坑?
35 | 微服务架构最佳实践 - 方法篇
36 | 微服务架构最佳实践 - 基础设施篇
37 | 微内核架构详解
架构实战 (13讲)
38 | 架构师应该如何判断技术演进的方向?
39 | 互联网技术演进的模式
40 | 互联网架构模板:“存储层”技术
41 | 互联网架构模板:“开发层”和“服务层”技术
42 | 互联网架构模板:“网络层”技术
43 | 互联网架构模板:“用户层”和“业务层”技术
44 | 互联网架构模板:“平台”技术
45 | 架构重构内功心法第一式:有的放矢
46 | 架构重构内功心法第二式:合纵连横
47 | 架构重构内功心法第三式:运筹帷幄
48 | 再谈开源项目:如何选择、使用以及二次开发?
49 | 谈谈App架构的演进
50 | 架构实战:架构设计文档模板
特别放送 (7讲)
架构专栏特别放送 | “华仔,放学别走!”第1期
架构专栏特别放送 | “华仔,放学别走!” 第2期
如何高效地学习开源项目 | “华仔,放学别走!” 第3期
架构师成长之路 | “华仔,放学别走!” 第4期
架构师必读书单 | “华仔,放学别走!” 第5期
新书首发 | 《从零开始学架构》
致「从0开始学架构」专栏订阅用户
结束语 (1讲)
结束语 | 坚持,成就你的技术梦想
从0开始学架构
登录|注册

04 | 复杂度来源:高性能

李运华 2018-05-05
周四,我为你讲了架构设计的主要目的是为了解决软件系统复杂度带来的问题。那么从今天开始,我将为你深入分析复杂度的 6 个来源,先来聊聊复杂度的来源之一高性能
对性能孜孜不倦的追求是整个人类技术不断发展的根本驱动力。例如计算机,从电子管计算机到晶体管计算机再到集成电路计算机,运算性能从每秒几次提升到每秒几亿次。但伴随性能越来越高,相应的方法和系统复杂度也是越来越高。现代的计算机 CPU 集成了几亿颗晶体管,逻辑复杂度和制造复杂度相比最初的晶体管计算机,根本不可同日而语。
软件系统也存在同样的现象。最近几十年软件系统性能飞速发展,从最初的计算机只能进行简单的科学计算,到现在 Google 能够支撑每秒几万次的搜索。与此同时,软件系统规模也从单台计算机扩展到上万台计算机;从最初的单用户单工的字符界面 Dos 操作系统,到现在的多用户多工的 Windows 10 图形操作系统。
当然,技术发展带来了性能上的提升,不一定带来复杂度的提升。例如,硬件存储从纸带→磁带→磁盘→SSD,并没有显著带来系统复杂度的增加。因为新技术会逐步淘汰旧技术,这种情况下我们直接用新技术即可,不用担心系统复杂度会随之提升。只有那些并不是用来取代旧技术,而是开辟了一个全新领域的技术,才会给软件系统带来复杂度,因为软件系统在设计的时候就需要在这些技术之间进行判断选择或者组合。就像汽车的发明无法取代火车,飞机的出现也并不能完全取代火车,所以我们在出行的时候,需要考虑选择汽车、火车还是飞机,这个选择的过程就比较复杂了,要考虑价格、时间、速度、舒适度等各种因素。
软件系统中高性能带来的复杂度主要体现在两方面,一方面是单台计算机内部为了高性能带来的复杂度;另一方面是多台计算机集群为了高性能带来的复杂度

单机复杂度

计算机内部复杂度最关键的地方就是操作系统。计算机性能的发展本质上是由硬件发展驱动的,尤其是 CPU 的性能发展。著名的“摩尔定律”表明了 CPU 的处理能力每隔 18 个月就翻一番;而将硬件性能充分发挥出来的关键就是操作系统,所以操作系统本身其实也是跟随硬件的发展而发展的,操作系统是软件系统的运行环境,操作系统的复杂度直接决定了软件系统的复杂度。
操作系统和性能最相关的就是进程线程。最早的计算机其实是没有操作系统的,只有输入、计算和输出功能,用户输入一个指令,计算机完成操作,大部分时候计算机都在等待用户输入指令,这样的处理性能很显然是很低效的,因为人的输入速度是远远比不上计算机的运算速度的。
为了解决手工操作带来的低效,批处理操作系统应运而生。批处理简单来说就是先把要执行的指令预先写下来(写到纸带、磁带、磁盘等),形成一个指令清单,这个指令清单就是我们常说的“任务”,然后将任务交给计算机去执行,批处理操作系统负责读取“任务”中的指令清单并进行处理,计算机执行的过程中无须等待人工手工操作,这样性能就有了很大的提升。
批处理程序大大提升了处理性能,但有一个很明显的缺点:计算机一次只能执行一个任务,如果某个任务需要从 I/O 设备(例如磁带)读取大量的数据,在 I/O 操作的过程中,CPU 其实是空闲的,而这个空闲时间本来是可以进行其他计算的。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《从0开始学架构》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(142)

  • kingeasternsun
    大神能否在每篇文章结尾推荐一些相关的书籍,大神领进门,修行还是靠个人
    2018-05-05
    304
  • 公号-代码荣耀
    今日心得
    1 WHAT 对高性能的理解?
    性能是软件的一个重要质量属性。衡量软件性能包括了响应时间、TPS、服务器资源利用率等客观指标,也可以是用户的主观感受(从程序员、业务用户、终端用户/客户不同的视角,可能会得出不同的结论)。

    在说性能的时候,有一个概念与之紧密相关—伸缩性,这是两个有区别的概念。性能更多的是衡量软件系统处理一个请求或执行一个任务需要耗费的时间长短;而伸缩性则更加关注软件系统在不影响用户体验的前提下,能够随着请求数量或执行任务数量的增加(减少)而相应地拥有相适应的处理能力。

    但是,什么是“高”性能?这可能是一个动态概念,与当前的技术发展状况与业务所处的阶段紧密相关。比如,现在在行业/企业内部认为的高性能,站在5年后来看,未必是高性能。因此,站在架构师、设计师的角度,高性能需要和业务所处的阶段来衡量。高到什么程度才能与当前或可预见的未来业务增长相匹配。一味去追求绝对意义上的高,没有太大的实际意义。因为,伴随性能越来越高,相应的方法和系统复杂度也是越来越高,而这可能会与当前团队的人力、技术、资源等不相匹配。但是什么才合适的高性能了?这可能需要从国、内外的同行业规模相当、比自己强的竞争者、终端用户使用反馈中获取答案并不断迭代发展。

    软件系统中高性能带来的复杂度主要体现在两方面,一方面是单台计算机内部为了高性能带来的复杂度;另一方面是多台计算机集群为了高性能带来的复杂度。

    2 WHY 为什么需要高性能?
    追求良好的用户体验;
    满足业务增长的需要。

    3 HOW 如何做好高性能?
    可以从垂直与水平两个维度来考虑。垂直维度主要是针对单台计算机,通过升级软、硬件能力实现性能提升;水平维度则主要针对集群系统,利用合理的任务分配与任务分解实现性能的提升。

    垂直维度可包括以下措施:
    增大内存减少I/O操作
    更换为固态硬盘(SSD)提升I/O访问速度
    使用RAID增加I/O吞吐能力
    置换服务器获得更多的处理器或分配更多的虚拟核
    升级网络接口或增加网络接口

    水平维度可包括以下措施:
    功能分解:基于功能将系统分解为更小的子系统
    多实例副本:同一组件重复部署到多台不同的服务器
    数据分割:在每台机器上都只部署一部分数据

    垂直维度方案比较适合业务阶段早期和成本可接受的阶段,该方案是提升性能最简单直接的方式,但是受成本与硬件能力天花板的限制。

    水平维度方案所带来的好处要在业务发展的后期才能体现出来。起初,该方案会花费更多的硬件成本,另外一方面对技术团队也提出了更高的要求;但是,没有垂直方案的天花板问题。一旦达到一定的业务阶段,水平维度是技术发展的必由之路。因此,作为技术部门,需要提前布局 ,未雨绸缪,不要被业务抛的太远。
    2018-05-05
    234
  • 三军
    面试官: 小伙子,说下进程和线程?
    我:
    1, 早期的计算机是没有操作系统的,只有输入,计算,输出。手工输入速度远低于计算机的计算速度。

    2, 于是出现了批处理操作系统,通过纸带,磁带等工具预先写入指令,形成一个指令清单(即任务)交给计算机处理。但批处理系统的缺点是只能有一个任务,而且当计算机在进行I/O处理时,CPU是空闲的。

    3, 世人发明了进程,一个进程就代表一个任务,多个进程通过分时操作能让用户认为并行操作多任务,进程间的资源是独立单元,但是可以通过介质进行通信。缺点:进程内只进行串行处理,无法很好地分工合作提高处理效率。

    4, 于是就有了操作系统调度的最小单元-线程,线程能够使进程内的子任务能够共享进程内的资源,并并行工作,大大提高操作系统的性能。

    区别:
    线程是任务调度的最小单元,共用进程内的资源。
    进程是资源分配的最小单元,与其他进程资源互相独立。
    2018-05-05
    2
    105
  • loveluckystar
    之前我们的系统是all-in的单系统模式,虽然水平扩展了大量机器,但是仍然存在性能问题,比如类似秒杀之类的活动,几乎会在瞬间把整个系统的数据库连接耗尽,导致其他服务发生卡顿甚至不可用;并且全在一个业务系统中,开发部属效率极低,扩展性也存在问题。

    于是我们将系统进行了拆分,起初是按照业务拆分成几个核心系统,同时针对不同业务的负载情况进行了合理的水平扩展,整个系统的性能得到了提升,扩展性得到了保证,并且开发部署效率也得到了极大的提高。

    但是随着业务的发展,之前的系统拆分不能满足现有业务,同时随着公司很多老员工的离开,之前的架构设计思路没有人清楚,于是就变成了走一步看一步的推进模式,衍生出了各种独立的服务达40个左右,这样系统之间的边界越来越模糊,甚至出现了服务间的循环调用,白白浪费时间。而且一次调用链路过长,发生问题很难定位。

    所以我觉得我们的系统就是一个活生生的,没有搞好架构设计的例子,前期是没有设计导致性能瓶颈,后期是过度设计导致系统复杂。

    作者回复: 典型案例,值得好好总结归纳一下

    2018-05-07
    36
  • 探索无止境
    意犹未尽,期待后文!希望可以不受篇幅的限制,针对实战案例做更多的分析!
    2018-05-05
    35
  • gevin
    我这边很多项目都是面向传统行业国企的,他们成熟的传统方案都和IT无关,先现在要向IT靠拢。通常用户那边的业务量、并发量小,企业不差钱,所以一般都是通过硬件层面的垂直扩展来提高性能的。对我们的用户而言,一方面喜欢性能强悍的硬件设备,另一方面,当我们给他们写软件开发的报告时,什么样的技术方案火,就要在报告里体现出什么样的技术(比如现在给用户的方案都要和向微服务靠拢),面子上的工作要做足,也很有意思~

    作者回复: 这就是你们项目的复杂度:如何以更低成本优雅的装逼😂

    2018-05-21
    20
  • Sadieʕ·͡ˑ·ཻʔ
    这个小程序可以改进一下吗,把语音的进度条提供出来。中断后不想从头听起
    2018-05-17
    16
  • 小喵喵
    李老师,当一个系统分为很多子系统时,每个子系统都有独立的数据库,如何保证数据的一致性呢?比如我有一个业务需要在A库插入一跳数据,在B库也要插入了一跳数据,然后在C库修改一条数据。假设中间那个库操作失败了,如何做到这个数据的一致性呢?

    作者回复: BASE原理,最终一致性,后面会讲

    2018-05-06
    12
  • pavel
    感谢老师回复。我们系统的量,每天学到存储大概有2T,采用mysql和hbase做存储。我们是做网站统计的,类似cnzz。每天接到的pv请求会到十亿次以上。我们使用集群接收,Kafka做消息队列,storm实时消费。统计结果存储在mysql,行为数据等存储在hbase。由于实时性要求以及量大,存储性能实在是一个瓶颈,主从同步滞后也相对严重,现在都已经去掉从库了。针对这种IO场景,而且实时性要求较高,R如何来应对呢?之前有个方案是mysql采取大量的分表分库,总共20台服务器,ssd硬盘,这样是能支持,但是成本还是挺大的,是否有更好的,或者我应该从哪方便去考虑呢?

    作者回复: 1. 压缩
    2. 合并:将多个数据合并为一个数据,可以在web端做
    3. 采样:统计其实不需要精确值,例如1000000001和1000000002没有区别,可以用采样来推算原始值
    你的系统复杂度就是大数据量(规模)和实时性,对结果其实不要求非常精确。

    2018-05-22
    9
  • Sean
    架构无处不在,生活中也有很多例子。就比如去快餐厅去吃饭,涉及的任务就有打饭,选菜,付款,找座位。
    普通的快餐厅,比如**缘,就是单线程,所有必须排队进行,最原始的系统架构。所以你会发现效率低,通常会拍队列,体验就不好。
    而去**王吃饭,进去就有一个引导员(负载均衡),提前帮你分配座位,发点餐单,而且有多个引导员同时工作(负载均衡集群),而且各种菜系可以同时进行(并行)。另外一些需要等待的菜,会让你边吃边等(异步)。所以看上去人好多,很少有在排队的现象。可见,这位老板也是位不错的架构师。

    作者回复: 666

    2018-10-16
    6
  • 木木
    讲得很好啊,就是更新太慢,不够看啊
    2018-05-05
    6
  • 彡工鸟
    举例分析可否适当引入存储层来讲解呢。这才是真正的复杂点吧?
    2018-05-05
    6
  • 印宏宇
    一、所有的高性能都要针对不同的业务场景:
    (1)单机的高性能主要在于多任务处理,让不同或相同的任务能够同时处理。
    (2)集群的高性能主要在于任务(业务模块,组件,资源)的拆分和利用,一是分配,二是分解,大规模分配的前提是要合理的分解系统,合理的分解也是为了更好的聚合任务。

    二、其实现在针对网络访问,dns,反向代理,web服务,应用服务,缓存,数据库,分布式文件等都有很多的解决方案,但如何把这些方案和当前你的业务结合起来,并且你的业务如何进行设计,如何拆分功能和组件来满足不同时期的业务性能变化。

    三、其实老师今天提供了一个渐进性的方案,也是业务性能变化的应对方法论,先单机,再集群,然后拆分再集群,不管什么样的性能问题都能用这个方法论来解决。具体如何集群相应开源的解决方案很多,但是业务系统如何拆分,拆分的粒度,我觉得老师也应该有相应的方法论,期待...

    具体到我们公司,涉及到性能要改的地方很多了,包括静态资源处理,业务消息队列多线程处理,数据库现在是单库,如何进行读写分离。。。
    2018-05-06
    5
  • 肖一林
    拆分业务就是消除木桶效应。服务之间调用尽量少,能减少系统损耗。
    2018-05-18
    4
  • 清泉
    说说我的理解,不管是任务分配还是任务分解,都是通过分摊单台机器的流量来提高整个系统的处理性能。

    对于任务分解,我认为不但没有性能上的收益,反而有性能上的损耗,本来可以在一个进程内部完成的交互,分解后却需要进行服务器间的网络交互。(分解前后业务逻辑不变的情况下)


    不知道我这么理解对不对,但是与楼主说的任务分解一定程度上可以提高性能有些矛盾,求楼主指点迷津😊

    作者回复: 有性能损耗,但性能收益更多,举个简单例子,A功能和B功能在同一系统,A功能慢查询导致整个系统性能低,B功能性能同样被拉低。
    我举例是告诉你说有慢查询,实际上很多系统隐藏的性能问题并不明显就能看出来。

    2018-05-05
    4
  • zeus2_18921421203
    目前性能首先必须把单机性能用起来,比如多线程一起执行,写入批量 减少io。单机到极限后用集群,集群必须要有任务调度,还存在互斥锁,复杂度急剧提高,性能再不够要分析性能瓶颈了,是io还是线程切换还是中断?基本单机加集群能搞定大部分,很少要优化线程模型的,用线程池就足够了,还有actor这个大杀器没用呢。
    2018-05-05
    4
  • 十七
    目前系统按业务做了拆分,确实带来了更大的复杂度,特别是数据库层面上,数据并不能根据业务完全分离
    2018-05-05
    4
  • 老王
    我在做一个机器学习的程序,目前还是在单机上训练SVM,可以通过划分训练集,利用多台机器并行训练然后再合并的方式提升训练性能。
    2018-05-05
    4
  • 卡莫拉内西
    我们公司做的政府项目,没有高并发的场景,业务大多也是crud,高可用是有的,高扩展的场景较少,需求基本上是产品经理整理好的,一台ng,两台应用服务器,一主两从mysql,nas设备,redis都可以不用,请问这样业务场景的公司是否适合长期呆下去,还是说可以为了架构而架构,公司本身不差钱,给政府做项目几乎也是友情价,老板在乎的可能是数据

    作者回复: 职业选择不是本专栏的内容呢,看你个人追求什么了,有的人追求稳定,有的人追求兴趣,有的人追求回报

    2018-05-06
    3
  • 新人小胖
    我们现在的系统是一个消息处理系统,主要的瓶颈在于消息的处理是必须要是顺序的,不能乱序,所以subscribe消息是单线程的,目前需要解决这个问题。

    作者回复: “顺序”有两种场景:1. 按先后顺序分配,2. 处理完前一条才能处理完后一条。

    第一种情况按照简单的任务分配就可以实现高性能,第二种如果任务的处理比较复杂的话,可以用任务分解,将任务分解为多个步骤,采用流水线的架构设计达到高性能,如果任务很简单,单台机器做好优化性能也能做到比较高,例如redis就是单进程的

    2018-05-05
    3
收起评论
99+
返回
顶部