# 分布式理论


<!--more-->

## 1.数据一致性

- 分布式数据一致性

  分布式数据一致性，指的是数据在多份副本中存储时，各**副本**中的数据是一致的。 

- 副本一致性

  布式系统当中，数据往往会有多个副本。多个副本就需要保证数据的一致性。这就带来了同步的问题，因为网络延迟等因素, 我们几乎没有办法保证可以同时更新所有机器当中的包括备份所有数据. 就会有数据不一致的情况

  ![img_4](https://img.zhaojq.top/20260727092007373.png "img_4")

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

- 一致性分类

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

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

  3. 最终一致性
    **最终一致性也是弱一致性的一种**，它无法保证数据更新后，所有后续的访问都能看到最新数值，而是需要一个时间，在这个时间之后可以保证这一点（就是在一段时间后，节点间的数据会最终达到一致状态），而在这个时间内，数据也许是不一致的，这个系统无法保证强一致性的时间片段被称为「**不一致窗口**」。不一致窗口的时间长短取决于很多因素，比如备份数据的个数、网络传输延迟速度、系统负载等。

    > 最终一致性在实际应用中又有多种变种：
    >
    > - 因果一致性
    >   如果进程A通知进程B它已更新了一个数据项，那么进程B的后续访问将返回更新后的值。与进程A无因果关系的进程C的访问遵守一般的最终一致性规则
    >
    >   ![img_5](https://img.zhaojq.top/20260727092007576.png "img_5")
    >
    > - 读己之所写一致性
    >   当进程A自己更新一个数据项之后，它总是访问到更新过的值，绝不会看到旧值。这是因果一致性模型的一个特例。
    >
    >   ![img_6](https://img.zhaojq.top/20260727092007744.png "img_6")
    >
    > - 会话一致性
    >   它把访问存储系统的进程放到会话的上下文中。只要会话还存在，系统就保证"读己之所写"一致性。如果由于某些失败情形令会话终止，就要建立新的会话，而且系统的保证不会延续到新的会话。
    >
    >   ![img_7](https://img.zhaojq.top/20260727092007916.png "img_7")
    >
    > - 单调读一致性
    >   如果一个进程已经读取到一个特定值，那么该进程不会读取到该值以前的任何值。
    >
    > - 单调写一致性
    >   系统保证对同一个进程的写操作串行化。
    >
    >   ![img_8](https://img.zhaojq.top/20260727092008130.png "img_8")

  4. 一致性模型图

    ![img_9](https://img.zhaojq.top/20260727092008405.png "img_9")

## 2.CAP定理

### 2.1 cap定理介绍

CAP定理（CAP theorem），又被称作布鲁尔定理（Brewer's theorem），它指出对于一个分布式计算系统来说，不可能同时满足以下三点 

| 选项                              | 具体意义                                                     |
| --------------------------------- | ------------------------------------------------------------ |
| 一致性（Consistency）             | 所有节点访问时都是同一份最新的数据副本                       |
| 可用性（Availability）            | 每次请求都能获取到非错的响应，但是不保证获取的数据为最新数据 |
| 分区容错性（Partition tolerance） | 分布式系统在遇到任何网络分区故障的时候，仍然能够对外提供满足一致性和可用性的服务，除非整个网络环境都发生了故障 |

- 一致性Consistency

  这里指的是强一致性
  在写操作完成后开始的任何读操作都必须返回该值，或者后续写操作的结果. 也就是说，在一致性系统中，一旦客户端将值写入任何一台服务器并获得响应，那么之后client从其他任何服务器读取的都是刚写入的数据 

  >  ![img_10](https://img.zhaojq.top/20260727092008589.png "img_10")
  >
  > - 客户端向G1写入数据v1，并等待响应
  > - 此时，G1服务器的数据为v1，而G2服务器的数据为v0，两者不一致
  > - 接着，在返回响应给客户端之前，G2服务器会自动同步G1服务器的数据，使得G2服务器的数据也是v1
  > - 一致性保证了不管向哪台服务器（比如这边向G1）写入数据，其他的服务器（G2）能实时同步数据
  > - G2已经同步了G1的数据，会告诉G1，我已经同步了
  > - G1接收了所有同步服务器的已同步的报告，才将"写入成功"信息响应给client
  > - client再发起请求，读取G2的数据
  > - 此时得到的响应是v1，即使client读取数据到G2

- 可用性（A-Availability)

  系统中非故障节点收到的每个请求都必须有响应. 在可用系统中，如果我们的客户端向服务器发送请求，并且服务器未崩溃，则服务器必须最终响应客户端，不允许服务器忽略客户的请求 

- 分区容错性（P-Partition tolerance）

  允许网络丢失从一个节点发送到另一个节点的任意多条消息，即不同步. 也就是说，G1和G2发送给对方的任何消息都是可以放弃的，也就是说G1和G2可能因为各种意外情况，导致无法成功进行同步，分布式系统要能容忍这种情况。

### 2.2 CAP三者不可能同时满足论证

假设确实存在三者能同时满足的系统

1. 那么我们要做的第一件事就是分区我们的系统，由于满足分区容错性，也就是说可能因为通信不佳等情况，G1和G2之间是没有同步

   ![img_11](https://img.zhaojq.top/20260727092008774.png "img_11")

2. 接下来，我们的客户端将v1写入G1，但G1和G2之间是不同步的，所以如下G1是v1数据，G2是v0数据

   ![img_12](https://img.zhaojq.top/20260727092008957.png "img_12")

3. 由于要满足可用性，即一定要返回数据，所以G1必须在数据没有同步给G2的前提下返回数据给client,如下

   ![img_13](https://img.zhaojq.top/20260727092009123.png "img_13")

4. 接下去，client请求的是G2服务器，由于G2服务器的数据是v0，所以client得到的数据是v0

   ![img_14](https://img.zhaojq.top/20260727092009292.png "img_14")

**结论：**很明显，G1返回的是v1数据，G2返回的是v0数据，两者不一致。其余情况也有类似推导，也就是说**CAP三者不能同时出现**。

![img_15](https://img.zhaojq.top/20260727092009476.png "img_15")

### 2.3 cap三才如何权衡

- CA (Consistency +  Availability)：关注一致性和可用性，它需要非常严格的全体一致的协议。CA  系统不能容忍网络错误或节点错误，一旦出现这样的问题，整个系统就会拒绝写请求，因为它并不知道对面的那个结点是否挂掉了，还是只是网络问题。唯一安全的做法就是把自己变成只读的。
- CP (consistency + partition  tolerance)：关注一致性和分区容忍性。它关注的是系统里大多数人的一致性协议。这样的系统只需要保证大多数结点数据一致，而少数的结点会在没有同步到最新版本的数据时变成不可用的状态。这样能够提供一部分的可用性。
- AP (availability + partition tolerance)：这样的系统关心可用性和分区容忍性。因此，这样的系统不能达成一致性，需要给出数据冲突，给出数据冲突就需要维护数据版本。

> 放弃了一致性，满足分区容错，那么节点之间就有可能失去联系，为了高可用，每个节点只能用本地数据提供服务，而这样会容易导致全局数据不一致性。对于互联网应用来说，机器数量庞大，节点分散，网络故障再正常不过了，那么此时就是保障AP，放弃C的场景，而从实际中理解，像网站这种偶尔没有一致性是能接受的，但不能访问问题就非常大了。

> 对于银行来说，就是必须保证强一致性，也就是说C必须存在，那么就只用CA和CP两种情况，当保障强一致性和可用性（CA），那么一旦出现通信故障，系统将完全不可用。另一方面，如果保障了强一致性和分区容错（CP），那么就具备了部分可用性。实际究竟应该选择什么，是需要通过业务场景进行权衡的（并不是所有情况都是CP好于CA，只能查看信息但不能更新信息有时候还不如直接拒绝服务）

## 3.BASE理论

上面我们讲到CAP不可能同时满足，而分区容错性是对于分布式系统而言，是必须的。最后，我们说，如果系统能够同时实现 CAP 是再好不过的了，所以出现了 BASE 理论

BASE：全称：**Basically Available(基本可用)**，**Soft state（软状态）**,和 **Eventually consistent（最终一致性）**三个短语的缩写 ,Base 理论是对 CAP 中一致性和可用性权衡的结果，其来源于对大型互联网分布式实践的总结，是基于 CAP 定理逐步演化而来的

其核心思想是： 即使无法做到强一致性（Strongconsistency），但每个应用都可以根据自身的业务特点，采用适当的方式来使系统达到最终一致性（Eventual consistency）。

- Basically Available(基本可用)

  什么是基本可用呢？假设系统，出现了不可预知的故障，但还是能用，相比较正常的系统而言

  > - 响应时间上的损失：正常情况下的搜索引擎 0.5 秒即返回给用户结果，而基本可用的搜索引擎可以在 1 秒返回结果。
  > - 功能上的损失：在一个电商网站上，正常情况下，用户可以顺利完成每一笔订单，但是到了大促期间，为了保护购物系统的稳定性，部分消费者可能会被引导到一个降级页面

- Soft state（软状态）
  什么是软状态呢？相对于原子性而言，要求多个节点的数据副本都是一致的，这是一种 "硬状态"。软状态指的是：允许系统中的数据存在中间状态，并认为该状态不会影响系统的整体可用性，即允许系统在多个不同节点的数据副本存在数据延时。

3. Eventually consistent（最终一致性）
上面说软状态，然后不可能一直是软状态，必须有个时间期限。在期限过后，应当保证所有副本保持数据一致性。从而达到数据的最终一致性。这个时间期限取决于网络延时，系统负载，数据复制方案设计等等因素。

