文章目录
1. 分布式系统
1.1 分布式系统概念
通俗的理解,所谓分布式系统,就是一个业务拆分成多个子业务,分布在不同的服务器节点,共同构成的系统称为分 布式系统,同一个分布式系统中的服务器节点在空间部署上是可以随意分布的,这些服务器可能放在不同的机柜中,也可能在不同的机房中,甚至分布在不同的城市。
1.2 分布式系统的特点
- 分布式
- 对等性
- 并发性
- 缺乏全局时钟
- 故障总是发生
1.3 分布式系统的发展
- 升级单机处理能力的性价比越来越低
- 单机处理能力存在瓶颈
- 稳定性和可用性这两个指标很难达到
1.4 分布式架构的演变
- 后端单应用架构(Back-End Single Application Architecture)这一概念有时用于描述一个集中式的后端服务设计,其核心思想是将后端系统设计为一个单一的应用程序或服务,而不是分布式的微服务架构。这种架构通常包括以下几个特点和考虑
后端单应用架构的特点
集中式应用:
后端单应用架构将所有的业务逻辑、数据处理、用户管理等功能集中在一个单一的应用程序中。所有的服务和功能都在同一个应用内运行,而不是分布在多个服务中。
统一的数据存储:
通常会使用一个集中式数据库来存储所有数据。这样可以简化数据管理和访问,避免了分布式数据库系统的复杂性。
简化的代码管理:
所有的业务逻辑和服务代码都在一个代码库中,减少了代码的分散和跨服务的协调复杂性。
单点部署:
只需部署和维护一个单一的应用程序实例,简化了部署和运维过程。
统一的技术栈:整个应用程序使用一致的技术栈和框架,避免了技术不兼容的问题。
应用服务器:
应用服务器是运行应用程序代码的地方。它负责处理业务逻辑、用户请求、数据处理、计算和其他应用层功能。应用服务器通常处理来自客户端的请求,执行必要的计算,然后将数据传递给数据库服务器。
数据库服务器:
数据库服务器专注于存储和管理数据。它执行数据的CRUD(创建、读取、更新、删除)操作,确保数据的完整性、一致性和安全性。数据库服务器通常提供高效的数据存取能力,并可能包括复杂的查询处理和事务管理功能。
将应用服务器与数据库服务器分离是一种常见的系统架构设计,具有显著的性能优化、可扩展性、安全性和维护便利性。虽然它可能带来一些网络延迟和架构复杂性的问题,但这些可以通过适当的网络设计、负载均衡和安全措施来缓解。在现代的高可用和高性能系统中,这种分离往往是实现灵活和可扩展架构的关键部分。
应用服务器集群是一种通过将多个应用服务器组成一个集群来提高应用系统的可用性、性能和扩展性的架构设计。集群中的应用服务器通过协同工作来处理用户请求,从而实现负载均衡、容错和可扩展性。
应用服务器集群的优点
- 性能提升:负载均衡:通过将用户请求分发到多个应用服务器节点,集群可以提高处理能力和响应速度,避免单一服务器的性能瓶颈。并行处理:多个节点可以并行处理请求,显著提升系统的处理能力和吞吐量。
- 高可用性:故障容错:即使部分节点出现故障,其他正常运行的节点可以继续处理请求,保证系统的高可用性。
- 故障恢复:集群通常配置有自动故障检测和恢复机制,能够自动检测节点故障并将流量重定向到健康的节点上。
- 可扩展性:水平扩展:可以通过添加更多的应用服务器节点来扩展系统的容量。这样可以根据需求动态调整集群的规模。灵活扩展:集群可以根据流量变化进行灵活的扩展和收缩,以适应业务的波动。
- 维护和升级:逐步升级:可以逐个节点进行维护和升级,而不会影响整个系统的可用性。用户请求可以自动转发到其他正常运行的节点上。
- 热部署:集群支持在不中断服务的情况下进行应用程序的热部署和升级。应用服务器集群的挑战
- 网络延迟:延迟增加:集群中的节点通过网络进行通信,可能会引入一定的网络延迟,特别是在高负载情况下。
- 数据一致性:同步问题:如果应用服务器节点之间需要共享状态或数据,可能会面临数据同步和一致性的问题。这需要额外的机制来保证数据的一致性。
- 复杂性管理:配置复杂:集群的配置和管理比单一应用服务器更复杂,需要管理负载均衡器、节点健康检查、故障恢复等多种组件。
- 监控和维护:需要对多个节点进行监控和维护,确保集群的稳定运行。
- 安全性:安全配置:集群中的多个节点需要一致的安全配置和策略,确保集群的整体安全性。这包括网络安全、数据加密和访问控制等方面。
应用场景
大规模Web应用:高流量的Web应用,如电子商务网站和社交媒体平台,通常使用应用服务器集群来处理大量的用户请求。
企业级应用:需要高可用性和高性能的企业级应用,如金融系统和大数据分析平台,适合使用应用服务器集群。
云服务和微服务架构:云服务和微服务架构中,应用服务器集群可以提供弹性和可扩展的服务支持。
应用服务器负载均衡器(Load Balancer)是一种重要的技术,用于在多个应用服务器之间分配用户请求,从而优化资源利用、提高系统的性能和可用性。负载均衡器可以是硬件设备、软件解决方案或云服务提供的功能,其主要作用是实现负载均衡和故障转移。
负载分配:
请求分发:负载均衡器将来自客户端的请求分发到集群中的不同应用服务器上,确保没有单一服务器承受过多的负载。
算法选择:负载均衡器使用不同的算法来分配请求,如轮询、加权轮询、最少连接、最少响应时间等,以优化请求分配。
Elasticsearch:一个开源的分布式搜索引擎,支持高效的全文搜索、实时数据分析和多种查询功能。
数据同步:
数据导入:将数据库中的数据导入到搜索引擎中。可以通过数据迁移工具、ETL(提取、转换、加载)过程或编写自定义脚本来实现。
实时同步:配置实时数据同步机制,以确保搜索引擎中的数据与数据库中的数据保持一致。例如,可以通过数据库触发器、消息队列(如Kafka)或数据变更日志(如Debezium)来实现实时同步。
在数据库设计和管理中,水平拆分和垂直拆分是用来优化性能和管理大型数据集的两种常见策略。它们有助于提高查询效率、分散负载、以及简化数据管理。下面是它们的具体概念和应用场景:
水平拆分(Horizontal Partitioning) 水平分表
水平拆分,也称为水平分区,是将数据库表的数据行按某种条件分割成多个子表。每个子表都包含原始表的一部分数据,但所有子表的结构相同。这种拆分方式可以帮助处理大规模数据,减少单个表的负载。
将一张表的数按照时间,分成不同的数据库
垂直拆分(Vertical Partitioning)垂直分表
垂直拆分是将数据库表的列按功能或访问频率分割成多个子表。每个子表都包含原始表的一部分列。这样做的目的是提高查询效率,减少I/O操作,并提高数据的缓存效率。
将数据库表根据字段来将数据库拆分为不同的表
水平分库
将一张数据库的数据,根据哈希分片分布到不同的数据库实例中
垂直分库
一个数据库分成不同的数据库实例,将数据库的不同列,分配到不同的数据库实例中
应用拆分 是一种将一个大型应用程序拆分成多个较小的、独立的应用程序或服务的策略。这种方法旨在提高应用程序的可维护性、可扩展性和灵活性。应用拆分通常有几种不同的形式,最常见的包括微服务架构、功能模块化、和服务拆分等。以下是关于应用拆分的详细介绍:
微服务架构(Microservices Architecture)
功能模块化(Modularization)
服务拆分(Service Splitting)
服务拆分(Service Splitting)是将一个大型应用程序拆分成多个独立的服务的过程,每个服务负责特定的业务功能或模块。这种方法有助于提高系统的可维护性、可扩展性、灵活性,并优化整体性能。服务拆分通常涉及到微服务架构,但也可以用于其他形式的服务划分。
假设有一个电子商务平台的应用程序,最初作为一个单体应用运行。可以将其拆分为以下服务:
用户服务:负责用户管理、注册、认证和授权。
订单服务:处理订单创建、更新和查询。
支付服务:处理支付处理和结算。
库存服务:管理商品库存和库存更新。
推荐服务:提供商品推荐和个性化服务。
通知服务:处理电子邮件、短信和推送通知。
每个服务可以独立开发、部署和扩展,服务之间通过API或消息队列进行通信。在实际使用中,系统需要处理跨服务的事务和数据一致性问题,同时确保服务的高可用性和性能。
2 分布式系统面临的问题
2.1 网络本身的不可靠
因此每次网络通信都会伴随着网络不可用的风险(光纤、路由、DNS等硬件设备或系统的不 可用),都会导致最终分布式系统无法顺利进行一次网络通信,另外,即使分布式系统各节点之间的网络通信能够 正常执行,其延时也会大于单机操作,存在巨大的延时差别,也会影响消息的收发过程,因此消息丢失和消息延迟
变的非常普遍。
分布式系统中,由于网络是不可靠的,虽然绝大部分情况下,网络通信能够接收到成功或失败的响应,但当网络出 现异常的情况下,就会出现超时现象,通常有以下两种情况: (没有发送和消费后没有接收)
- 由于网络原因,该请求并没有被成功的发送到接收方,而是在发送过程就发生了丢失现象。
- 该请求成功的被接收方接收后,并进行了处理,但在响应反馈给发送方过程中,发生了消息丢失现象。
2.1.1 请求过程中丢失
由于网络问题,发送方在请求发送过程中丢失了消息。即请求在发送过程中没有到达接收方。
- 重试机制,发送方可以在请求丢失后自动重试发送。重试机制应考虑到网络抖动和请求重复问题。
- 幂等性:确保请求的处理是幂等的,即多次处理相同的请求不会导致副作用。
- 确认机制,发送方等待接收方确认收到请求的响应,确保请求成功发送到接收方。
2.1.2 响应反馈过程中的丢失
- 确认机制:接收方在处理请求后,向发送方发送确认消息,确保发送方收到响应。
- 超时和重试:发送方在接收到响应前设定超时时间,并在超时后重试请求。
- 消息持久化,在消息传递系统中,确保消息在发送和接收过程中能够持久化存储,以防丢失。
- 事务管理:确保请求和响应的处理是事务性的,要么全部成功,要么全部失败。
2.2 网络分区
网络之间出现了网络不连通,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个 孤立的区域,分布式系统就会出现局部小集群,在极端情况下,这些小集群会独立完成原本需要整个分布式系统才
能完成的功能,包括数据的事务处理,这就对分布式一致性提出非常大的挑战。
2.3 节点故障
节点故障是分布式系统下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机或"僵死"现象,
根据经验来说,每个节点都有可能出现故障,并且经常发生.
3. 一致性
分布式数据一致性,指的是数据在多份副本中存储时,各副本中的数据是一致的。
3.1 副本一致性
分布式系统当中,数据往往会有多个副本。如果是一台数据库处理所有的数据请求,那么通过ACID四原则,基本 可以保证数据的一致性。而多个副本就需要保证数据会有多份拷贝。这就带来了同步的问题,因为我们几乎没有办 法保证可以同时更新所有机器当中的包括备份所有数据。 网络延迟,即使我在同一时间给所有机器发送了更新数据
的请求,也不能保证这些请求被响应的时间保持一致存在时间差,就会存在某些机器之间的数据不一致的情况。
总得来说,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。因此,如何既保证数据 的一致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。于是,一致性级别由此
诞生:
3.2 一致性分类
强一致性
这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往 对系统的性能影响大。但是强一致性很难实现。
弱一致性
这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致, 但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。
最终一致性
最终一致性 是分布式系统中一个重要的概念,指的是在系统中各个节点(或副本)在经过一段时间后,数据会趋向一致性,即所有的副本最终会达到一致的状态。最终一致性是一种放宽一致性要求的策略,常用于高可用性和扩展性需求较高的系统中。
最终一致性的实现方法
- 数据同步和复制,同步复制和异步复制:
- 冲突解决,基于时间戳解决: 使用时间戳来决定数据的版本。较新的时间戳的写入会覆盖较旧的时间戳的写入。
- 事务和补偿机制: 通过两阶段提交(2PC)或三阶段提交(3PC)等协议保证一致性。
- 数据一致性检查: 定期扫描系统中的数据副本,并进行一致性检查
- 事件驱动架构: 通过发布和订阅事件的机制来传播数据变化,确保所有副本都能收到更新
异步复制: 主节点处理写操作后,将数据异步地复制到从节点。这意味着写操作完成后,主节点不等待从节点的确认。
同步复制:主节点在完成写操作后,等待所有从节点确认数据已被写入
使用同步复制还是异步复制呢?
同步复制:强一致性,所有副本在写操作完成时都是一致的,确保数据的一致性。
写操作的延迟增加,因为需要等待所有副本的确认,可能影响系统的响应时间和吞吐量
异步复制: 在异步复制中,主节点在完成写操作后,不需要等待从节点的确认就返回操作结果。从节点在后台接收数据并更新。
写操作在主节点完成后立即返回,减少了写操作的延迟,提高了系统的响应时间。
使用混合模式对支付相关的数据使用同步复制,对日志相关的数据使用异步复制
4. CAP定理
CAP 理论含义是,一个分布式系统不可能同时满足一致性(C:Consistency),可用性(A: Availability)和分区容错 性(P:Partition tolerance)这三个基本需求,最多只能同时满足其中的2个。
C 一致性
分布式系统当中的一致性指的是所有节点的数据一致,或者说是所有副本的数据一致
A 可用性 Reads and writes
always succeed. 也就是说系统一直可用,而且服务一直保持正常
P 分区容错性
系统在遇到一些节点或者网络分区故障的时候,仍然能够提供满足一致性和可用性的服务
4.1 一致性
一致性是值写操作后读操作可以读到最新的数据状态,当数据分布在多个节点上时,从任意节点读取到的数据都是最 新的
- 商品服务写入主数据库成功, 则想从数据库查询数据也成功
- 商品服务写入主数据库失败,则向从数据库查询也失败
如何实现一致性? 、
1.写入主数据库后要数据同步到从数据库
2.写入主数据库后,在向从数据库同步期间要将从数据库锁定, 等待同步完成后在释放锁,以免在写新数据后,向从数据库查询到旧的数据.
分布式一致性的特点:
1.由于存在数据库同步过程,写操作的响应会有一定的延迟
2.为了保定数据的一致性,对资源暂时锁定,待数据同步完成后释放锁定资源
3.如果请求数据同步失败的节点则会返回错误信息, 一定不会返回旧数据.
4.1.1 数据同步的方式
使用同步复制:
双向确认机制,在主数据库写入操作完成后,等待从数据库的确认响应,以确保数据已经成功同步。
事务日志传输:主数据库将写操作记录到事务日志中,从数据库通过读取和重放这些日志来完成数据同步。
异步复制
主数据库完成写操作后,不等待从数据库的确认,直接返回操作结果。从数据库在后台接收数据并更新。
延迟处理:在主数据库完成写入后,异步地将数据变更传输到从数据库。
数据一致性检查:使用一致性检查工具定期确认主从数据库的同步状态。
4.1.2 在向从数据库同步期间锁定从数据库
锁定从数据库
在主数据库写入后,在数据同步到从数据库期间,锁定从数据库以防止新的写入操作,确保查询时数据的一致性。
使用数据库锁机制,使用读写分离,将读的操作转移到主库上面
使用“读一致性”或“快照隔离”
使用数据库的事务隔离级别或读一致性机制来避免读取到未同步的数据。
确保数据库的读取操作基于一致的快照,即使在数据同步期间也不会读取到未同步的数据。
事务隔离级别:配置数据库的事务隔离级别(如READ COMMITTED、REPEATABLE READ),以确保读取的数据的一致性。
4.2 可用性
可用性是指任何操作都可以得到响应的结果,且不会出现响应超时或响应错误。
商品信息读写要满足可用性需要实现如下目标:
1.从数据库接收到数据库查询的请求则立即能够响应数据查询结果
2.从数据库不允许出现响应超时或错误
- 主数据库想从数据库同步数据失败不形象写操作
- 其中一个节点挂掉不会影响另一个节点对外提供服务
尽量使用异步取代同步,这样节点之间能有效的实现松耦合,然后添加集群选举,节点挂掉就会自动提供服务
4.3 分区容忍性
分布式系统的各个节点部署在不同的子网中, 不可避免的会出现由于网络问题导致节点之间通信失败,此时仍可以对 外提供服务, 这个就是分区容错性 (分区容忍性).
商品信息读写要满足分区容错性需要实现如下目标:
- 主数据库想从数据库同步数据失败不形象写操作
- 其中一个节点挂掉不会影响另一个节点对外提供服务 如何实现分区容错性?
1.尽量使用异步取代同步操作,举例 使用异步方式将数据从主数据库同步到从数据库, 这样节点之间能有效的实现松 耦合;
2.添加数据库节点,其中一个从节点挂掉,由其他从节点提供服务
舍弃A(可用性),保留CP(一致性和分区容错性)
一个系统保证了一致性和分区容错性,舍弃可用性。也就是说在极端情况下,允许出现系统无法访问的情况出现,这个 时候往往会牺牲用户体验,让用户保持等待,一直到系统数据一致了之后,再恢复服务。
舍弃C(一致性),保留AP(可用性和分区容错性)
这种是大部分的分布式系统的设计,保证高可用和分区容错,但是会牺牲一致性。
舍弃P(分区容错性),保留CA(一致性和可用性)
如果要舍弃P,那么就是要舍弃分布式系统,CAP也就无从谈起了。可以说P是分布式系统的前提,所以这种情况是不存在 的。
5. BASE 理论
Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个 短语的缩写,来自 ebay 的架构师提出。
BASE是对CAP中一致性和可用性权衡的结果,BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可 以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
5.1 基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性——但请注意,这绝不等价于系统不可 用。以下就是两个"基本可用"的例子
响应时间上的损失:正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出 现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了1~2秒。
功能上的损失:正常情况下,在一个电子商务网站(比如淘宝)上购物,消费者几乎能够顺利地完成每一笔 订单。但在一些节日大促购物高峰的时候(比如双十一、双十二),由于消费者的购物行为激增,为了保护
系统的稳定性(或者保证一致性),部分消费者可能会被引导到一个降级页面
5.2 软状态
什么是软状态呢?相对于一致性,要求多个节点的数据副本都是一致的,这是一种 “硬状态”。 软状态指的是:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同
节点的数据副本之间进行数据同步的过程中存在延迟。
5.3 最终一致性
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此最终 一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
6. 分布式事务
我们知道事务有4个非常重要的特性,即我们常说的(ACID)。
Atomicity(原子性):是说事务是一个不可分割的整体,所有操作要么全做,要么全不做;只要事务中有一个操作 出错,回滚到事务开始前的状态的话,那么之前已经执行的所有操作都是无效的,都应该回滚到开始前的状态。
Consistency(一致性):是说事务执行前后,数据从一个状态到另一个状态必须是一致的,比如A向B转账(A、 B的总金额就是一个一致性状态),不可能出现A扣了钱,B却没收到的情况发生。
Isolation(隔离性):多个并发事务之间相互隔离,不能互相干扰。关于事务的隔离性,可能不是特别好理解, 这里的并发事务是指两个事务操作了同一份数据的情况;而对于并发事务操作同一份数据的隔离性问题,则是要求 不能出现脏读、幻读的情况,即事务A不能读取事务B还没有提交的数据,或者在事务A读取数据进行更新操作时, 不允许事务B率先更新掉这条数据。而为了解决这个问题,常用的手段就是加锁了,对于数据库来说就是通过数据 库的相关锁机制来保证。
Durablity(持久性):事务完成后,对数据库的更改是永久保存的。
6.1 什么是 2PC
2PC ( Two-Phase Commit缩写)即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit phase),2是指两个阶段,P是指准备阶段,C是指提交阶段。
在计算机中部分关系数据库如Oracle、MySQL支持两阶段提交协议.
两个阶段过程:
- 准备阶段(Prepare phase):事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事 务,并写本地的Undo/Redo日志,此时事务没有提交。 (Undo日志是记录修改前的数据,用于数据库回 滚,Redo日志是记录修改后的数据,用于提交事务后写入数 据文件)
- 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者
发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操
6.2 2PC执行流程
- 事务询问 协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
- 执行事务 (写本地的Undo/Redo日志)
- 各参与者向协调者反馈事务询问的响应,ACK 确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。
总结: 各个参与者进行投票是否让事务进行.
中断事务步骤如下
6.3 2PC 优点缺点
优点 原理简单,实现方便
缺点 同步阻塞,单点问题,数据不一致,过于保守
同步阻塞:
二阶段提交协议存在最明显也是最大的一个问题就是同步阻塞,在二阶段提交的执行过程中,所有参与该事务操作 的逻辑都处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,无法进行其他操作。这种同步阻
塞极大的限制了分布式系统的性能。
单点问题:
协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将无法运转,更重要的是:其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成事务操作。
数据不一致:
假设当协调者向所有的参与者发送 commit 请求之后,发生了局部网络异常或者是协调者在尚未发送完所有 commit 请求之前自身发生了崩溃,导致最终只有部分参与者收到了 commit 请求。这将导致严重的数据不一致问
题。
过于保守: 如果在二阶段提交的提交询问阶段中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息的话, 这时协调者只能依靠其自身的超时机制来判断是否需要中断事务,显然,这种策略过于保守。换句话说,二阶段提
交协议没有设计较为完善的容错机制,任意一个节点失败都会导致整个事务的失败。
7. 一致性协议 3PC
3PC,全称 “three phase commit”,是 2PC 的改进版,将 2PC 的 “提交事务请求” 过程一分为二,共形成了由 CanCommit、PreCommit和doCommit三个阶段组成的事务处理协议。
7.1 CanCommit
第一个阶段:
CanCommit
① 事务询问
协调者向所有的参与者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作,并开始等待 各参与者的响应。
② 各参与者向协调者反馈事务询问的响应
参与者在接收到来自协调者的包含了事务内容的canCommit请求后,正常情况下,如果自身认为可以顺利执行事
务,则反馈Yes响应,并进入预备状态,否则反馈No响应。
7.2 PreCommit
协调者在得到所有参与者的响应之后,会根据结果有2种执行操作的情况:执行事务预提交,或者中断事务 假如所有参与反馈的都是Yes,那么就会执行事务预提交。
① 发送预提交请求: 协调者向所有参与者节点发出preCommit请求,并进入prepared阶段。
② 事务预提交: 参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。
③ 各参与者向协调者反馈事务执行的结果:若参与者成功执行了事务操作,那么反馈Ack
若任一参与者反馈了No响应,或者在等待超时后,协调者尚无法接收到所有参与者反馈,则中断事务 2. 中断事务也分为2个步骤:
① 发送中断请求: 协调者向所有参与者发出abort请求。
② 中断事务:
无论是收到来自协调者的abort请求或者等待协调者请求过程中超时,参与者都会中断事务
7.3 do Commit
执行事务提交
① 发送提交请求:
进入这一阶段,假设协调者处于正常工作状态,并且它接收到了来自所有参与者的Ack响应,那么他将从预提交状 态转化为提交状态,并向所有的参与者发送doCommit请求。
② 事务提交:参与者接收到doCommit请求后,会正式执行事务提交操作,并在完成提交之后释放整个事务执行过程中占用的事 务资源。
③ 反馈事务提交结果:参与者在完成事务提交后,向协调者发送Ack响应。
④ 完成事务:协调者接收到所有参与者反馈的Ack消息后,完成事务。
中断事务
① 发送中断请求:协调者向所有的参与者节点发送abort请求。
② 事务回滚:参与者收到abort请求后,会根据记录的Undo信息来执行事务回滚,并在完成回滚之后释放整 个事务执行期间占用的资源。
③ 反馈事务回滚结果:参与者在完成事务回滚后,向协调者发送Ack消息。
④ 中断事务:协调者接收到所有参与者反馈的Ack消息后,中断事务。
- 协调者出现问题
- 协调者和参与者之间的网络故障
如果出现了任一一种情况,最终都会导致参与者无法收到 doCommit 请求或者 abort 请求,针对这种情况,参与者都会在等待超时之后,继续进行事务提交
7.4 2PC对比3PC
- 首先对于协调者和参与者都设置了超时机制(在2PC中,只有协调者拥有超时机制,即如果在一定时间内没有收 到参与者的消息则默认失败)
主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种 机制也侧面降低了整个事务的阻塞时间和范围。
-
通过CanCommit、PreCommit、DoCommit三个阶段的设 计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的 。
-
PreCommit是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。
问题:3PC协议并没有完全解决数据不一致问题。
8. 一致性算法 Paxos
Paxos算法是Lamport提出的一种基于消息传递的分布式一致性算法,使其获得2013年图灵奖。
Paxos这个名词几乎等同于分布式一致性。Google的很多大型 分布式系统都采用了Paxos算法来解决分布式一致性问题,如Chubby、Megastore以及Spanner等。开源的 ZooKeeper,以及MySQL 5.7推出的用来取代传统的主从复制的MySQL Group Replication等纷纷采用Paxos算法 解决分布式一致性问题。
然而,Paxos的最大特点就是难,不仅难以理解,更难以实现
8.1 Paxos 解决了什么问题
解决了分布式系统一致性问题。
8.2 Paxos相关概念
首先一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里
提案 (Proposal):Proposal信息包括提案编号 (Proposal ID) 和提议的值 (Value)
Client:客户端 客户端向分布式系统发出请求,并等待响应。例如,对分布式文件服务器中文件的写请求。
Proposer:提案发起者 提案者提倡客户请求,试图说服Acceptor对此达成一致,并在发生冲突时充当协调者以推动协议向前发展
Learners:最终决策的学习者 学习者充当该协议的复制因素
假设有一组可以提出提案的进程集合,那么对于一个一致性算法需要保证以下几点:
在这些被提出的提案中,只有一个会被选定
如果没有提案被提出,就不应该有被选定的提案。
当一个提案被选定后,那么所有进程都应该能学习(learn)到这个被选定的value
8.3 Paxos 的工作流程
1. 准备阶段(Prepare Phase):
提议者选择一个提议编号,并向多数接受者发送 “准备” 请求。
如果接受者收到准备请求,它必须响应一个承诺,表示它不会接受编号小于这个提议编号的提议。接受者还可能包含它已经接受的提议的编号和对应的值(如果有的话)。
2. 承诺阶段(Promise Phase):
接受者回应准备请求,承诺不接受任何编号小于请求编号的提议,并返回它之前接受的提议(如果有的话)。
3. 提议阶段(Propose Phase):
提议者在获得多数接受者的承诺后,向这些接受者发送提议请求,包含提议的值。提议的值可能是提议者初始提出的值,或者是接受者已经接受过的值(如果接受者已经接受了另一个提议)。
4. 接受阶段(Accept Phase):
接受者如果收到的提议请求的编号与它承诺的编号一致,就会接受这个提议,并通知提议者。
5. 学习阶段(Learn Phase):
一旦提议被多数接受者接受,该提议被认为是被选中的,并且结果会被通知给所有学习者。
Paxos 的关键特性
安全性(Safety):保证没有两个提议会被接受为不同的值。
活跃性(Liveness):如果大多数接受者都正常工作,那么最终会有一个提议被接受。
9. 一致性算法 Raft
9.1 什么是Raft 算法
是一种为了管理复制日志的一致性算法。
Raft将一致性算法分解成了3模块 1. 领导人选举 2. 日志复制 3. 安全性
Raft算法分为两个阶段,首先是选举过程,然后在选举出来的领导人带领进行正常操作,比如日志复制等。
9.2 领导人Leader选举
Raft 通过选举一个领导人,然后给予他全部的管理复制日志的责任来实现一致性。 在Raft中,任何时候一个服务器都可以扮演下面的角色之一:
领导者(leader):处理客户端交互,日志复制等动作,一般一次只有一个领导者
候选者(candidate):候选者就是在选举过程中提名自己的实体,一旦选举成功,则成为领导者
跟随者(follower):类似选民,完全被动的角色,这样的服务器等待被通知投票
Raft使用心跳机制来触发选举。当server启动时,初始状态都是follower。每一个server都有一个定时器,超时时 间为election timeout(一般为150-300ms),如果某server没有超时的情况下收到来自领导者或者候选者的任何
消息,定时器重启,如果超时,它就开始一次选举。
9.3 Raft选举过程
- 某一时刻,其中得一个follow由于没有由于没有收到 leader 的 heartbeat 率先发生 election timeout 进而发起选举。
- 只要集群中超过半数的节点接受投票,candidate 节点将成为即切换 leader 状态。
- 成为 leader 节点之后,leader 将定时向 follower 节点同步日志并发送 heartbeat。
9.4 节点异常
集群中各个节点的状态随时都有可能发生变化。从实际的变化上来分类的话,节点的异常大致可以分为四种类型:
leader 不可用; follower 不可用; 多个 candidate 或多个 leader;新节点加入集群。
9.5 leader 不可用
下面将说明当集群中的 leader 节点不可用时,raft 集群是如何应对的。
➢ 一般情况下,leader 节点定时发送 heartbeat 到 follower 节点。
由于某些异常导致 leader 不再发送 heartbeat ,或 follower 无法收到 heartbeat 。
当某一 follower 发生 election timeout 时,其状态变更为 candidate,并向其他 follower 发起投票。
当超过半数的 follower 接受投票后,这一节点将成为新的 leader,leader 的步进数加 1 并开始向 follower 同 步日志。
当一段时间之后,如果之前的 leader 再次加入集群,则两个 leader 比较彼此的步进数,步进数低的 leader 将 切换自己的状态为 follower。
较早前 leader 中不一致的日志将被清除,并与现有 leader 中的日志保持一致。
9.6 follower 节点不可用
follower 节点不可用的情况相对容易解决。因为集群中的日志内容始终是从 leader 节点同步的,只要这一节点再 次加入集群时重新从 leader 节点处复制日志即可
集群中的某个 follower 节点发生异常,不再同步日志以及接收 heartbeat。
经过一段时间之后,原来的 follower 节点重新加入集群。
这一节点的日志将从当时的 leader 处同步。
9.7 多个 candidate 或多个 leader
在集群中出现多个 candidate 或多个 leader 通常是由于数据传输不畅造成的。出现多个 leader 的情况相对少见, 但多个 candidate 比较容易出现在集群节点启动初期尚未选出 leader 的“混沌”时期。
初始状态下集群中的所有节点都处于 follower 状态。
两个节点同时成为 candidate 发起选举。
两个 candidate 都只得到了少部分 follower 的接受投票。
➢ candidate 继续向其他的 follower 询问。
由于一些 follower 已经投过票了,所以均返回拒绝接受
candidate 也可能向一个 candidate 询问投票
在步进数相同的情况下,candidate 将拒绝接受另一个 candidate 的请求
由于第一次未选出 leader,candidate 将随机选择一个等待间隔(150ms ~ 300ms)再次发起投票
如果得到集群中半数以上的 follower 的接受,这一 candidate 将成为 leader
稍后另一个 candidate 也将再次发起投票
9.8 日志复制(保证数据一致性)
日志复制的过程
Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中, 然后并行的向其他服务器发起 AppendEntries RPC复制日志条目。当这条日志被复制到大多数服务器上,Leader
将这条日志应用到它的状态机并向客户端返回执行结果。
客户端的每一个请求都包含被复制状态机执行的指令。
leader把这个指令作为一条新的日志条目添加到日志中,然后并行发起 RPC 给其他的服务器,让他们复制这 条信息。
跟随者响应ACK,如果 follower 宕机或者运行缓慢或者丢包,leader会不断的重试,直到所有的 follower 最终 都复制了所有的日志条目。
通知所有的Follower提交日志,同时领导人提交这条日志到自己的状态机中,并返回给客户端。
可以看到,直到第四步骤,整个事务才会达成。中间任何一个步骤发生故障,都不会影响日志一致性。