目录
随着计算机系统规模变得越来越大,将所有的业务单元集中部署在一个或若干个大型机上的体系结构,已经越来越不能满足当今计算机系统,分布式的处理方式越来越受到业界的青睐——计算机系统正经历从集中式向分布式架构的变革。
1.分布式的特点
- 分布性:分布式系统中的多台计算机都会在空间上随意分布,同时机器的分布状况也会随时变动。
- 对等性:分布式系统中的计算机没有主从之分,即没有控制整个系统的主机,也没有被控制的从机,组成分布式系统的所有计算机节点都是对等的。
- 并发性:在一个计算机网络中,程序运行过程中的并发性操作是非常常见的行为,例如同一个分布式系统中的多个节点,可能会并发地操作一些共享的资源,诸如数据库或者分布式存储等。
- 缺乏全局时钟:一个典型的分布式系统是由一系列在空间上随意分布的多个进程组成的,具有明显的分布性,这些进程之间通过交换信息来进行相互通信。因此,在分布式系统中,很难定义两个事件究竟谁先谁后,原因就是因为分布式系统缺乏一个全局的时钟序列控制。
- 故障总是会发生:组成分布式系统的所有计算机,都有可能会发生任何形式的故障。
2.分布式环境的各种问题
分布式环境中存在一些典型的问题:
- 通信异常:分布式系统需要在各个节点之间进行网络通信,因此每次网络通信都会伴随着网络不可用的风险,网络光纤、路由器或是DNS等硬件设备或者是系统不可用都会导致最终分布式系统无法顺利完成一次网络通信。即使分布式系统各节点之间的网络通信能够正常进行,其延时也会远远大于单机操作。
- 网络分区:当网络由于发生异常情况,导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式系统的所有节点中,只有部分节点之间能够进行正常通信,而另外一些节点则不能,这个现象称为网络分区,俗称“脑裂”。
- 三态:分布式系统中的每一次的请求与响应,存在特有的“三态”概念,即成功、失败和超时。
- 节点故障:组成分布式系统的服务器节点出现的宕机或者“僵死”现象。
3.事务
3.1 ACID特性
事务是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元,狭义的事务特指数据库事务。一方面,当多个应用程序并发访问数据库时,事务可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。另外一方面,事务为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持数据一致性的方法。事务具有四个特征:原子性,一致性,隔离性和持久性。事务的ACID特性如下图所示:
3.2 分布式事务
在单机数据库中,我们很容易实现一个满足ACID特性的事务处理系统,但是在分布式的数据库中,数据分散在各个不同的机器上,如何对这些数据进行分布式的事务处理具有非常大的挑战,比如前面说到的机器宕机和各种网络异常问题等。
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及到对多个数据源或业务系统的操作。例如,一个跨银行的转账操作涉及调用两个异地的银行服务,其中一个是本地银行提供的取款服务,另一个是目标银行提供的存款服务,这两个服务本身是无状态并且是互相独立的,共同构成了一个完整的分布式事务。如果从本地银行取款成功,但是因为某种原因存款服务失败了,那么就必须回滚到取款前的状态,否则用户可能会发现自己的钱不翼而飞。一个分布式事务可以看作是由多个分布式的操作序列组成的,例如上面举例中的取款服务和存款服务,通常可以把这一系列分布式的操作序列称为子事务。
4.CAP和BASE理论
4.1 CAP定理
CAP理论告诉我们,一个分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Available)和分区容错性(P:Partition Tolerance)这三个基本需求,最多只能同时满足其中的两项。CAP定理的示意图如下所示:
- 一致性:在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。例如一个将数据副本分布在不同分布式节点上的系统来说,如果对第一个节点的数据进行了更新操作并且更新成功后,其他节点上的数据也应该得到更新,并且所有用户都可以读取到其最新的值,那么这样的系统就被认为具有强一致性(或严格的一致性)。
- 可用性:可用性是指系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。“有效的时间内”是指,对于用户的一个操作请求,系统必须能够在指定的时间(即响应时间)内返回对应的处理结果,如果超过了这个时间范围,那么系统就被认为是不可用的。“返回结果”是可用性的另一个非常重要的指标,它要求系统在完成对用户请求的处理后,返回一个正常的响应结果。正常的响应结果通常能够明确的反映出对请求的处理结果,即成功或失败,而不是一个让用户感到困惑的返回结果。
- 分区容错性:分区容错性约束了一个分布式系统需要具有如下特性:分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。网络分区是指在分布式系统中,不同的节点分布在不同的子网络(机房或异地网络等)中,由于一些特殊的原因导致这些子网络之间出现网络不连通的状况,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个孤立的区域。需要注意的是,组成一个分布式系统的每个节点的加入与退出都可以看作是一个特殊的网络分区。
由于一个分布式系统无法同时满足上面的三个需求,而只能满足其中的两项,因此在进行对CAP定理的应用的时候,需要根据业务的要求抛弃其中的一项。CAP定理示意图如下:
另外一方面需要明确地一点是,对于一个分布式系统而言,分区容错性是一个最基本的要求,因为既然是一个分布式系统,那么分布式系统中的组件必然需要被部署到不同的节点,因此必然会出现子网络,也就是说网络问题是一个必然会出现的问题,所以分区容错性也就成为了一个分布式系统必然需要面对和解决的问题,
4.2 BASE理论
BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写。BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当地方式来使系统达到最终一致性。
- 基本可用:基本可用是指分布式系统在出现不可预知的故障时候,允许损失部分可用性,但这绝不等价于系统不可用。比如出现故障时,部分请求的响应时延延长;大促购物高峰时,触发限流等。
- 弱状态:指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同的数据副本之间进行数据同步的过程存在时延。
- 最终一致性:最终一致性强调的是系统中所有的数据副本,经过一段时间的同步之后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
在实际工程实践中,最终一致性存在以下五类主要变种:
- 因果一致性:因果一致性是指如果进程A在更新完某个数据项后通知了进程B,那么进程B之后对该数据项的访问都应该能够获取到进程A更新后的最新值,即不能发生丢失更新的情况。与此同时,与进程A没有因果关系的进程C的数据访问则没有这样的限制。
- 读己之所写:进程A更新一个数据项之后,它自己总是能够访问到更新过的最新值,而不会看到旧值。因此,读己之所写也可以看作是一种特殊的因果一致性。
- 会话一致性:会话一致性将对系统数据的访问过程框定在了一个会话当中:系统能保证在同一个有效的会话中实现“读己之所写”的一致性,也就是说,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。
- 单调读一致性:如果一个进程从系统中读取出一个数据项的某个值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值。
- 单调写一致性:一个系统能够保证来自同一个进程的写操作被顺序地执行。
以上就是最终一致性的五种常见的变种,在实际系统实践中,可以将其中的若干个变种互相结合起来,以构建一个具有最终一致性特性的分布式系统。总的来说,BASE理论面向的是大型高可用可扩展的分布式系统,它完全不用于ACID的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
5.常用注册中心
目前主流注册中心产品如下图所示:
5.1 Zookeeper
Zookeeper在设计时遵循CP原则,但ZK并不能提供强一致性的服务,提供的只是单调一致性。因为在同步流程中,leader向follower同步数据时,当同步完成的follower数量大于n+1时同步流程结束。如果client连接的并非同步完成的follower,那么得到的并非最新数据,但可以保证单调性。ZK不保证A(可用性),因此会存在以下几个可用性问题:
- 节点多了会导致写数据延时非常大,因为需要多个节点同步
- 节点多了Leader选举非常耗时(30s-120s都有可能),而Leader选举过程中不对外提供服务,就会放大网络问题,最终ZK通过加入Observer节点来缓解这个问题
在服务发现的场景中,对于服务消费者来说,能拿到服务提供者才是最重要的,消费者可以拿到可能不正确的服务实例信息后尝试消费一下,也要胜过因为无法获取服务提供者导致系统异常要好。在云部署环境下,因为网络问题使得ZK集群失去master节点是大概率事件,虽然服务能最终恢复,但是漫长的选举时间导致注册服务长期不可用是不能容忍的,因此ZK不适合做服务发现。
5.2 Eureka
Spring Cloud Netflix在设计Eureka时就谨遵AP原则,尽管目前2.0已经闭源了,但是1.X仍然是比较活跃的。
Eureka可以运行多个实例来构建集群,解决单点问题,但不同于ZK的选举Leader的过程,Eureka采用的是Peer to Peer(组播)对等通信。这是一种去中心化的架构,无master/slave之分,每一个Peer都是对等的。Eureka的集群中,只要有一台Eureka存在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的。
5.3 Consul
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X)。
Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。
Consul强一致性(C)带来的问题:
- 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认为注册成功
- Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性
5.4 Nacos
Nacos是阿里开源的,Nacos 支持基于 DNS 和基于 RPC 的服务发现。在Spring Cloud中使用Nacos,只需要先下载 Nacos 并启动 Nacos server,Nacos只需要简单的配置就可以完成服务的注册发现。
Nacos除了服务的注册发现之外,还支持动态配置服务。动态配置服务可以让你以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
一句话概括就是Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。