1.架构的分类

架构一般可以分为技术架构,应用架构,业务架构:
1.业务架构从概念层帮助开发人员更好的理解系统。
2. 应用架构从逻辑层面帮助开发落地系统,如数据交互关系、应用形式、交互方式,是的整 个系统逻辑上更容易理解,步入大家熟知的SOA就属于应用架构的范畴 。
3.技术架构主要解决技术平台选型、如操作系统、中间件、设备、多机房、水平扩展、高可 用等问题。

2.大型架构的网站演进

2.1 电商案例

为了更好的理解,我们用电商网站来举例,作为一个交易类型的网站,一定会具备 用户(用户注册、用户管理)、商品(商品展示、商品管理)、交易(下单、支付)这些功能 ,假如只需要支持这几个基本功能

分布式架构选型 分布式架构种类_服务器


各个功能 模块之间是通过 JVM 内部的方 法调用来进行交互的,而应用和 数据库之间是通过 JDBC 进行访 问。

2.2单机负载警告

随着网站的开放,访问量不断的增大,那么这个服务器的负载势必会持续升高,先从架构上来考虑,别的事情先忽略。可以把数据库从一台机器上分布到两台机器上。

分布式架构选型 分布式架构种类_分布式架构选型_02


网站从一台变成了2台,这个变化对我们 来说影响非常小。单机的情况下,我们应 用采用 JDBC 的方式来和数据库进行连 接,现在数据库与应用分开了,我们只需 要在配置文件中把数据库的地址从本机 改成数据库服务器的ip地址就行。 对于开发、测试、部署都没有影响 ,调整以后我们能够缓解当前的系统压力, 不过随着时间的退役,访问量继续增大的 话,我们的系统还是需要做改造 。

为什么这么分呢?

一个请求的访问到处理到最终到返回,性能的瓶颈再:文件I/O,网络I/O,CPU,内存等因素,如果资源消耗过多,通常会造成系统响应速度比较慢,所以增加了一台机器,使得数据库的IO和CPU独占一台机器从而增加性能。

CPU/IO/内存

1.主要由上下文切换,因为每一个CPU核心只能在同一时刻执行一个线程,cpu的几种调度方式。如抢占式和轮询,每个线程都会分配一定的执行时间,当达到执行时间的时候,线程中由IO阻塞或者优先级高的线程要执行任务时,cpu会切换执行其他线程,而在切换的过程中,需要存储当前线程的执行状态并恢复要执行的线程状态,这 个过程就是上下文切换。比如 IO、锁等待等场景下也会触发上下文切换,当上下文切换 过多时会造成内核占用比较多的CPU。

2.文件IO,比如频繁的日志写入,磁盘本身的处理速度较慢、都会造成IO性能问题

3.网络IO,带宽不够

4.内存,包括内存溢出、内存泄漏、内存不足 ;

3.应用服务器->集群

这个时候应用服务器的压力变大,服务器由一台变成两台,这两个服务器之间没有直接的交互,他们依赖的数据库对外界提供的服务,这个时候会有两个问题出现:
1.两个服务器访问如何选择。
可以通过DNS域名解析也可以通过负载均衡
2.session问题

3.1 水平和垂直

垂直伸缩:表示通过升级或者增加单台机器的硬件来支撑访问量以及数据量增长的方式,垂 直伸缩的好处在于技术难度比较低,运营和改动成本也相对较低。但是缺点是机器性能是有 瓶颈的,同时升级高性能的小型机或者大型机,成本是非常大的。这也是阿里去IOE的一个 原因之一 增加 C PU 核心数 : 增加 C P U 后系统的服务能力能够得到大的增长,比如响应速度、同时可 以处理的线程数。但是引入 C PU 后也会带来一些显著的问题

  1. 锁竞争加剧;多个线程同时运行访问某个共享数据,那么就涉及到锁竞争,锁竞争激烈时 会导致很多线程都在等待锁,所以即时增加 C PU 也无法让线程得到更快的处理。当然这里 是有调优手段的,可以通过调优手段来降低锁竞争
  2. 支撑并发请求的线程数是固定的,那么即时增加 C PU ,系统的服务能力也不会得到提升
    3.对于单线程任务,多核心 C PU 是没有太大的作用的 增加内存: 增加内存可以直接提成系统的响应速度 , 当然,也有可能达不到效果,就是如果 JVM 堆内存是固定的。
    水平伸缩:通过增加机器来支撑访问量及数据量增长的方式,成为水平伸缩,水平伸缩理论 上来说没有瓶颈,但是缺点是技术要求比较高,同时给运维带来了更大的挑战 垂直伸缩和水平伸缩都有各自的有点,我们在实际使用过程中都会对两者做结合,一方面要 考虑硬件升级的成本,一方面要考虑软件改造的成本。

