分布式理论与分布式架构设计理论

上一章-RPC

1 分布式架构介绍

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

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

1.1 分布式与集群的区别

集群: 多个服务器做同一个事情
在这里插入图片描述
分布式: 多个服务器做不同的事情
在这里插入图片描述

1.2 分布式系统特性

  1. 分布性
    空间中随机分布。这些计算机可以分布在不同的机房,不同的城市,甚至不同的国家。
  2. 对等性
    分布式系统中的计算机没有主/从之分,组成分布式系统的所有节点都是对等的。
  3. 并发性
    同一个分布式系统的多个节点,可能会并发地操作一些共享的资源,诸如数据库或分布式存储。
  4. 缺乏全局时钟
    既然各个计算机之间是依赖于交换信息来进行相互通信,很难定义两件事件的先后顺序,缺乏全局 始终控制序列
  5. 故障总会发生
    组成分布式的计算机,都有可能在某一时刻突然间崩掉。分的计算机越多,可能崩掉一个的几率就 越大。如果再考虑到设计程序时的异常故障,也会加大故障的概率。
  6. 处理单点故障
    单点SPoF(Single Point of Failure):某个角色或者功能只有某一台计算机在支撑,在这台计算 机上出现的故障是单点故障。

1.3 分布式系统面临的问题

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

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

  3. 节点故障
    节点故障是分布式系统下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机 或"僵死"现象,根据经验来说,每个节点都有可能出现故障,并且经常发生.
    在这里插入图片描述

  4. 三态
    分布式系统每一次请求与响应存在特有的“三态”概念,即成功、失败和超时。

  5. 重发
    分布式系统在发生调用的时候可能会出现 失败 超时 的情况. 这个时候需要重新发起调用.

  6. 幂等
    一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。
    也就是 说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同

2 分布式理论

2.1 数据一致性

分布式数据一致性,指的是数据在多份副本中存储时,各副本中的数据是一致的。
在这里插入图片描述

2.1.1 副本一致性

分布式系统当中,数据往往会有多个副本。多个副本就需要保证数据的一致性。这就带来了同步的 问题,因为网络延迟等因素, 我们几乎没有办法保证可以同时更新所有机器当中的包括备份所有数据. 就 会有数据不一致的情况
在这里插入图片描述
总得来说,我们无法找到一种能够满足分布式系统中数据一致性解决方案。因此,如何既保证数据的一 致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。于是,一致性级 别由此诞生.

2.1.2 一致性分类

  1. 强一致性
    这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好, 但实现起来往往对系统的性能影响大。但是强一致性很难实现。
  2. 弱一致性
    这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据 能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。
  3. 最终一致性
    最终一致性也是弱一致性的一种,它无法保证数据更新后,所有后续的访问都能看到最新数值,而 是需要一个时间,在这个时间之后可以保证这一点(就是在一段时间后,节点间的数据会最终达到 一致状态),而在这个时间内,数据也许是不一致的,这个系统无法保证强一致性的时间片段被称 为「不一致窗口」。不一致窗口的时间长短取决于很多因素,比如备份数据的个数、网络传输延迟 速度、系统负载等。
    在这里插入图片描述
    最终一致性在实际应用中又有多种变种:

因果一致性

  • 如果进程A通知进程B它已更新了一个数据项,那么进程B的后续访问将返回更新后的值。与进 程A无因果关系的进程C的访问遵守一般的最终一致性规则在这里插入图片描述
  • 读己之所写一致性
    当进程A自己更新一个数据项之后,它总是访问到更新过的值,绝不会看到旧值。这是因果一 致性模型的一个特例。在这里插入图片描述
  • 会话一致性
    它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之所写”一 致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统的保证不会延续到新 的会话。在这里插入图片描述
  • 单调读一致性
    如果一个进程已经读取到一个特定值,那么该进程不会读取到该值以前的任何值。在这里插入图片描述
  • 单调写一致性
    系统保证对同一个进程的写操作串行化。
    在这里插入图片描述
    一致性模型图在这里插入图片描述

2.2 CAP定理

CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式 计算系统来说,不可能同时满足以下三点
在这里插入图片描述
1. 一致性(C-Consistency)
这里指的是强一致性
在写操作完成后开始的任何读操作都必须返回该值,或者后续写操作的结果. 也就是说,在一 致性系统中,一旦客户端将值写入任何一台服务器并获得响应,那么之后client从其他任何服务器 读取的都是刚写入的数据
在这里插入图片描述
在这里插入图片描述
2. 可用性(A-Availability)
系统中非故障节点收到的每个请求都必须有响应. 在可用系统中,如果我们的客户端向服务器 发送请求,并且服务器未崩溃,则服务器必须最终响应客户端,不允许服务器忽略客户的请求

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

