一、相关概念引入
1.1 基本概念
1、应用(Application)/系统(System)
为了完成⼀整套服务的⼀个程序或者⼀组相互配合的程序群。⽣活例⼦类⽐:为了完成⼀项任 务,⽽搭建的由⼀个⼈或者⼀群相互配的⼈组成的团队。
2、模块(Module)/组件(Component)
当应用较复杂时,为了分离职责,将其中具有清晰职责的、内聚性强的部分,抽象出概念,便于理解。⽣活例⼦类⽐:军队中为了进⾏某据点的攻克,将⼈员分为突击⼩组、爆破⼩组、掩护⼩组、 通信⼩组等。
3、分布式(Distributed)
系统中的多个模块被部署于不同服务器之上,即可以将该系统称为分布式系统。如Web服务器与数据库分别⼯作在不同的服务器上,或者多台Web服务器被分别部署在不同服务器上。⽣活例⼦类⽐:为了更好的满⾜现实需要,⼀个在同⼀个办公场地的⼯作⼩组被分散到多个城市的不同⼯作场地中进⾏远程配合⼯作完成⽬标。跨主机之间的模块之间的通信基本要借助⽹络⽀撑完成。
4、集群(Cluster)
被部署于多台服务器上的、为了实现特定⽬标的⼀个/组特定的组件,整个整体被称为集群。比如多个MySQL⼯作在不同服务器上,共同提供数据库服务目标,可以被称为⼀组数据库集群。⽣活例⼦类比:为了解决军队攻克防守坚固的⼤城市的作战⽬标,指挥部将⼤批炮兵部队集中起来形成⼀个炮兵打击集群。
5、分布式vs集群
通常不用太严格区分两者的细微概念,细究的话,分布式强调的是物理形态,即工作在不同服务器上并且通过网络通信配合完成任务;而集群更在意逻辑形态,即是否为了完成特定服务目标。
6、主(Master)/从(Slave)
集群中,通常有⼀个程序需要承担更多的职责,被称为主;其他承担附属职责的被称为从,比如MySQL集群中,只有其中⼀台服务器上数据库允许进行数据的写⼊(增/删/改),其他数据库的数据修改全部要从这台数据库同步而来,则把那台数据库称为主库,其他数据库称为从库。
6、中间件(Middleware)
⼀类提供不同应用程序用于相互通信的软件,即处于不同技术、工具和数据库之间的桥梁,和业务无关且更通用(数据库/缓存/消息队列/Web服务器/网关)。⽣活例⼦类⽐:⼀家饭店开始时,会每天去市场挑选买菜,但随着饭店业务量变⼤,成⽴⼀个采购部,由 采购部专职于采买业务,称为厨房和菜市场之间的桥梁。
1.2 评价指标(Metric)
1、可用性(Availability)
**考察单位时间段内,系统可以正常提供服务的概率/期望。例如:年化系统可用性=系统正常提供服务时长/⼀年总时长。**这⾥暗含着⼀个指标,即如何评价系统提供⽆法是否正常,我们就不深⼊了。 平时我们常说的4个9即系统可以提供99.99%的可⽤性,5个9是99.999%的可⽤性,以此类推。 我们平时只是⽤⾼可⽤(High Availability HA)这个⾮量化⽬标简要表达我们系统的追求。
2、响应时⻓(Response TimeRT)
**指用户完成输⼊到系统给出用户反应的时长,用来衡量服务器性能。例如点外卖业务的时长=拿到外卖的时刻-完成点单的时刻。**通常我们需要衡量的是最⻓响应时⻓、平均响应时⻓和中位数响应时⻓。这个指标原则 上是越⼩越好,但很多情况下由于实现的限制,需要根据实际情况具体判断
3、吞吐(Throughput)vs并发(Concurrent)
吞吐考察单位时间段内,系统可以成功处理的请求的数量。并发指系统同⼀时刻⽀持的请求最高量。例如⼀条辆⻋道⾼速公路,⼀分钟可以通过20辆⻋,则并发是3,⼀分钟的吞吐量是20。实践中,并发量往往⽆法直接获取,很多时候都是⽤极短的时间段(⽐如1秒)的吞吐量做代替。我们平时⽤⾼并发(Hight Concurrnet)这个⾮量化⽬标简要表达系统的追求。
二、架构演进
2.1 单机结构
单机架构,就是只有一台服务器,这个服务器负责所有的工作。
初期,我们需要利⽤我们精⼲的技术团队,快速将业务系统投⼊市场进⾏检验,并且可以迅速响 应变化要求。但好在前期⽤⼾访问量很少,没有对我们的性能、安全等提出很⾼的要求,⽽且系统架 构简单,⽆需专业的运维团队,所以选择单机架构是合适的。

