Skip to content

Commit

Permalink
完善分布式章节
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Jun 10, 2024
1 parent 81a281f commit bc2eebc
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 38 deletions.
8 changes: 2 additions & 6 deletions balance/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@
—— 摘自《编程珠玑》[^1]
:::

负载均衡是构建可靠分布式系统最核心的概念之一
负载均衡是构建可靠分布式系统核心的概念之一,并在系统的各个层面发挥着关键作用。譬如以分发流量和提升网络边缘的扩展性为目的的四层负载均衡 LVS、DPVS,在应用层发挥网关作用的 OpenResty、Kong,还有集群内部的各类的分布式治理框架 SpringCloud 中的 Ribbon 等等

以四层负载均衡(譬如 LVS、DPVS)为核心的网络边缘,再到以七层负载均衡(譬如 OpenResty、Kong、APISIX 等)为核心的网关,还有集群内部的各类的分布式框架,譬如 SpringCloud 的 Ribbon 等等。负载均衡的影响在分布式系统中随处可见。



不过无论负载均衡器以何种形式存在,核心的职责都是“**选择谁来处理用户请求**”和“**将用户请求转发过去**”,本章我们把握这两个职责去分析四层及七层负载均衡的设计模式、工作原理、部署方式等技术。
不过无论这些负载均衡器工作在什么位置或者以何种形式存在,核心的职责无外乎“**选择谁来处理用户请求**”和“**将用户请求转发过去**”,本章我们把握这两个职责去分析四层及七层负载均衡的设计模式、工作原理、部署方式等技术。

:::center
![](../assets/balance-summary.png)<br/>
Expand Down
14 changes: 10 additions & 4 deletions distributed-transaction/ACID.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# 5.1 从一致性开始

事务存在的意义就是保证系统中不同数据间不会产生矛盾,数据修改后的结果是我们期望的,也就是保证数据状态的一致性(Consistency)。想要达成数据状态的一致性,需要三个方面的努力:
事务存在的意义就是保证系统中不同数据间不会产生矛盾,数据修改后的结果是我们期望的,也就是保证数据状态的一致性(Consistency)。

想要达成数据状态的一致性,需要 3 个方面的努力:

- **原子性(A**tomic):原子化更新。业务操作要么全部完成, 要么全都不做,不容忍中间状态。
- **隔离性(I**solation):在不同的业务处理过程中,事务保证了各自业务正在读、写的数据互相独立,不会彼此影响。
- **持久性(D**urability):业务数据不会丢失。事务结束后,除非数据被其他业务更新,否则不应该有变化。

这也就是常说的事务的 **ACID 特性**,不过这里要额外进行说明:事实上对于一致性而言,A、I、D 是手段,C(Consistency)是三者协作的目标,弄到一块完全是为了读起来顺口。
这也就是常说的事务的 **ACID 特性**

:::tip 额外知识
事实上对于一致性而言,A、I、D 是手段,C(Consistency)是三者协作的目标,弄到一块是为了读起来顺口。
:::

当事务的影响范围局限在单机本地内的系统时,一致性通过编码实现起来水到渠成,但倘若事务修改的对象影响涉及外部,譬如跨越网络、跨越不同的数据源时,一致性问题通常很难再使用 A、I、D 来解决,但是外部一致性又是分布式系统中必然会遇到且必须要解决的问题,此时我们就要转变观念,**将一致性从是或否的二元问题转变为可以按不同强度分开讨论的多元问题,在确保代价可承受的前提下获得强度尽可能高的一致性保障**
当事务的影响范围局限在单机本地内的系统时,一致性通过编码实现起来水到渠成,但倘若事务修改的对象影响涉及外部,譬如跨越网络、跨越不同的数据源时,一致性问题通常很难再使用 A、I、D 来解决,但是外部一致性又是分布式系统中必然会遇到且必须要解决的问题,此时我们就要转变观念,**将一致性从是或否的二元问题转变为可以按不同强度分开讨论的多元问题,在确保代价可承受的前提下获得强度尽可能高的一致性保障**。一致性强弱的程度关乎系统设计权衡,由此事务处理从一个具体操作上的“编程问题”而转变成一个需要全局权衡的“架构问题”

一致性强弱的程度关乎系统设计权衡,由此事务处理从一个具体操作上的「编程问题」而转变成一个需要全局权衡的「架构问题」。人们在探索这些架构的设计时产生了诸多思路和理论,这其中最为出名的就是一致性与可用性的权衡定理 —— CAP 定理。
人们在探索这些架构的设计时产生了诸多思路和理论,这其中最为出名的就是一致性与可用性的权衡定理 —— CAP 定理。
14 changes: 8 additions & 6 deletions distributed-transaction/BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

