分布式理论

分布式理论

分布式系统定义

分布式系统可以简单地概括为

分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。

通俗的理解,所谓分布式系统,就是一个业务拆分成多个子业务,分布在不同的服务器节点,共同构成的系统称之为分布式系统,同一个分布式系统中的服务器节点在空间部署上是可以随意分布的,这些服务器可能放在不同的机柜中,也有可能在不同的机房中,甚至分布在不同的城市。

为什么要构建分布式系统?

类比一下,分布式系统就是一群人一起干活,人多力量大。每个服务器的算力是有限的,但是通过分布式系统,由n个服务器组起来的集群,算力是可以无限扩张的。

分布式环境下的存在问题

通信异常

分布式系统需要在各个节点之间进行通信,通信必然引入网络因素,由于网络本身的不可靠性,因此每次网络通信都会伴随着网络不可用的风险(光纤、路由、DNS等硬件设备或者系统的不可用),都会导致最终分布式系统无法顺利进行一次网络通信。另外,即使分布式系统各节点之间的网络通信能够正常执行,其延时也会大于单机操作,存在巨大的延时差别,也会影响消息的收发过程,因此消息丢失和消息延迟变得非常普遍。

网络分区

由于网络发生异常情况,导致分布式系统中部分节点之间的网络延迟不断增大,最终导致组成分布式系统中只有部分节点能够进行正常通信,而另外一些节点则不能,这种情况为网络分区,也就是俗称的“脑裂”。

当出现网络分区时,网络之间出现了网络不连通,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分开了若干个孤立的区域,分布式系统就会出现局部小集群。在极端情况下,这些小集群会独立完成原本需要整个分布式系统才能完成的功能,包括数据的事务处理,这就对分布式一致性提出非常大的挑战。

三态

从上面的介绍,已经了解到了在分布式环境下,网络可能会出现各种各样的问题,因此分布式系统每一次请求和响应存在特有的“三态”概念,即成功、失败、超时。

在传统的单机系统中,应用程序调用一个方法后,能后得到非常明确的响应:成功或失败,而在分布式系统中,由于网络是不可靠的,虽然绝大部分情况下,网络通信能够接收到成功或失败的响应,但当网络出现异常的情况下,就会出现超时现象,通常有以下两种情况:

  • 由于网络原因,该请求没有被成功的发送到接收方,而是在发送过程就发送了丢失现象
  • 改请求成功的被接收方接收后,并进行了处理,但在响应的过程中,发生了消息丢失现象

节点故障

节点故障是分布式系统下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机或僵死现象,根据经验来说,每个检点都有可能出现故障,并且经常发生

一致性概念

分布式一致性是一个相当重要且被广泛探索与论证的问题,首先来看三种业务场景

  • 火车站售票

    假如我们的用户是一位经常坐火车的旅行家,通常他是去车站的售票处购买车票,然后拿着车票去检票口检票上车。

    想象一下,如果他选择的目的地是深圳,而某一趟开往深圳的火车只剩下最后一张票,可能在同一时间,不同的售票窗口的另一位乘客也购买了这一张车票。假如说售票系统没有进行一致性的保障,两个人都买到了这张票,然而在检票的时候,其中一个乘客就会没有座位,这是该业务场景下不能接受的。

    该场景下,对售票系统需要严格的一致性要求 —— 系统的数据,无论在哪个售票窗口,每时每刻都必须是准确无误的。

  • 银行转账

    假如我们的业务是银行转账系统,汇款人在到银行转账时,有可能会存在 转账将在N个工作日内到账。

  • 网上购物

    对于电商平台,当我们看见一件库存为5的商品时,我们开始下单购买,在下单的一瞬间,系统可能会告知用户,库存量不足。此时绝大部分消费者都会抱怨自己动作太慢,但其实页面上显示的那个库存量,并不一定是商品的真实库存量,只有在真正下单购买的时候,系统才会检查该商品的真实库存量。

案例解读:

对于上面的三个案例,我们发现,业务对数据一致性的需求是不一样的:

  1. 有些系统,既需要快速地响应用户,同时还要保证系统的数据对于任意客户端都是真实可靠的,就像火车站售票系统
  2. 有些系统,需要为用户保证绝对可靠的数据安全,虽然在数据一致性上存在延时,但最终保证严格的一致性,就像银行的转账系统
  3. 有些系统,虽然向用户展示了一些“错误”的数据,但是在整个系统使用过程中,一定会在某个流程上对系统数据进行准确无误的检查,从而避免用户发生不必要的损失,就像网购系统

分布式一致性的提出

在分布式系统中要解决的一个重要问题就是数据的复制。

在我们的日常开发中,如果我们使用了MySQL主从配置,有可能存在客户端A将数据库的值由V1修改为V2,此时在客户端B无法读取到V的最新值,需要一段时间之后才能读到。这就是常见的数据库之间复制的延时问题。

分布式理论
分布式系统对于数据的复制需求一般都来自于以下两个原因:

  1. 为了增加系统的可用性,以防止单点故障引起的系统不可用
  2. 提高系统的整体性能,通过负载均衡技术,能够让分布在不同地方的数据副本都能为用户提供服务

数据复制在可用性和性能方面给分布式系统带来的巨大好处是不言而喻的,然而数据复制所带来的一致性挑战,也是每一个开发人员不得不面对的。

所谓分布式一致性问题,是指在分布式环境中引入数据复制机制之后,不同数据节点之间可能出现的、并无法依靠计算机应用程序自身解决的数据不一致的情况。

简单讲,数据不一致就是指在对一个副本数据进行更新的时候,必须确保也能够更新其他的副本,否则不同的副本之间的数据将不一致。

那么如何解决分布式数据不一致的问题?

既然是由于延时动作引起的问题,那么我们可以将写入的动作阻塞,知道数据复制完成后,才完成写入动作。这似乎能解决问题,一些系统的架构也确实是这样做的。但是这个思路在解决数据一致性的问题的同时,又带来了新的问题:写入的性能。如果你的应用场景有非常多的写性能,那么应用这个思路后,所有的请求都会阻塞在前一个请求的写操作上,导致系统整体性能急剧下降。

总的来说,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。因此,如何既保证数据的一致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。

于是,一致性级别由此诞生:

强一致性

这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来也会是什么,用户体验好,但实现起来往往对系统的性能影响大

弱一致性

这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到在某个时间级别后(比如秒级别),数据能够达到一致状态

最终一致性

最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型。

分布式事务

在单机数据库中,我们很容易能够实现一套满足ACID特性的事务处理系统,但在分布式数据库中,根据分散在各台不同的机器上,如何对这些数据进行分布式的事务处理具有非常大的挑战

分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点上,通常一个分布式事务中会涉及对多个数据源或业务系统的操作。

可以设想一个典型的分布式事务场景:

一个异地转账操作涉及调用两个异地的银行服务,其中一个是本地银行提供的取款服务,另一个则是异地银行提供的存款服务,这两个服务本身是无状态并且相互独立的,共同构成了一个完整的分布式事务。如果从本地银行扣款成功,但是因为某种原因存款服务失败了,那么就必须回滚到取款之前的状态,否则用户可能会发现自己的钱不翼而飞了。

从这个例子可以看到,一个分布式事务可以看作是多个分布式的操作序列组成的,例如上面例子的取款服务和存款服务,通常可以把这一系列分布式的操作成为子事务。因此,分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务特性。

但由于在分布式事务中,各个子事务的执行是分布式的,因此要实现一种能保证ACID特性的分布式事务处理系统就显得格外复杂,尤其是对于一个高并发的互联网分布式系统来说,如果我们期望实现一套满足ACID特性的分布式事务,很可能出现的情况就是在系统的可用性和严格一致性之间出现冲突。因为当我们要求分布式系统具有严格一致性时,很可能就需要系统的可用性。但毋庸置疑的一点是,可用性又是一个消费者不允许我们讨价还价的系统属性,比如淘宝这样的网站,就要求7*24小时不间断地对外提供服务,而对于一致性,则更加是所有消费者对于一个软件的刚需。

因此,在可用性和一致性之间永远无法存在一个两全其美的方案,于是如何构建一个兼顾可用性和一致性的分布式系统成为了无数开发人员探讨的难题,于是就出现了CAP和BASE这样的分布式经典理论。