用户在浏览器中输⼊www.xxx.com,⾸先经过DNS服务将域名解析成IP地址10.102.41.1,随后浏览器访问该IP对应的应⽤服务。就是我们所写的服务器程序,然后这个服务器程序又作为mysql的客户端向mysql服务器发送读写请求。
单机程序中,其实也可以把数据库服务器也去掉,光一个应用服务器又复杂业务又负责数据存储,但是这样会比较麻烦
千万不要瞧不起单机架构!!因为绝大部分公司的产品都是单机架构的,因为计算机硬件发展速度很快,哪怕只有一台主机他的性能也是很高的,可以支持非常高的并发和非常大的数据存储
相关软件:
Web服务器软件:Tomcat、Netty、Nginx、Apache等
数据库软件:MySQL、Oracle、PostgreSQL、SQL Server等
2.2 为什么需要分布式系统
单机效率已经很高了,但是如果业务进一步增长,当用户量和数据都水涨船高,一台主机难以应付的时候,就又必要引入更多的主机、更多的硬件资源!!
1、一台主机的硬件资源是有上限的,包括但不限于以下操作
(1)CPU
(2)内存
(3)硬盘
(4)网络
(5)......
服务器每次收到一个请求,都是需要消耗上述的一些资源的,如果同一时刻处理的请求多了,可能就会导致某个硬件资源不够用了!!从而导致服务器处理请求的时间变长甚至是处理出错!!
2、如果我们遇到了这样服务器不够用的场景要如何处理呢??
(1)节流:软件上优化。对程序员要求高,比方通过性能测试查看是哪个环节出的问题再去对症下药(数据结构和算法)
(2)开源:增加更多的硬件资源,但是一个主机上能够增加的硬件资源也是有限的,这取决于主板的扩展能力。
(3)引入多台主机:但并不是说买了新机器就可以解决问题了,也需要在软件上做出相应的调整和适配!!
引入多台主机,咱们得系统就可以被称为"分布式系统"了,但是这是万不得已的操作,因为这样系统的复杂程度会大大提高,且出现bug的概率也会更高!!
2.3 应用服务和数据库服务分离
随着系统的上线,我们不出意外地获得了成功。市场上出现了⼀批忠实于我们的用户,使得系统 的访问量逐步上升,逐渐逼近了硬件资源的极限,同时团队也在此期间积累了对业务流程的⼀批经 验。⾯对当前的性能压⼒,我们需要未雨绸缪去进⾏系统重构、架构挑战,以提升系统的承载能力。 但由于预算仍然很紧张,我们选择了将应⽤和数据分离的做法,可以最小代价的提升系统的承载能力。