在这里插入图片描述

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

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

  1. 那么我们要做的第一件事就是分区我们的系统,由于满足分区容错性,也就是说可能因为通信不佳 等情况,G1和G2之间是没有同步在这里插入图片描述
  2. 接下来,我们的客户端将v1写入G1,但G1和G2之间是不同步的,所以如下G1是v1数据,G2是v0 数据。在这里插入图片描述
  3. 由于要满足可用性,即一定要返回数据,所以G1必须在数据没有同步给G2的前提下返回数据给 client,如下在这里插入图片描述
    接下去,client请求的是G2服务器,由于G2服务器的数据是v0,所以client得到的数据是v0在这里插入图片描述
    结论: 很明显,G1返回的是v1数据,G2返回的是v0数据,两者不一致。其余情况也有类似推导,也就是说CAP三者不能同时出现。
    在这里插入图片描述

2.2.2 CAP三者如何权衡

三选二利弊如何

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

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

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

2.3 BASE理论

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

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

其核心思想是:既是无法做到强一致性(Strong consistency,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

  1. Basically Available(基本可用)
    什么是基本可用呢?假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言:
  • 响应时间上的损失:正常情况下的搜索引擎 0.5 秒即返回给用户结果,而基本可用的搜索引擎 可以在 1 秒返回结果。
  • 功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单,但是到了大 促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面
  1. Soft state(软状态)
    什么是软状态呢?相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种 “硬状态”。 软状态指的是:允许系统中的数据存在中间状态,并认为该状态不会影响系统的整体可用性,即允
    许系统在多个不同节点的数据副本存在数据延时。
  2. Eventually consistent(最终一致性)
    上面说软状态,然后不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保 持数据一致性。从而达到数据的最终一致性。这个时间期限取决于网络延时,系统负载,数据复制 方案设计等等因素。
    在这里插入图片描述

3 分布式一致性协议

3.1 两阶段提交协议(2PC)

两阶段提交协议

两阶段提交协议,简称2PC(2 Prepare Commit),是比较常用的解决分布式事务问题的方式,要么所 有参与进程都提交事务,要么都取消事务,即实现ACID中的原子性(A)的常用手段。
分布式事务: 事务提供一种操作本地数据库的不可分割的一系列操作 “要么什么都不做,要么做全 套(All or Nothing)”的机制,而分布式事务就是为了操作不同数据库的不可分割的一系列操作 “要 么什么都不做,要么做全套(All or Nothing)”的机制
在这里插入图片描述
2PC执行流程

  1. 成功执行事务事务提交流程在这里插入图片描述
    在这里插入图片描述
  2. 中断事务流程
    假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参 与者的反馈响应,那么就会中断事务
    在这里插入图片描述
    在这里插入图片描述

3.1.1 2PC 优点缺点

1在这里插入图片描述
在这里插入图片描述

3.2 三阶段提交协议(3PC)

三阶段提交协议出现背景:一致性协议中设计出了二阶段提交协议(2PC),但是2PC设计中还存 在缺陷,于是就有了三阶段提交协议,这便是3PC的诞生背景。

3.2.1 三阶段提交协议

3PC,全称 “three phase commit”,是 2PC 的改进版,将 2PC 的 “提交事务请求” 过程一分为二,共 形成了由CanCommit、PreCommit和doCommit三个阶段组成的事务处理协议。在这里插入图片描述
在这里插入图片描述

3.2.2 三个阶段详解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果出现了任一一种情况,最终都会导致参与者无法收到 doCommit 请求或者 abort 请求,针对 这种情况,参与者都会在等待超时之后,继续进行事务提交

3.2.3 2PC对比3PC

  1. 首先对于协调者和参与者都设置了超时机制(在2PC中,只有协调者拥有超时机制,即如果在一定 时间内没有收到参与者的消息则默认失败),主要是避免了参与者在长时间无法与协调者节点通讯 (协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自 动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。
  2. 通过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个 缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的 。
  3. PreCommit是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。

3.3 NWR协议

3.3.1 什么是NWR协议

NWR是一种在分布式存储系统中用于控制一致性级别的一种策略。在亚马逊的云存储系统中,就应用 NWR来控制一致性。
N:在分布式存储系统中,有多少份备份数据
W:代表一次成功的更新操作要求至少有w份数据写入成功
R: 代表一次成功的读数据操作要求至少有R份数据成功读取

3.3.2 原理

NWR值的不同组合会产生不同的一致性效果,当W+R>N的时候,整个系统对于客户端来讲能保证强 一致性。

以常见的N=3、W=2、R=2为例:
N=3,表示,任何一个对象都必须有三个副本
W=2表示,对数据的修改操作只需要在3个副本中的2个上面完成就返回
R=2表示,从三个对象中要读取到2个数据对象,才能返回

在分布式系统中,数据的单点是不允许存在的。即线上正常存在的备份数量N设置1的情况是 非常危险的,因为一旦这个备份发生错误,就 可能发生数据的永久性错误。假如我们把N设 置成为2,那么,只要有一个存储节点发生损坏,就会有单点的存在。所以N必须大于2。N越 高,系统的维护和整体 成本就越高。工业界通常把N设置为3。

  1. 当W是2、R是2的时候,W+R>N,这种情况对于客户端就是强一致性的。在这里插入图片描述
  2. 当R+W<=N,无法保证数据的强一致性在这里插入图片描述

3.4 Gossip 协议

Gossip 协议也叫 Epidemic 协议 (流行病协议)。原本用于分布式数据库中节点同步数据使用, 后被广泛用于数据库复制、信息扩散、集群成员身份确认、故障探测等。
从 gossip 单词就可以看到,其中文意思是八卦、流言等意思,我们可以想象下绯闻的传播(或者流 行病的传播);gossip 协议的工作原理就类似于这个。gossip 协议利用一种随机的方式将信息传播到整 个网络中,并在一定时间内使得系统内的所有节点数据一致。Gossip 其实是一种去中心化思路的分布式 协议,解决状态在集群中的传播和状态一致性的保证两个问题。在这里插入图片描述

3.4.1 Gossip原理

Gossip 协议的消息传播方式有两种:反熵传播 和 谣言传播

  1. 反熵传播
    是以固定的概率传播所有的数据。所有参与节点只有两种状态:Suspective(病原)、 Infective(感染)。过程是种子节点会把所有的数据都跟其他节点共享,以便消除节点之间数据的任 何不一致,它可以保证最终、完全的一致。缺点是消息数量非常庞大,且无限制;通常只用于新加 入节点的数据初始化。
  2. 谣言传播
    是以固定的概率仅传播新到达的数据。所有参与节点有三种状态:Suspective(病原)、 Infective(感染)、Removed(愈除)。过程是消息只包含最新 update,谣言消息在某个时间点之后会 被标记为 removed,并且不再被传播。缺点是系统有一定的概率会不一致,通常用于节点间数据 增量同步。

3.4.3 通信方式

Gossip 协议最终目的是将数据分发到网络中的每一个节点。根据不同的具体应用场景,网络中两个节 点之间存在三种通信方式:推送模式、拉取模式、推/拉模式

  1. Push
    节点 A 将数据 (key,value,version) 及对应的版本号推送给 B 节点,B 节点更新 A 中比自己新的数 据
  2. PullA 仅将数据 key, version 推送给 B,B 将本地比 A 新的数据(Key, value, version)推送给 A,A 更 新本地
  3. Push/Pull
    与 Pull 类似,只是多了一步,A 再将本地比 B 新的数据推送给 B,B 则更新本地

3.4.4 优缺点

综上所述,我们可以得出 Gossip 是一种去中心化的分布式协议,数据通过节点像病毒一样逐个传 播。因为是指数级传播,整体传播速度非常快。
在这里插入图片描述

3.5 Paxos协议

Paxos协议其实说的就是Paxos算法, Paxos算法是基于消息传递且具有高度容错特性的一致性算 法,是目前公认的解决分布式一致性问题最有效的算法之一。在这里插入图片描述
Paxos 解决了什么问题在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如何解决2PC和3PC的存在的问题呢?在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5.1 Basic Paxos相关概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5.2 Basic Paxos流程图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5.3 Multi-Paxos流程图

针对basic Paxos是存在一定得问题,首先就是流程复杂,实现及其困难, 其次效率低(达成一致性需要2轮 RPC调用),针对basic Paxos流程进行拆分为选举和复制的过程.
在这里插入图片描述
在这里插入图片描述

3.5.4 Multi-Paxos角色重叠流程图

在这里插入图片描述

3.6 Raft协议

Paxos 是论证了一致性协议的可行性,但是论证的过程据说晦涩难懂,缺少必要的实现细节,而且 工程实现难度比较高,  广为人知实现只有 zk 的实现 zab 协议。
Paxos协议的出现为分布式强一致性提供了很好的理论基础,但是Paxos协议理解起来较为困难, 实现比较复杂。
然后斯坦福大学RamCloud项目中提出了易实现,易理解的分布式一致性复制协议 Raft。Java, C++,Go 等都有其对应的实现之后出现的Raft相对要简洁很多。引入主节点,通过竞选确定主节点。节 点类型:Follower、Candidate 和 Leader
Leader 会周期性的发送心跳包给 Follower。每个 Follower 都设置了一个随机的竞选超时时间,一 般为 150ms~300ms,如果在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选 阶段, 通过竞选阶段的投票多的人成为Leader![在这里插入图片描述](https://img-blog.csdnimg.cn/6773304078184539a23c5065310fe226.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dKT0VE,size_16,color_FFFFFF,t_70)

3.6.1 Raft相关概念

在这里插入图片描述
竞选阶段流程
Leader节点宕机
多个 Candidate 竞选
日志复制
网络分区
网络分区情况日志复制

通过Raft完整版动画演示可以很好的理解
github也提供一个https://raft.github.io/动画演示地址 . 原理都是一样的.

3.7 Lease机制

Lease机制,翻译过来即是租约机制,是一种在分布式系统常用的协议,是维护分布式系统数据一致性 的一种常用工具。

Lease机制有以下几个特点:

  • Lease是颁发者对一段时间内数据一致性的承诺;
  • 颁发者发出Lease后,不管是否被接收,只要Lease不过期,颁发者都会按照协议遵守承诺;
  • Lease的持有者只能在Lease的有效期内使用承诺,一旦Lease超时,持有者需要放弃执行,重新申 请Lease。在这里插入图片描述
    Lease机制解决了什么问题?

分布式系统中,如何确认一个节点是否工作正常?如果有5副本1-5。其中1号为主副本。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2. 会在剩下的副节点中选取一当主节点.在这里插入图片描述
主要解决思路有四种:
- 设计能容忍双主的分布式协议
- Raft协议-通过Term版本高的同步低的.
- 用lease机制
- 涉及去中心化-Gossip协议

lease的容错

  1. 主节点宕机
    lease机制天生即可容忍网络、lease接收方的出错,时间即Lease剩余过期时长
  2. 中心节点异常
    颁发者宕机可能使得全部节点没有lease,系统处于不可用状态,解决的方法就是使用一个小集群 而不是单一节点作为颁发者。
  3. 时差问题
    中心节点与主节点之间的时钟可能也存在误差,只需要中心节点考虑时钟误差即可。

应用

  1. GFS(Google 文件系统)中,Master通过lease机制决定哪个是主副本,lease在给各节点的心跳响应 消息中携带。收不到心跳时,则等待lease过期,再颁发给其他节点。
  2. chubby中,paxos选主后,从节点会给主颁发lease,在期限内不选其他节点为主。另一方面,主 节点给每个client节点发送lease,用于判断client死活。

4 分布式系统设计策略

在分布式环境下,有几个问题是普遍关心的.

  • 如何检测当前节点还活着?
  • 如何保障高可用?
  • 容错处理
  • 负载均衡

4.1 心跳检测

在分布式环境中,我们提及过存在非常多的节点(Node)。那么就有一个非常重要的问题,如 何检测一个节点出现了故障乃至无法工作了?
通常解决这一问题是采用心跳检测的手段,如同通过仪器对病人进行一些检测诊断一样。
心跳顾名思义,就是以固定的频率向其他节点汇报当前节点状态的方式。收到心跳,一般可以认 为一个节点和现在的网络是良好的。当然,心跳汇报时,一般也会携带一些附加的状态、元数据信息, 以便管理在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2 高可用

4.2.1 高可用HA设计

在这里插入图片描述
在这里插入图片描述
3. 集群模式
集群模式是指有多个节点在运行,同时可以通过主控节点分担服务请求。集群模式需要解决主控 节点本身的高可用问题,一般采用主备模式。

4.2.2 高可用HA下"脑裂问题"

  1. 什么是脑裂.
    在高可用(HA)系统中,当联系两个节点的"心跳线"断开时(即两个节点断开联系时),本来为 一个整体、动作协调的HA系统,就分裂成为两个独立的节点(即两个独立的个体)。由于相互失去了 联系,都以为是对方出了故障,两个节点上的HA软件像"裂脑人"一样,“本能"地争抢"共享资源”、 争起"应用服务"。就会发生严重后果:
  • 共享资源被瓜分、两边"服务"都起不来了;
  • 两边"服务"都起来了,但同时读写"共享存储",导致数据损坏(常见如数据库轮询着的联机日 志出错)。
    两个节点相互争抢共享资源,结果会导致系统混乱,数据损坏。对于无状态服务的HA,无所 谓脑裂不脑裂,但对有状态服务(比如MySQL)的HA,必须要严格防止脑裂
    在这里插入图片描述

4.3 容错性

容错顾名思义就是IT系统对于错误包容的能力
容错的处理是保障分布式环境下相应系统的高可用或者健壮性,一个典型的案例就是对于缓存穿透 问 题的解决方案。我们来具体看一下这个例子,如图所示
在这里插入图片描述
问题描述:
我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在 就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存 在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,或者有人恶意攻击
如频繁发起为id为“-1”的条件进行查询,可能DB就挂掉了。在这里插入图片描述
那这种问题有什么好办法解决呢?

  1. 临时存放null值
  2. 使用布隆过滤器在这里插入图片描述

4.4 负载均衡

负载均衡:其关键在于使用多台集群服务器共同分担计算任务,把网络请求及计算分配到集群可用 的不同服务器节点上,从而达到高可用性及较好的用户操作体验。
如图,不同的用户client1、client2、client3访问应用,通过负载均衡器分配到不同的节点。
在这里插入图片描述
在这里插入图片描述

5. 分布式架构服务调用

5.1 服务调用

和传统的单体架构相比,分布式多了一个远程服务之间的通信,不管是 soa 还是微服务,他们本 质上都是对于业务服务的提炼和复用。那么远程服务之间的调用才是实现分布式的关键因素。在这里插入图片描述

5.2 实现方式

5.2.1 HTTP 应用协议的通信框架

在这里插入图片描述

5.2.2 RPC 框架

PC全称为remote procedure call,即远程过程调用。借助RPC可以做到像本地调用一样调用远 程服务,是一种进程间的通信方式. 。常见的RPC框架有一下几种.

  1. Java RMI
    Java RMI(Romote Method Invocation)是一种基于Java的远程方法调用技术,是Java特有的一 种RPC实现。在这里插入图片描述
  2. Hessian
    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比 WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以 它很适合于发送二进制数据。在这里插入图片描述
  3. Dubbo
    Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服 务的输出和输入功能,可以和Spring框架无缝集成。Dubbo是一款高性能、轻量级的开源Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注 册和发现。在这里插入图片描述
  4. gRPC
    gRPC是由Google公司开源的一款高性能的远程过程调用(RPC)框架,可以在任何环境下运行。该 框架提供了负载均衡,跟踪,智能监控,身份验证等功能,可以实现系统间的高效连接。在这里插入图片描述

5.3 跨域调用

5.3.1 跨域

在分布式系统中, 会有调用其他业务系统,导致出现跨域问题,跨域实质上是浏览器的一种保护处 理。如果产生了跨域,服务器在返回结果时就会被浏览器拦截(注意:此时请求是可以正常发起的,只是 浏览器对其进行了拦截),导致响应的内容不可用. 产生跨域的几种情况有一下:在这里插入图片描述

5.3.2 常见的解决方案

  1. 使用jsonp解决网站跨域
    缺点:不支持post请求,代码书写比较复杂
  2. 使用HttpClient内部转发
  3. 使用设置响应头允许跨域
    response.setHeader(“Access-Control-Allow-Origin”, “*”); 设置响应头允许跨域.
  4. 基于Nginx搭建企业级API接口网关
  5. 使用Zuul搭建微服务API接口网关
    Zuul是spring cloud中的微服务网关。网关: 是一个网络整体系统中的前置门户入口。请求首先通 过网关,进行路径的路由,定位到具体的服务节点上。可以使用zuul的过滤器的请求转发去解决跨 域问题

6.分布式服务治理

6.1 服务协调

分布式协调技术主要用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某 种临界资源,防止造成"脏数据"的后果。在这里插入图片描述
分布式锁也就是我们分布式协调技术实现的核心内容。 分布式锁两种实现方式:

  1. 基于缓存(Redis等)实现分布式锁在这里插入图片描述
  2. ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树 结构,规定同一个目录下只能有一个唯一文件名, 基于ZooKeeper实现分布式锁的步骤如下:在这里插入图片描述

6.2 服务削峰

6.2.1 为什么要削峰

主要是还是来自于互联网的业务场景,例如,春节火车票抢购,大量的用户需要同一时间去抢购; 以及大家熟知的阿里双11秒杀, 短时间上亿的用户涌入,瞬间流量巨大(高并发).

6.2.2 流量削峰方案

削峰从本质上来说就是更多地延缓用户请求,以及层层过滤用户的访问需求,遵从“最后落地到数据 库的请求数要尽量少”的原则。

  1. 消息队列解决削峰
    要对流量进行削峰,最容易想到的解决方案就是用消息队列来缓冲瞬时流量,把同步的直接调用转 换成异步的间接推送,中间通过一个队列在一端承接瞬时的流量洪峰,在另一端平滑地将消息推送 出去。在这里插入图片描述
    消息队列中间件主要解决应用耦合,异步消息, 流量削锋等问题。常用消息队列系统:目前 在生产环境,使用较多的消息队列有 ActiveMQ、RabbitMQ、 ZeroMQ、Kafka、RocketMQ 等。
    在这里,消息队列就像“水库”一样,拦截上游的洪水,削减进入下游河道的洪峰流量,从而达 到减免洪水灾害的目的。
  2. 流量削峰漏斗:层层削峰
    分层过滤其实就是采用“漏斗”式设计来处理请求的,这样就像漏斗一样,尽量把数据量和请求量一 层一层地过滤和减少了。如下图所示:在这里插入图片描述
    在这里插入图片描述

6.3 服务降级

6.3.1 什么是服务降级

当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换 种简单的方式处理,从而释放服务器资源以保证核心服务正常运作或高效运作
在这里插入图片描述
整个架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保 证重要或基本的服务能正常运行,我们可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用

6.3.2 降级策略

当触发服务降级后,新的交易再次到达时,我们该如何来处理这些请求呢?从分布式,微服务架构全局的 视角来看,降级处理方案:
在这里插入图片描述

6.3.3 分级降级

结合服务能否降级的优先原则,并根据台风预警(都属于风暴预警)的等级进行参考设计,可将分布 式服务架构的所有服务进行故障风暴等级划分为以下四种在这里插入图片描述

6.4 服务限流

6.4.1 什么是服务限流

限流并非新鲜事,在生活中亦无处不在,下面例举一二:
在这里插入图片描述
以上"限流"例子,可以让服务提供者稳定的服务客户。
限流的目的是通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系 统,一旦达到限制速率则可以拒绝服务、排队或等待在这里插入图片描述

6.4.2 多维度限流

在请求到达目标服务接口的时候, 可以使用多维度的限流策略,这样就可以让系统平稳度过瞬间来临的并 发在这里插入图片描述

6.4.3 限流算法

  1. 限流算法-计数器(固定窗口)
    计数器限制每一分钟或者每一秒钟内请求不能超过一定的次数,在下一秒钟计数器清零重新计算
    在这里插入图片描述
    存在问题:
    客户端在第一分钟的59秒请求100次,在第二分钟的第1秒又请求了100次, 2秒内后端会受到200 次请求的压力,形成了流量突刺

  2. 限流算法-计数器(滑动窗口)
    滑动窗口其实是细分后的计数器,它将每个时间窗口又细分成若干个时间片段,每过一个时间片 段,整个时间窗口就会往右移动一格在这里插入图片描述
    时间窗口向右滑动一格,这时这个时间窗口其实已经打满了100次,客户端将被拒绝访问,时间窗口 划分的越细,滑动窗口的滚动就越平滑,限流的效果就会越精确

  3. 限流算法-漏桶
    漏桶算法类似一个限制出水速度的水桶,通过一个固定大小FIFO队列+定时取队列元素的方式实 现,请求进入队列后会被匀速的取出处理(桶底部开口匀速出水),当队列被占满后后来的请求会 直接拒绝(水倒的太快从桶中溢出来)在这里插入图片描述
    优点是可以削峰填谷,不论请求多大多快,都只会匀速发给后端,不会出现突刺现象,保证下游服 务正常运行 , 缺点就是在桶队列中的请求会排队,响应时间拉长

  4. 限流算法-令牌桶
    令牌桶算法是以一个恒定的速度往桶里放置令牌(如果桶里的令牌满了就废弃),每进来一个请求 去桶里找令牌,有的话就拿走令牌继续处理,没有就拒绝请求在这里插入图片描述
    令牌桶的优点是可以应对突发流量,当桶里有令牌时请求可以快速的响应,也不会产生漏桶队列中 的等待时间, 缺点就是相对漏桶一定程度上减小了对下游服务的保护

6.5 服务熔断

6.5.1 什么是服务熔断

【熔断】, 熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游 服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服 务的调用。这种牺牲局部,保全整体的措施就叫做熔断。

如果不采取熔断措施,我们的系统会怎样呢? 举例说明:

当前系统中有A,B,C三个服务,服务A是上游,服务B是中游,服务C是下游. 它们的调用链如下:在这里插入图片描述
一旦下游服务C因某些原因变得不可用,积压了大量请求,服务B的请求线程也随之阻塞。线程资源 逐渐耗尽,使得服务B也变得不可用。紧接着,服务 A也变为不可用,整个调用链路被拖垮。在这里插入图片描述
像这种调用链路的连锁故障,叫做雪崩。

6.5.2 熔断机制

在这种时候,就需要我们的熔断机制来挽救整个系统。
在这里插入图片描述
这里需要解释两点:

  1. 开启熔断
    在固定时间窗口内,接口调用超时比率达到一个阈值,会开启熔断。
    进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的默认方法,达到服务降 级的效果。
  2. 熔断恢复
    熔断不可能是永久的。当经过了规定时间之后,服务将从熔断状态回复过来,再次接受调用方的远程 调用。

6.5.3 熔断机制实现

  1. Spring Cloud Hystrix
    Spring Cloud Hystrix是基于Netflix的开源框架Hystrix实现,该框架实现了服务熔断、线程隔离等 一系列服务保护功能。
    对于熔断机制的实现,Hystrix设计了三种状态:在这里插入图片描述
    在这里插入图片描述
  2. Sentinel
    Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,防止避免影 响到其它的资源,最终产生雪崩的效果。
    Sentinel 熔断手段:
    在这里插入图片描述

6.6 服务链路追踪

6.6.1 什么是链路追踪

分布式微服务架构上通过业务来划分服务的,通过REST调用对外暴露的一个接口,可能需要很多个 服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口 调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。
在这里插入图片描述
随着服务的越来越多,对调用链的分析会越来越复杂。它们之间的调用关系也许如下:在这里插入图片描述
分布式链路追踪(Distributed Tracing),也叫 分布式链路跟踪,分布式跟踪,分布式追踪 等等. 其 实就是将一次分布式请求还原成调用链路。显示的在后端查看一次分布式请求的调用情况,比如各个节 点上的耗时、请求具体打到了哪台机器上、每个服务节点的请求状态等等。

6.6.2 链路跟踪具备的功能

  1. 故障快速定位
    通过调用链跟踪,一次请求的逻辑轨迹可以用完整清晰的展示出来。开发中可以在业务日志中添 加调用链ID,可以通过调用链结合业务日志快速定位错误信息。在这里插入图片描述
  2. 各个调用环节的性能分析
    在调用链的各个环节分别添加调用时延,可以分析系统的性能瓶颈,可以进行针对性的优化。通 过分析各个环节的平均时延,QPS等信息,可以找到系统的薄弱环节,对一些模块做调整。在这里插入图片描述
  3. 数据分析
    调用链绑定业务后查看具体每条业务数据对应的链路问题,可以得到用户的行为路径,经过了哪些 服务器上的哪个服务,汇总分析应用在很多业务场景。
  4. 生成服务调用拓扑图
    通过可视化分布式系统的模块和他们之间的相互联系来理解系统拓扑。点击某个节点会展示这个 模块的详情,比如它当前的状态和请求数量。

6.6.3 链路跟踪设计原则

在这里插入图片描述

6.6.4 链路跟踪Trace模型

Trace调用模型,主要有以下概念:在这里插入图片描述
Client && Server:对于跨服务的一次调用,请求发起方为client,服务提供方为Server各术语在一次 分布式调用中,关系如下图所示在这里插入图片描述
链路跟踪系统实现:
大的互联网公司都有自己的分布式跟踪系统,比如Google的Dapper,Twitter的zipkin,淘宝的鹰 眼,新浪的Watchman,京东的Hydra等等.

7.架构设计基本原则

架构最重要的就是编程思想:

  1. 利于开发者
  2. 利于公司
  3. 利于客户

7.1 开闭原则

7.1.2 开闭原则的定义

开闭原则:软件实体应当对扩展开放,对修改关闭,这就是开闭原则的经典定义。 这里的软件实体包括以下几个部分:

  1. 项目中划分出的模块
  2. 类与接口
  3. 方法
    开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以 扩展模块的功能,使其满足新的需求。

7.1.2 开闭原则的作用

开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性 和延续性。具体来说,其作用如下。

  1. 对软件测试的影响
  2. 可以提高代码的可复用性
  3. 可以提高软件的可维护性

7.2 单一职责原则

7.2.1 单一职责原则的定义

单一职责原则又称单一功能原则,这里的职责是指类变化的原因,单一职责原则规定一个类应该有 且仅有一个引起它变化的原因,否则类应该被拆分。
该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:

  1. 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
  2. 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代 码或代码的浪费。

7.2.2 单一职责原则的优点

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有 以下优点。

  1. 降低类的复杂度
  2. 提高类的可读性
  3. 提高系统的可维护性
  4. 变更引起的风险降低

7.2.3 单一职责原则的实现方法

单一职责原则是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,再封装到不 同的类或模块中。而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。下面以 大学学生工作管理程序为例介绍单一职责原则的应用。
大学学生工作管理程序:在这里插入图片描述

7.3 接口隔离原则

7.3.1 接口隔离原则的定义

接口隔离原则要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客 户感兴趣的方法。
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两 者是不同的:

  1. 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
  2. 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要 针对抽象和程序整体框架的构建。

7.3.2 接口隔离原则的优点

接口隔离原则是为了约束接口、降低类对接口的依赖性,遵循接口隔离原则有以下 5 个优点。

  1. 提高系统的灵活性和可维护性
  2. 降低系统的耦合性。
  3. 保证系统的稳定性
  4. 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
  5. 能减少项目工程中的代码冗余

7.3.3 接口隔离原则的实现方法

在具体应用接口隔离原则时,应该根据以下几个规则来衡量。
接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深 入了解业务逻辑。
提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

7.4 里氏替换原则

7.4.1 里氏替换原则的定义

里氏替换原则主要阐述了有关继承的一些原则。里氏替换原则是继承复用的基础,它反映了基类与 子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。总结:子类可以扩展父类的 功能,但不能改变父类原有的功能

7.4.2 里氏替换原则的作用

里氏替换原则的主要作用如下。

  1. 里氏替换原则是实现开闭原则的重要方式之一。
  2. 它克服了继承中重写父类造成的可复用性变差的缺点。
  3. 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
  4. 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需 求变更时引入的风险。

7.4.3 里氏替换原则的实现方法

根据上述理解,对里氏替换原则的定义可以总结如下:

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法在这里插入图片描述
  2. 子类中可以增加自己特有的方法在这里插入图片描述
    在这里插入图片描述

7.5 依赖倒置原则

7.5.1 依赖倒置原则定义

依赖倒置原则的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依 赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。

7.5.2 依赖倒置原则的作用

依赖倒置原则的主要作用如下。

  1. 可以降低类间的耦合性。
  2. 可以提高系统的稳定性。
  3. 可以减少并行开发引起的风险。
  4. 可以提高代码的可读性和可维护性。

7.6 迪米特法则

7.6.1 迪米特法则的定义

迪米特法则又叫作最少知识原则, 迪米特法则的定义是:只与你的直接朋友交谈,不跟“陌生人”说 话。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方 转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

7.6.2 迪米特法则的优点

迪米特法则要求限制软件实体之间通信的宽度和深度,正确使用迪米特法则将有以下两个优点。

  1. 降低了类之间的耦合度,提高了模块的相对独立性。
  2. 由于亲合度降低,从而提高了类的可复用性和系统的扩展性。

7.6.3 迪米特法则的实现方法

从迪米特法则的定义和特点可知,它强调以下两点:

  1. 从依赖者的角度来说,只依赖应该依赖的对象。
  2. 从被依赖者的角度说,只暴露应该暴露的方法。

7.7 合成复用原则

7.7.1 合成复用原则的定义

合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则
(Composition/Aggregate Reuse Principle,CARP)。它要求在软件复用时,要尽量先使用组合或者 聚合等关联关系来实现,其次才考虑使用继承关系来实现。
如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的, 两者都是开闭原则的具体实现规范

7.7.2 合成复用原则的重要性

通常类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优点,但它也存在以下缺 点。

  1. 继承复用破坏了类的封装性
  2. 子类与父类的耦合度高
  3. 它限制了复用的灵活性
    采用合成复用原则时,他可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已 有对象的功能,它有以下优点。
  4. 它维持了类的封装性
  5. 新旧类之间的耦合度低
  6. 复用的灵活性高
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值