3.2引入负载均衡设备

分布式架构选型 分布式架构种类_分布式架构选型_03


负载均衡算法

1.轮询发:将请求按照顺序轮流分发到各个服务器上,没有关心服务器的实际的连接数和当前系统负载。

缺点:当集群中服务器硬件配置不同、性能差别大时,无法区别对待

2.随机法: 根据随机函数将请求分发到不同的机器上,如果请求量过大的话,就会平均发到每一台机器上。

优点:简单使用,不需要额外的配置和算法。

缺点:随机数的特点是在数据量大到一定量时才能保证均衡,所以如果请求量有限的话,可 能会达不到均衡负载的要求。

3.源地址hash法

根据消费服务的ip进行hash,将该hash值与服务器列表对比,进行选择服务访问;

4.加权轮询法

不同服务器的抗压能力不同,所以根据不同的比重来分配

5.最小连接数法

根据后台服务连接数的请求情况,选择一个链接数比较小的服务器访问

3.2.1session问题

打开一个网页,基本上需要浏览器和 web 服务器进行多次交互,我们都知道 Http 协议 本身是无状态的,这也是http协议设计的初衷,客户端只需要简单的向服务器请求下载某些 文件,无论是客户端还是服务器都没必要记录彼此过去的行为,每一次请求之间是独立的, 好比一个顾客和一个自动售货机之间的关系一样.
而实际上,我们很多的场景都需要带有状态的特性,因此聪明的我们引入了 session+cookie 机制来记住每次请求的会话。 在会话开始时,给当前会话分配一个唯一的会话标识(sessionid),然后通过 cookie 把这个 标识告诉浏览器,以后在每次请求的时候,浏览器都会带上这个会话标识来告诉web服务器 请求属于哪个会话。在web服务器上,各个会话有独立的存储,保存不同会话的信息。 如果遇到禁用cookie的情况,一般的做法就是把这个会话标识放到URL的参数中。

3.2.2 分布式下的session共享

服务器实现的session复制和session共享,这个共享是和服务器相关的;我们在web服务之间增加了会话数据同步,通过同步保证了不同的web服务之间session一致;
存在问题:
1.同步session数据会造成网络带宽开销。只要session数据有变化,就要将数据同步到其他web服务器上,机器越多,带来的开销越大;
2. 每台Web服务器都要保存所有Session数据,如果整个集群的Session数据很多(很多 人同时访问网站)的话,每台机器用于保存Session数据的内容占用会很严重。 这个方案是靠应用容器来完成Session的复制从而解决Session的问题的,应用本身并不关 心这个事情。这个方案不适合集群机器数多的场景。
利用成熟的session复制。内存数据库redis; Session 数据不保存到本机而且存放到一个集中存储的地方,修改 Session 也是发生在集中 存储的地方。Web 服务器使用 Session 从集中存储的地方读取。这样保证了不同 Web 服务 器读取到的Session数据都是一样的。存储Session的具体方式可以是数据库
存在问题:
1.读取session引入的网络操作,相对于本机来说,问题在于存在延迟和不稳定性;
2.如果集中存储session的机器或者是集群发生了问题,就会影响应用;
相对于Session Replication,当Web服务器数量比较大、Session数比较多的时候,这个集 中存储方案的优势是非常明显的。

3.2.3 将session维护在客户端

cookie,客户端存在风险,数据不安全,存放的数据比较小;所以将session维护在客户端,还要给数据加密;session数据存放到cookie中,然后web服务器从cookle中生成的session数据,这就好比我们每次都把自己的碗筷带在身上,这样去那家饭店就可以随意选择了。相 对前面的集中存储方案,不会依赖外部的存储系统,也就不存在从外部系统获取、写入Session 数据的网络时延、不稳定性了。
存在问题:
安全性。Session数据本来都是服务端数据,而这个方案是让这些服务端数据到了外部网络及 客户端,因此存在安全性上的问题。我们可以对写入的Cookie的Session数据做加密,不过 对于安全来说,物理上不能接触才是安全的。

3.2.4数据库压力增大,读写分离

随着业务的继续增长,数据量和访问量持续增加。对于大型网站来说,有不少业务是读多写 少,这个情况也会直接反馈到数据库上。那么对于这种情况来说,我们可以考虑采用读写分 离的方式来优化数据库的压力 ;
这个结构的变化会带来两个问题 :

  1. 数据如何同步 我们希望通过读库来分担主库上读的压力,那么首先 需要解决的是怎么复制到读库的问题。数据库系统一 般都提供了数据复制的功能,我们可以直接使用数据 库系统自身的机制。不同的数据库系统有不同的支持, 比如Mysql支持Master+slave的结构提供数据复制机 制 ;
  2. 应用对数据源如何路由 对于应用来说,增加一个读库对结构变化产生了一定 的影响,也就是我们的应用需要根据不同的情况来选 择不同的数据库源 ;