和之前架构的主要区别在于将数据库服务独立部署在同⼀个数据中心的其他服务器上,应⽤服务通过网络访问数据。
2.4 应用服务集群架构
我们的系统受到了用户的欢迎,并且出现了爆款,单台应⽤服务器已经⽆法满⾜需求了。我们的单机应⽤服务器⾸先遇到了瓶颈,摆在我们技术团队⾯前的有两种⽅案,⼤家针对⽅案的优劣展示了热烈的讨论:
**• 垂直扩展/纵向扩展Scale Up。通过购买性能更优、价格更高的应用服务器来应对更多的流量。这种方案的优势在于完全不需要对系统软件做任何的调整;**但劣势也很明显:硬件性能和价格的增⻓关系是⾮线性的,意味着选择性能2倍的硬件可能需要花费超过4倍的价格,其次硬件性能提升是 有明显上限的。
• 水平扩展/横向扩展Scale Out。通过调整软件架构,增加应用层硬件,将用户流量分担到不同的 应⽤层服务器上,来提升系统的承载能能。 这种⽅案的优势在于成本相对较低,并且提升的上限空 间也很⼤。但劣势是带给系统更多的复杂性,需要技术团队有更丰富的经验。 经过团队的学习、调研和讨论,最终选择了水平扩展的方案,来解决该问题,但这需要引入⼀个新的组件负载均衡:为了解决用户流量向哪台应用服务器分发的问题,需要⼀个专门的系统组件做流 量分发。实际中负载均衡不仅仅指的是工作在应用层的,甚至可能是其他的网络层之中。

2.5 理解负载均衡
负载均衡器就像一个组长一样,要负责把任务合理分发给组员
1、负载均衡器的流量调度算法也有很多种,这⾥简单介绍⼏种较为常⻅的
• Round-Robin 轮询算法。即⾮常公平地将请求依次分给不同的应⽤服务器。但是这样其实并不好,如果一个用户发送多个请求的话我们会希望尽可能让一个用户的请求都在一台机器上
• Weight-Round-Robin轮询算法。为不同的服务器(⽐如性能不同)赋予不同的权重(weight), 能者多劳。
• ⼀致哈希散列算法。通过计算用户的特征值(⽐如IP地址)得到哈希值,根据哈希结果做分发,优 点是确保来⾃相同用户的请求总是被分给指定的服务器。也就是我们平时遇到的专项客⼾经理服务。
具体这个算法怎么去设计,也是要结合实际的业务场景。
2、 负载均衡里能够承担这么多请求么??
负载均衡器(负责分配工作)对于请求的承担能力要远超应用服务器(负责执行任务)的。如果真的扛不住了那就只能引入更多的负载均衡器了!(多个机房)
3、关于负载均衡的生活举例:1个班主任(应用服务器)可以跟进50个同学(请求),跟进他们的作业、日常需求。但是当学生越来越多的时候就需要有更多的班主任(引入更多应用服务器),但是班主任多的话也需要管理,因为比如有的班主任请假(应用服务器宕机),需要想办法把他的学生分担给其他班主任,所以设置1个年段长(负载均衡器),来给班主任分配学生(流量调度算法),而随着学生再更多,班主任和年级长也更多,这个时候就需要有更多的校区(增加负载均衡器),然后由校长(负载均衡器管理器)对各个校区做管理。
要注意的是,当人(机器)变多的时候,管理成本和出问题的概率也会变得很高!!
4、负载均衡软件:Nginx、HAProxy、LVS、F5等
2.6 读写分离/主从分离架构
我们把用户的请求通过负载均衡分发到不同的应⽤服务器之后,可以并⾏处理了, 并且可以随着业务的增⻓,可以动态扩张服务器的数量来缓解压⼒。但是现在的架构⾥,无论扩展多少台服务器,这些请求最终都会从数据库读写数据,到⼀定程度之后,数据的压⼒成为系统承载能⼒的瓶颈点。我们可以像扩展应⽤服务器⼀样扩展数据库服务器么?
答案是否定的,因为数据库服务有其特殊性:如果将数据分散到各台服务器之后,数据的⼀致性将无法得到保障。所谓数据的⼀致性, 此处是指:针对同⼀个系统,无论何时何地,我们都应该看到⼀个始终维持统⼀的数据。 想象⼀下, 银⾏管理的账户⾦额,如果收到⼀笔转账之后,⼀份数据库的数据修改了,但另外的数据库没有修改,则用户得到的存款⾦额将是错误的。 我们采⽤的解决办法是这样的,保留⼀个主要的数据库作为写⼊数据库,其他的数据库作为从属数据库。从库的所有数据全部来⾃主库的数据,经过同步后,从库可以维护着与主库⼀致的数据。然后为了分担数据库的压⼒,我们可以将写数据请求全部交给主库处理,但读请求分散到各个从库中。 由于⼤部分的系统中,读写请求都是不成⽐例的,例如100次读1次写,所以只要将读请求由各个从 库分担之后,数据库的压⼒就没有那么大了。当然这个过程不是无代价的,主库到从库的数据同步其实是有时间成本的,但这个问题我们暂时不做进⼀步探讨。