2008 年,eBay 的系统架构师 Dan Pritchett 在 ACM 发表了论文《Base: An Acid Alternative》[^1],文中作者基于实践总结出一种独立 ACID 之外,通过引入消息队列和幂等来达成一致性目的系统化技术手段,并提出了最终一致性的概念。

从论文的名字就可以看出最终一致性的概念与 ACID 强一致性对立。因为 ACID 在英文中有的「酸」的含义,这个模型明显刻意拼凑成 BASE(BASE 英文中有碱的含义)。有酸 vs 碱 这个计算机浑然天成的梗加成,Dan Pritchett 论文被广泛传播,BASE 理论和最终一致性也被大家熟悉。
从论文的名字就可以看出最终一致性的概念与 ACID 强一致性对立。因为 ACID 在英文中有的“酸”的含义,这个模型明显刻意拼凑成 BASE(BASE 英文中有碱的含义)。有酸 vs 碱 这个计算机浑然天成的梗加成,Dan Pritchett 论文被广泛传播,BASE 理论和最终一致性也被大家熟悉。

:::tip BASE
BASE 分别是 Basically Available(基本可用)、Soft State(软状态)和 Eventually Consistent(最终一致性)三个短语的缩写。其核心思想即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性
:::

Dan Pritchett 在论文中的提出的实现最终一致性总结可称为基于**可靠事件队列**的事件驱动模式。可靠事件队列关键在于可靠事件的投递和避免事件重复消费,幸运的是现在流行的消息中间件都实现了事件的持久化和最少一次 的投递模式,此外幂等性实现也有非常成熟的方案,所以这些要求也不再是问题。

下面笔者以一个具体的案例说明 Dan Pritchett 提出的可靠事件队列的具体做法。譬如有这么一个电商系统,下单需要 3 个服务支持:支付服务(银行扣款)、库存服务(扣除购买商品的库存)、积分服务(为用户增加积分)。下单流程**最核心、出错影响最大的服务优先处理**,即:支付扣款 -> 仓库出库 -> 为用户增加积分,整个过程如图 6-2 所示。
下面笔者以一个具体的案例说明 Dan Pritchett 提出的可靠事件队列的具体做法。譬如有这么一个电商系统,下单需要 3 个服务支持:支付服务(银行扣款)、库存服务(扣除购买商品的库存)、积分服务(为用户增加积分)。下单流程**最核心、出错影响最大的服务优先处理**,即:支付扣款 -> 仓库出库 -> 为用户增加积分,整个过程如图 6-2 所示。

:::center
![](../assets/BASE.svg)
Expand All @@ -19,12 +19,14 @@ Dan Pritchett 在论文中的提出的实现最终一致性总结可称为基于

1. 用户向商店发送一个交易请求,譬如购买价值 ¥100 的某个商品。
2. 支付服务创建一个本地的扣款事务,如果扣款成功,则在自己的数据库内建立一张消息表,表内如下结构:事务ID,扣款¥100(状态:已完成),仓库出库(状态:待进行),赠送积分(状态:待进行)。
3. 在系统内建立一个消息服务,定时轮询消息表,将状态是进行中的消息同时发送到库存和积分服务节点中。这个时候会产生以下几种情况:
- 仓库服务和积分服务都顺利完成了出库和加分的工作,向支付服务返回执行结果,支付服务把消息改为已完成。整个事务顺利完成,最终实现一致性。
- 仓库服务和积分服务至少有一个因网络问题,未能收到来自支付服务的消息。此时,由于支付服务存储的消息状态一直处于进行中,所以消息服务器将在每次轮询的时候持续地向未响应的服务重复发送消息。**这个重复的操作决定着所有被消息服务器发送的消息操作都必须具备幂等性**(幂等性设计可以参考 5.3.4) 节内容。如此,出库以及增加积分的动作只会被处理一次。此过程持续自动重复至双方通信恢复正常。
3. 在系统内建立一个消息服务,定时轮询消息表,将状态是进行中的消息同时发送到库存和积分服务节点中。这个时候会产生以下几种情况:
- 仓库服务和积分服务都顺利完成了出库和加分的工作,向支付服务返回执行结果,支付服务把消息改为已完成。整个事务顺利完成,最终实现一致性。
- 仓库服务和积分服务至少有一个因网络问题,未能收到来自支付服务的消息。此时,由于支付服务存储的消息状态一直处于进行中,所以消息服务器将在每次轮询的时候持续地向未响应的服务重复发送消息。**这个重复的操作决定着所有被消息服务器发送的消息操作都必须具备幂等性**(幂等性设计可以参考 5.3.4) 节内容。如此,出库以及增加积分的动作只会被处理一次。此过程持续自动重复至双方通信恢复正常。
- 仓库服务和积分服务因某个原因无法完成处理,譬如仓库发现商品无货,此时,仍然继续持续发送消息,直至操作成功(譬如补充库存),或者被人工介入终止。**由此可见,可靠消息队列方式只要第一步成功了,后续就没有失败回滚的概念,只许成功,不许失败**。