3.2.5 搜索引擎是一个读库

搜索引擎其实可以理解成一个读库,我们的商品存储在数据库中,而网站需要提供用户实时 检索的功能,尤其是在商品搜索这块。对于这样的读请求,如果全部走读库,其实性能也会 存在一个瓶颈。而使用搜索引擎,不仅仅能大大提高检索速度。还能减轻读数据库的压力 而搜索引擎最重要的工作,就是需要根据被搜索的数据来构建索引,而随着被搜索的数据的 变化,索引也需要相应变化。
搜索集群的使用方式和读库的使用方式是一样的,只 是构建索引的过程基本都是需要我们自己来实现。可 以从两个纬度对搜索引擎构建索引的方式进行规划,一个是按照全量/增量划分。一种是按照实时/非实时划分。
全量方式用于第一次建立索引,可能是新建,也可能 是重建。而增量的方式是在全量的基础上持续更新索 引。 实时和非实时提现在索引更新的时间上,实时是最好的,非实时主要考虑到对数据源头的保护 总的来说,搜索引擎技术解决了站内搜索时某些场景 下的读的问题,提供了更好的查询效率。

3.2.6加速数据读取的利器-缓存及分布式存储

在大型网站中,基本上就是在解决存储和计算的问题,所以存储是一个很重要的支撑系统。 网站建设初期我们都是从关系型数据库开始的,而且很多时候为了方便,我们会把一些业务 逻辑放在数据库里面去做,比如触发器、存储过程。虽然在前期能够很方便的解决问题,但 是在未来的发展过程中会带来很多的麻烦,比如数据量大了以后,要做分库分表操作等. 同 时,业务发展到一定的体量以后,对存储的需求不能完全通过关系型数据库来满足 ;

3.2.7 分布式文件系统

对一些图片、大文本,使用数据库就不合适了,所以我们会采用分布式文件系统来实现文件 存储,分布式文件系统有很多产品、比如淘宝的TFS、google的GFS。还有开源的HDFS ;

3.2.8NOSQL

NoSQL是定位于是文件系统和SQL关系型数据库之间的范畴。

数据缓存

大型网站内部都会用到一些数据缓存,主要用于分担数据库的读的压力,缓存系统一般是用 来保存和查询键值对的。应用系统中一般会把热点数据放入到缓存,而缓存的填充也应该是 由应用系统完成。如果数据不存在,则从数据库独处数据后放入缓存。随着时间的推移,当 缓存容量不够需要清除数据时,最近不被访问的数据就会被清理掉。还有一种方式就是在数 据库的数据发生变化后,主动把数据放入到缓存系统中,这样的好处是数据变化时能够及时 更新缓存的数据,不会造成读取失效。

分布式架构选型 分布式架构种类_服务器_04


页面缓存

除了数据缓存外,对页面做缓存,数据缓存可以加速应用在响应请求时的数据读 取数度,但是最终展示给用户的还是页面,有些动态产生的页面或者访问量特别高的页面, 我们会对页面或者内容做一些缓存。

弥补关系型数据库的不足,引入分布式存储

为了弥补关系型数据库的不足,引入分布式存储;

redis、mongoDB、cassandra、HBase;根据不同的场景和数据结构类型,选择相应的数据类型,选择合适的分布式系统存储可能会提高性能。分布式系统通过集群提供了一个高容量,高并发,数据冗余的支持。

分布式架构选型 分布式架构种类_服务器_05

3.2.9读写分离,数据库瓶颈

通过读写分离以及在某些场景用分布式存储系统替换关系型数据库的方式,能够降低主库的 压力,解决数据存储方面的问题,不过随着业务的发展,我们的主库也会遇到瓶颈。推演到 现在,我们的网站各个模块:交易、商品、用户数据都还是存储在一个数据库。尽管增加了 缓存、读写分离的方式,但是数据库的压力仍然在持续增加,因此我们可以对数据垂直拆分 和水平拆分来解决数据库压力问题 。

3.2.9.1专库专用,数据库垂直拆分

把数据库中不同的业务的数据拆分到不同的数据库中,把用户,交易,商品的数据分开。

分布式架构选型 分布式架构种类_数据库_06


不同业务的数据从一个数据库中拆分到多个数据库中存储,如何实现单机跨业务的事务

1.使用分布式事务

2.去掉事务或者不追求强事务支持

对于数据拆分解决了把所有业务数据存放到一个库 中的压力问题,根据不同的特点进行更多的优化。

数据水平拆分:

数据水平拆分就是把一张表中的数据拆分到两个数据库中,为什么要使数据水平拆分的原因是:某个数据业务的数据量或者是更新量已经达到一个单表库的瓶颈,这个时候把这个数据库中的数据拆分到不同的数据库中。

数据水平拆分与读写分离的区别是:读写分离解决的是读压力大的问题,对于数据量大或者 更新量大的情况并不起作用。

数据水平拆分与数据垂直拆分的区别是,垂直拆分是把不同的表拆分到不同的数据库,而水 平拆分是把同一个表拆分到不同的数据库中。

我们可以进一步把用户表拆分到两个数据库中,它们拥有结构一模一样的用户表,而且每个 库中的用户表都只涵盖了一部分的用户,两个数据库的用户和在一起就相当于没有拆分之前 的用户表

分布式架构选型 分布式架构种类_数据库_07

3.2.9.2水平拆分带来的问题

1.sql漏油问题,需要根据一个条件来决定当前请求发到那个数据库中
2.主键处理,不能采用自增id,需要使用全局id.
3.由于同一个业务的数据被拆分到不同的数据库中,因此涉及到一些查询需要跨两个数据库获 取,如果数据量太大并且需要分页,就比较难处理了

3.2.10 数据库问题解决后,应用面对的挑战

前面讲的读写分离、分布式存储、数据垂直拆分和水平拆分都是解决数据方面的问题,接下 来我们要看看应用方面的变化 随着业务的发展,应用的功能会越来越多,应用也会越来越大,我们需要思考如何不让应用 持续变大,这就需要把应用拆开,从一个应用变为两个甚至是多个。 第一种方式 根据业务的特性把应用拆分,在我们的例子中,主要业务功能分三个部分、用户、商品、交 易。我们可以把原来的一个应用拆成分别以交易和商品为主的两个应用,对于交易和商品都 会有设计使用用户的地方,我们让这两个系统自己完成涉及用户的工作,而类似用户注册、 登录等基础的用户工作,可以暂时交给两个系统之一来完成。

分布式架构选型 分布式架构种类_数据库_08

4.0 服务化道路

我们在来看一下服务化的做法,我们把应用分为三层,处于最上端的是 web 系统,用于完成不同 的业务功能,处于中间的是一些服务中心,不同的服务中心提供不同的业务服务;处于最下层的则 是业务的数据库

分布式架构选型 分布式架构种类_服务器_09


与之前相比有几个重要的变化,首先业务功能之间的访问不仅仅是单机内部的方法调用,还引入了 远程的服务调用。其次,共享代码不再是散落在不同的应用中,这些实现被放在各个服务中心。最 后,数据库的连接也发生了一些变化,我们把数据库的交互工作放到了服务中心,让前端的web应 用更加注重与浏览器的交互工作,而不必过多关注业务逻辑的事情。链接数据库的任务交给响应的 业务服务中心了,这样可以降低数据库的连接数。 而服务中心不仅把一些可以共用的代码集中管理,而且还使得这些代码变得更好维护。 服务化的方式会带来很多好处,首先,从结构上来看,系统架构更加清晰了,比原本的架构 更加立体。从稳定性上来看,一些散落在多个应用系统中的代码变成了服务并且由专门的团队进行统一维护,一方面可以提高代码的质量,另一方面由于基础核心模块相对稳定,修改 和发布的频次相对于业务系统来说会少很多,这也会提高整个架构的稳定性。最后,更加底 层的资源由服务层统一管理,结构更加清晰,对于团队开发效率来说有比较大的提高 服务化的方式,对于研发也会有很大的影响,以前的开发模式是几个大团队负责几个大应用, 随着服务化的落地,我们的应用数量会飞速增长,系统内部的依赖关系也会变的错综复杂, 同时团队也进行了拆分,每个小团队专注于某个具体的服务或者应用上,迭代效率也会更高 。

5.什么是分布式架构

5.1分布式架构的定义

分布式是指网络计算机上的组件仅通过消息传递来进行通信和协调目标服务。
1.组件是分布在网络计算机上
2.组件之间是通过消息传递通信

5.2分布式的意义

1.升级单机处理能力的性价比越来越低
2.单机处理能力存在屏障
3.对于稳定性和可用性
过摩尔定律:
当价格不变时,每隔 18 个月,集成电路上课容纳的晶体管数量会增 加一倍,性能也会增加一倍。意味着随着时间的退役,单位成本的支出所能购买的计算能力 在提升,但是我们要求处理器的性能越高,所需要付出的成本也就越高。所以通过不断提升 单台机器的性能锁带来的产值是不划算的,同时,处理器本身也存在性能瓶颈。稳定性和可用性方面,在单机环境中是提供不了的。所以势必需要 分布式系统来解决