应用中需要对读写请求做分离处理,所以可以利用⼀些数据库中间件,将请求分离的职责托管出去。
相关软件:MyCat、TDDL、Amoeba、Cobar等类似数据库中间件等
2.7 引入缓存-冷热分离架构
随着访问量继续增加,发现业务中**⼀些数据的读取频率远大于其他数据的读取频率。我们把这部分数据称为热点数据,与之相对应的是冷数据**。
针对热数据,为了提升其读取的响应时间,可以增加本地缓存,并在外部增加分布式缓存,缓存热⻔商品信息或热⻔商品的html⻚⾯等。通过缓存能把绝大多数请求在读写数据库前拦截掉,⼤大降低数据库压力。其中涉及的技术包括:使用memcached作为本地缓存,使用Redis作为分布式缓存,还会涉及缓存**⼀致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效****等问题**。
缓存缓存不仅提高了效率,也降低了数据库的压力**,但必须要付出代价---小!**!
但是如果我们修改了主数据库的内容,势必也有可能需要修改redis的内容,这就可能存在一方修改成功了一方修改失败的这种情况,这就是我们引入分布式需要付出维护数据同步和一致性的代价!!
------>欲戴皇冠,必承其重!!(想得到一个效果就需要付出一定的代价)
相关软件:Memcached、Redis等缓存软件
2.8 数据库分库分表
随着业务的数据量增大,大量的数据存储在同⼀个库中已经显得有些力不从心了,所以可以按照业务,将数据分别存储。比如针对评论数据,可按照商品ID进行hash,路由到对应的表中存储;针对⽀付记录,可按照⼩时创建表,每个小时表继续拆分为小表,使用用户ID或记录编号来路由数据。只要实时操作的表数据量足够小,请求能够⾜够均匀的分发到多台服务器上的⼩表,那数据库就能通过⽔平扩展的⽅式来提⾼性能。其中前⾯提到的Mycat也⽀持在⼤表拆分为小表情况下的访问控制。这种做法显著的增加了数据库运维的难度,对DBA(数据库管理员)的要求较⾼。数据库设计到这种结构时,已经可以称为分布式数据库,但是这只是⼀个逻辑的数据库整体,数据库⾥不同的组成部分是由不同的组件单独来实现的,如分库分表的管理和请求分发,由Mycat实现,SQL的解析由单机的数据库实现,读写分离可能由网关和消息队列来实现,查询结果的汇总可能由数据库接口层来实现等等,这种架构其实是MPP (大规模并行处理)架构的⼀类实现。