以上这种依靠持续重试来保证可靠性的解决方案在计算机的其他领域中也被频繁使用,它还有专有的名称 —— 「最大努力交付(Best-Effort Delivery)」。而可靠事件队列还有一种更普遍的形式,被称为「最大努力一次提交(Best-Effort 1PC)」,指的是**将最有可能出错的业务以本地事务的方式完成后,采用不断重试的方式来促使同一个分布式事务中其他关联的业务全部完成**
以上这种依靠持续重试来保证可靠性的解决方案在计算机的其他领域中也被频繁使用,它还有专有的名称 —— “最大努力交付(Best-Effort Delivery)”。

可靠事件队列还有一种更普遍的形式,被称为“最大努力一次提交(Best-Effort 1PC)”,指的是**将最有可能出错的业务以本地事务的方式完成后,采用不断重试的方式来促使同一个分布式事务中其他关联的业务全部完成**

[^1]: 参见 https://queue.acm.org/detail.cfm?id=1394128
10 changes: 4 additions & 6 deletions distributed-transaction/CAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ CAP 定理描述的是**一个分布式系统中,涉及共享数据问题时

- **一致性****C**onsistency):代表数据在任何时刻、任何分布式节点中所看到的都是符合预期的。基于证明严谨性的考虑,在学术的研究中一致性指的是强一致性(Strong Consistency)或者也叫做线性一致性(Linearizability)。
- **可用性****A**vailability):代表系统不间断地提供服务的能力,理解可用性要先理解与其密切相关两个指标:可靠性(Reliability)和可维护性(Serviceability)。可靠性使用平均无故障时间(Mean Time Between Failure,MTBF)来度量;可维护性使用平均可修复时间(Mean Time To Repair,MTTR)来度量。可用性衡量系统可以正常使用的时间与总时间之比,其表征为:A = MTBF/(MTBF+MTTR),即可用性是由可靠性和可维护性计算得出的比例值,譬如 99.9999% 可用,即代表平均年故障修复时间为 32 秒。
- **分区容错性****P**artition tolerance):代表分布式环境中部分节点因网络原因而彼此失联后,即与其他节点形成网络分区时,系统仍能正确地提供服务的能力。
- **分区容错性****P**artition tolerance):代表分布式环境中部分节点因网络原因而彼此失联后,即与其他节点形成网络分区时,系统仍能正确地提供服务的能力。

:::tip 额外知识

Expand All @@ -30,14 +30,12 @@ CAP 定理描述的是**一个分布式系统中,涉及共享数据问题时
- **放弃一致性(AP without C)**:意味着我们将假设一旦发生分区,节点之间所提供的数据可能不一致。选择放弃一致性的 AP 系统目前是设计分布式系统的主流选择,因为 P 是分布式网络的天然属性,你再不想要也无法丢弃;而 A 通常是建设分布式的目的,如果可用性随着节点数量增加反而降低的话,分布式系统也就失去了存在的价值,除非银行、证券这些涉及金钱交易的服务,宁可中断也不能出错,否则多数系统是不能容忍节点越多可用性反而越低。


通过上面分析舍弃不同属性的影响,我们看到这么一个无奈的事实:「事务」原本的目的就是获得一致性,而在分布式环境中一致性却不得不成为通常被牺牲、被放弃的那一项属性,结果 AP 类型的系统反而成了分布式系统的主流。
通过上面分析舍弃不同属性的影响,我们看到这么一个现实:“事务”原本的目的就是获得一致性,而在分布式环境中一致性却不得不成为通常被牺牲、被放弃的那一项属性,结果 AP 类型的系统反而成了分布式系统的主流。

