说分布式系统必须要说集中式系统,集中式系统中整个项目就是一个独立的应用,整个应用也就是整个项目,所有的东西都在一个应用里面。
如一个网站就是一个应用,最后是多个增加多台服务器或者多个容器来达到负载均衡的避免单点故障的目的,当然,数据库是可以分开部署的。
集中式很明显的优点就是开发测试运维会比较方便,不用为考虑复杂的分布式环境。
集中式很明显的弊端就是不易扩展,每次更新都必须更新所有的应用。而且,一个有问题意味着所有的应用都有问题。当系统越来越大,集中式将是系统最大的瓶颈。
为了解决集中式系统的问题,分布式系统应运而生。
分布式系统是若干独立计算机的集合,这计算机对用户来说就像单个相关系统。也就是说分布式系统背后是由一系列的计算机组成的,但用户感知不到背后的逻辑,就像访问单个计算机一样。
分布式系统利弊:
在分布式系统中:
1、应用可以按业务类型拆分成多个应用,再按结构分成接口层、服务层;我们也可以按访问入口分,如移动端、PC端等定义不同的接口应用;
2、数据库可以按业务类型拆分成多个实例,还可以对单表进行分库分表;
3、增加分布式缓存、搜索、文件、消息队列、非关系型数据库等中间件;
很明显,分布式系统可以解决集中式不便扩展的弊端,我们可以很方便的在任何一个环节扩展应用,就算一个应用出现问题也不会影响到别的应用。随着微服务Spring Cloud & Docker的大热,及国内开源分布式Dubbo框架的重生,分布式技术发展非常迅速。分布式系统虽好,也带来了系统的复杂性,如分布式事务、分布式锁、分布式session、数据一致性等都是现在分布式系统中需要解决的难题,虽然已经有很多成熟的方案,但都不完美。分布式系统也增加了开发测试运维成本,工作量增加,分布式系统管理不好反而会变成一种负担。
简单的说,微服务架构是架构设计方式,它强调的是单体服务的拆分;分布式是系统部署方式,它强调的是多台计算机部署,两者概念不同。而微服务指的是小而精干的服务,是微服务架构的产物。
使用微服务架构开发的程序大多是采用分布式部署的,而分布式部署的应用不一定是微服务架构应用,比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。
从集中式向分布式演变的过程中,必然引入网络因素,由于网络本身的不可靠性,因此也引入了额外的问题。分布式系统需要在各个节点之间进行网络通信,因此每次网络通信都会伴随着网络不可用的风险,网络光纤、路由器或是DNS等硬件设备或是系统不可用都会导致最终分布式系统无法顺利完成一次网络通信。另外,即使分布式系统各个节点之间的网络通信能够正常进行,其延时也会大于单机操作。通常我们认为现代计算机体系结构中,单机内存访问的延时在纳秒数量级(通常是10ns),而正常的一次网络通信的延迟在0.1~1ms左右(相当于内存访问延时的105倍),如此巨大的延时差别,也会影响到消息的收发过程,因此消息丢失和消息延迟变得非常普遍。
当网络由于发生异常情况,导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式系统的所有节点中,只有部分节点之间能够正常通信,而另一些节点则不能,我们将这个现象称为网络分区故障。当出现网络分区时,分布式系统会出现局部小集群,在极端情况下,这些局部小集群会独立完成原本需要整个分布式系统才能完成的功能,包括对数据的事物处理,这就对分布式一致性提出了非常大的挑战。
上面两点,我们已经了解到在分布式环境下,网络可能会出现各式各样的问题,因此分布式系统的每一次请求与响应,存在特有的三态概念,即成功、失败、超时。 在传统的单机系统中,应用程序在调用一个函数之后,能够得到一个非常明确的响应:成功或失败。而在分布式系统中,由于网络是不可靠的,虽然在绝大部分情况 下,网络通信也能够接受到成功或失败的响应,当时当网络出现异常的情况下,就可能会出现超时现象,通常有以下两种情况:
(1)由于网络原因,该请求并没有被成功地发送到接收方,而是在发送过程中就发生了消息丢失现象;
(2)该请求成功地被接收方接收后,进行了处理,但是在将响应反馈给发送方的过程中,发生了消息丢失现象。
当出现这样的超时现象时,网络通信的发起方是无法确定当前请求是否被成功处理的。
节点故障则是分布式环境下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机或"僵死"现象,通常根据经验来说,每个节点都有可能出现故障,并且每天都在发生。
在分布式系统中, 出于以下两个原因,必须引入数据复制机制,即多数据库储存:
而在引入数据复制机制后,与集中式系统不同的是,分布式系统不同节点之间是通过网络进行数据传输和交流的,而网络是有延时的,所以要保证所有数据库中数据的一致性是比较困难的。
那么如何解决这个问题呢?
一种思路是"既然是由于延时动作引起的问题,那我可以将写入的动作阻塞,直到数据复制完成后,才完成写入动作"。 没错,这似乎能解决问题,满足了数据强一致性的要求,而且有一些系统的架构也确实直接使用了这个思路。但这个思路在解决一致性问题的同时,又带来了新的问题:写入的性能。如果你的应用场景有非常多的写请求,那么使用这个思路之后,后续的写请求都将会阻塞在前一个请求的写操作上,导致系统整体性能急剧下降。
总得来说,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。因此,如何既保证数据的一致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。于是,一致性级别由此诞生:
1、强一致性
这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大。
2、弱一致性
这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不久承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。
3、最终一致性
最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型。
在分布式系统中,因为数据分散在各台不同的机器上,如何对这些数据进行分布式的事务处理具有非常大的挑战。
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点上,通常一个分布式事务中会涉及对多个数据源或业务系统的操作。
例如:一个跨银行的转账操作涉及调用两个异地的银行服务,其中一个是本地银行提供的取款服务,另一个则是目标银行提供的存款服务,这两个服务本身是无状态并且相互独立的,共同构成了一个完整的分布式事务。如果从本地银行取款成功,但是因为某种原因存款服务失败了,那么就必须回滚到取款之前的状态,否则用户可能会发现自己的钱不翼而飞了。
从这个例子可以看到,一个分布式事务可以看做是多个分布式的操作序列组成的,例如上面例子的取款服务和存款服务,通常可以把这一系列分布式的操作序列称为子事务。因此,分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了 ACID事物特性。但由于在分布式事务中,各个子事务的执行是分布式的,因此要实现一种能够保证ACID特性的分布式事务处理系统就显得格外复杂。
上面提到了构建一个分布式系统遇到种种问题,为了更好的解决这些问题,提出了一些指导性的理论。
指的是在一个分布式系统中,**强一致性(Consistency)、高可用性(Availability)、分区容错性(Partition tolerance)**这三个要素最多只能同时实现两点,不可能三者兼顾。
强一致性(Consistency): 在分布式环境下,一致性是指数据在多个副本之间能否保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。
高可用性(Availability): 可用性是指系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。这里的重点是"有限时间内"和"返回结果"。
"有限时间内"是指,对于用户的一个操作请求,系统必须能够在指定的时间内返回对应的处理结果,如果超过了这个时间范围,那么系统就被认为是不可用的。另外,"有限的时间内"是指系统设计之初就设计好的运行指标,通常不同系统之间有很大的不同,无论如何,对于用户请求,系统必须存在一个合理的响应时间,否则用户便会对系统感到失望。
"返回结果"是可用性的另一个非常重要的指标,它要求系统在完成对用户请求的处理后,返回一个正常的响应结果。正常的响应结果通常能够明确地反映出队请求的处理结果,即成功或失败,而不是一个让用户感到困惑的返回结果。
分区容错性(Partition tolerance): 分区容错性约束了一个分布式系统具有如下特性:分布式系统在遇到任何网络分区故障的时候,剩下的网络分区仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
需要明确的一点是, 对于一个分布式系统而言, 分区容错性是一个最基本的要求。因为既然是一个分布式系统,那么分布式系统中的组件必然需要被部署到不同的节点,否则也就无所谓分布式系统了,因此必然出现子网络。而对于分布式系统而言,网络问题又是一个必定会出现的异常情况,因此分区容错性也就成为了一个分布式系统必然需要面对和解决的问题,所以CAP中的P(分区容错性)是必须要保证的,因此大多数的分布式系统都是CP或者AP系统,但是我们往往希望C和A之间能够有一种调和,让他们基本得到满足,因此eBay的架构师提出了BASE理论:
Basically Available(基本可用),Soft State(软状态)和Eventually Consistent(最终一致性)三个短语的缩写。
Basically Available(基本可用): 假设系统出现了不可预知的故障,但还能用,只不过相比较正常的系统而言在响应时间和功能上有一些损失。
Soft State(软状态):CAP理论中的C要求多个节点的数据副本必须保持一致,这是一种“硬状态”,而Soft State 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
Eventually Consistent(最终一致性):数据的软状态不可能一直保持,必须有一个时限,在时限过后,应当保证所有副本的数据保持一致性。这个时限取决于网络延时、系统负载、数据复制方案等因素。
BASE理论总的来说,就是牺牲了强一致性来获得可用性,允许数据有中间态,并在时限内完成最终一致性。但同时, 在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此在具体的分布式系统架构设计过程中,ACID特性和BASE理论往往又会结合在一起。