相关软件:Greenplum、TiDB、Postgresql XC、HAWQ等,商⽤的如南⼤通⽤的GBase、睿帆科技的雪球 DB、华为的LibrA等
2.9 业务拆分-微服务
随着人员增加,业务发展,我们将业务分给不同的开发团队去维护,每个团队独立实现自己的微服务,然后互相之间对数据的直接访问进行隔离,可以利用Gateway、消息总线等技术,实现相互之间的调用关联。甚至可以把⼀些类似用户管理、安全管理、数据采集等业务提成公共服务。
负载均衡是为了解决请求增多的问题,分库分表是为了解决存储空间不足的问题。而微服务本质上是为了解决人员组织结构的分配问题(一般是大厂,如果是小公司没几个人搞微服务就没啥必要)----->当应用服务器复杂了,势必就需要更多的人来维护,而人多了就需要配套的管理来把这些人组织好,通过划分组织结构分成多个组(分工,也是更好划分责任),每个组分配领导进行管理。
问题:引入微服务解决了人的问题,但是付出的代价是什么呢??
1、系统性能下降。因为本来各个模块的相互调用只需要通过进程内部就可以完成,但是现在拆分出来的各个模块就必须依赖网络通信,网络通信的速度可能是比硬盘还慢的**(幸运的是硬件技术的发展,现在网卡有万兆网卡,读写速度已经超过了硬盘读写了,但是会比较贵)****,所以要想保证不下降太多,只能花钱引入更多的机器和硬件资源**。
2、系统复杂程度提高,可用性受到影响 。因为服务器更多以为着出问题的概率更大,因此着着就需要有一系列的手段来保证系统的可用性(更丰富的监控报警,以及配套的运维人员)
微服务的优势:
1、解决了人的问题
2、减少重复代码,提供功能的复用性。)
3、高度解耦: 每个服务都是独立的,可以独立开发、部署和扩展(硬件资源的综合调配),提高了系统的可维护性和可扩展性。
4、快速迭代: 服务可以根据需求快速更新和迭代,更容易适应业务变化。
5、资源隔离,互不影响,对调用方隐藏内部细节。
三、分布式系统总结
1、单机架构(应用程序+服务器)
2、数据库和应用分离:应用程序和数据库服务器可以分别放到不同主机上进行部署,这样有利于我们更好地调整硬件结构,提高性价比
3、引入负载均衡,应用服务器成为了一个集群:(1)通过负载均衡器把请求比较均匀地分发给集群中的每个应用服务器。(2)即使集群中的某个主机挂了,其他主机仍然可以承担服务,提高了整个系统的可用性。
4、引入读写分离,数据库主从结构:一个数据节点作为主节点,其他N个数据库作为同节点,主节点负责写数据,从节点负责读数据, 同时主节点还需要把修改过的数据同步给从节点。
5、引入缓存,冷热数据分离:(根据二八原则)进一步提高服务器针对请求的处理能力,redis在分布式系统中,通常扮演着缓存这样的角色 ,用来存储热点数据。
付出的代价就是数据库和缓存的数据一致性问题需要解决!
6、**引入分库分表:**让数据库能够进一步扩展存储空间。
7、引入微服务:从业务功能的角度把应用服务器拆分成更多功能更单一、更小的服务器。
付出的代价就是系统的性能会下降,且复杂程度会提高。
上述这些演化步骤,只是一个粗略的过程,实际上一个商业项目的真实演化过程都是和他的业务发展密切相关的,业务决定技术,技术只是用来给业务提供支持的
所谓分布式系统,就是想办法引入更多的硬件资源。
注意,以上所说的架构演变顺序只 是针对某个侧⾯进⾏单独的改进,在实际场景中,可能同⼀时间会有⼏个问题需要解决,或者可能先达到瓶颈的是另外的⽅⾯,这时候就应该按照实际问题实际解决。如在政府类的并发量可能不⼤,但业务可能很丰富的场景,⾼并发就不是重点解决的问题,此时优先需要的可能会是丰富需求的解决⽅案。对于单次实施并且性能指标明确的系统,架构设计到能够⽀持系统的性能指标要求就足够了,但要留有扩展架构的接⼝以便不备之需。对于不断发展的系统,如电商平台,应设计到能满⾜下⼀阶段 ⽤⼾量和性能指标要求的程度,并根据业务的增⻓不断的迭代升级架构,以⽀持更⾼的并发和更丰富 的业务。
所谓的"⼤数据"其实是海量数据采集清洗转换、数据存储、数据分析、数据服务等场景解决⽅ 案的⼀个统称,在每⼀个场景都包含了多种可选的技术,如数据采集有Flume、Sqoop、Kettle等,数据存储有分布式⽂件系统HDFS、FastDFS,NoSQL数据库HBase、MongoDB等,数据分析有Spark技术栈、机器学习算法等。总的来说⼤数据架构就是根据业务的需求,整合各种⼤数据组件组合⽽成的 架构,⼀般会提供分布式存储、分布式计算、多维分析、数据仓库、机器学习算法等能⼒。⽽服务端架构更多指的是应⽤组织层⾯的架构,底层能力往往是由⼤数据架构来提供。