但无论如何,我们设计系统终究还是要确保操作结果至少在最终交付的时刻是正确的,这个意思是允许数据中间不一致,但应该在输出时被修正过来。为此,工程师们又重新给一致性下了定义,**将 CAP、ACID 中讨论的一致性称为强一致性,而把牺牲了 C 的 AP 系统但又要尽可能获得正确结果的行为称为追求弱一致性**。不过,如果只单纯说弱一致性,那其实就是不保证一致性的意思。在弱一致性里,工程师又总结出稍微强一点的特例,被称为最终一致性(由 eBay 的系统架构师 Dan Pritchett 在 BASE 理论提出)。
但无论如何,我们设计系统终究还是要确保操作结果至少在最终交付的时刻是正确的,这个意思是允许数据中间不一致,但应该在输出时被修正过来。为此,工程师们又重新给一致性下了定义,**将 CAP、ACID 中讨论的一致性称为强一致性,而把牺牲了 C 的 AP 系统但又要尽可能获得正确结果的行为称为追求弱一致性**。不过,如果只单纯说弱一致性,那其实就是不保证一致性的意思。在弱一致性里,工程师又总结出稍微强一点的特例,被称为最终一致性(由 eBay 的系统架构师 Dan Pritchett 在 BASE 理论提出)。

:::tip 额外知识

ACID 在英文中有的「酸」的含义,对应系统设计的强一致性,而 BASE 在英文中有「碱」的含义,对应系统放弃强一致性实现可用性的设计。酸 vs 碱衍生出 CAP 中的 AP 型可用性架构和 CP 型强一致性架构,所以 CAP 理论又戏称度量分布式系统的「Ph试纸」。

ACID 在英文中有的“酸”的含义,对应系统设计的强一致性,而 BASE 在英文中有“碱”的含义,对应系统放弃强一致性实现可用性的设计。酸 vs 碱衍生出 CAP 中的 AP 型可用性架构和 CP 型强一致性架构,所以 CAP 理论又戏称度量分布式系统的“Ph试纸”。
:::


Expand Down
2 changes: 1 addition & 1 deletion distributed-transaction/Saga.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 5.3.3 SAGA

SAGA 事务模式的历史十分悠久,还早于分布式事务概念的提出,它源于 1987 年普林斯顿大学的 Hector Garcaa-Molrna 和 Kenneth Salem 在 ACM 发表的一篇论文《SAGAS》[^1],论文中提出了一种提升长时间事务(Long Lived Transaction)运作效率的方法,大致的思路是**把一个大事务分解成多个可交错运行的子事务集合,并在每个子事务中引入补偿操作**
SAGA 事务模式的历史十分悠久,早于分布式事务概念的提出,它源于 1987 年普林斯顿大学的 Hector Garcaa-Molrna 和 Kenneth Salem 在 ACM 发表的一篇论文《SAGAS》[^1],论文中提出了一种提升长时间事务(Long Lived Transaction)运作效率的方法,大致的思路是**把一个大事务分解成多个可交错运行的子事务集合,并在每个子事务中引入补偿操作**

提出 SAGA 的目的原本是为了避免大事务长时间锁定数据库的资源,后来逐渐发展成将一个分布式环境中的大事务,分解为一系列本地事务的设计模式。在 SAGA 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。

Expand Down
2 changes: 1 addition & 1 deletion distributed-transaction/TCC.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

TCC 事务模型最早出现在 2007 年数据库专家 Pat Helland 发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》论文中[^1],不过该论文中 TCC 还是以 Tentative-Confirmation-Cancellation 作为名称,在国内经历阿里程立博士的传道之后,TCC 逐渐被大家广为了解并接受。

TCC 是一种对业务侵入性较强的事务方案,要求业务处理过程中必须拆分为预留业务资源」、「确认/释放消费资源两个子过程,两个子过程细化为如下三个阶段:
TCC 是一种对业务侵入性较强的事务方案,要求业务处理过程中必须拆分为预留业务资源”、“确认/释放消费资源两个子过程,两个子过程细化为如下三个阶段:

1. **Try 阶段**:尝试执行阶段,完成所有业务可执行检查(预留必须业务资源,保障隔离性)。
2. **Confirm 阶段**:如果所有分支的 Try 都成功了,则走到 Confirm 阶段。Confirm 真正执行业务,使用 Try 阶段预留的业务资源来完成处理。
Expand Down
Loading

0 comments on commit bc2eebc

Please sign in to comment.