CAP原则

EricBrewer

https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/

对于开发或设计分布式系统的架构师工程师来说,CAP是必须要掌握的理论。

CAP定理又被成为布鲁尔定理,是加州大学计算机科学家埃里克·布鲁尔提出来的猜想,后来被证明成为分布式计算领域公认的定理

CAP定义,在高并发的场景下要做取舍,在大型集群中分区容错很难保证,一旦要确保容错性,那么就会损失数据一致性和高可用特性。

C

Consistency -> 一致性

G1,G2为数据节点,同时存储了键值对 key=v:value=0

img

⭕ 上图:向G1 写入数据

imgimg

⭕ 上图:数据写入完成,G1->v:1,写入完成后,在向G1读取数据的时候就会得到v:1,此时是一致性

imgimg

⭕ 上图:那么此时如果向G2发起读请求的话,因为数据没有同步,就会得到v:0,此时数据不一致

imgimgimgimg

imgimgimgimg⭕ 上图:如果流程变成这样的

  • 写入G1
  • G1向G2同步数据
  • 等待同步完成
  • 通知写完成
  • 读取数据

似乎得到了一致性

一致性是指分布式系统中,数据在多节点存在副本,那么数据如果一直不修改,在读的时候是不存在问题的,你访问哪个节点的数据都一样

可一旦要是发生了修改,那么数据同步无法在修改的瞬间广播到所有副本节点

那么在读的时候就可能发生数据脏读 脑裂

数据库

item_id = 100,谁在改,时间

单点/AP

Redis 高性能

A/P

Zookeeper

饥渴式

1570811505077

懒汉式

1570811535035

数据篡改

拜占庭将军问题

分布式系统 一致性问题

  • 强一致性

  • 弱一致性

  • 最终一致性

CAP中的一致性

A

Availability -> 可用性

指的是服务是否可用,范围涵盖终端客户访问我们的系统或者是集群内部相互通讯交换数据

也就是说在Client向Server发起请求时,服务器返回了正确的响应,称之为可用,反之为不可用

这里有一个问题,如果发送请求在300年后给我返回数据了,那么算不算可用?

所以要提出访问延迟的概念,在某个时间范围内响应才算可用。

1s法则

1S法则”是面向Web侧,H5链路上加载性能 和体验方向上的一个指标,具体指:

  • “强网” (4G/WIFI)下,1秒完全完成页面加载,包括首屏 资源,可看亦可用;
  • 3G下1秒完成首包的返回 ;
  • 2G下1秒完成建连。

高可用架构在实施的时候可以分两个方向

客户端容错

例如:游戏服务器

服务器端容错

例如:Nginx负载均衡

P

Partition tolerance -> 分区容错性

img

啥叫分区容错

发生在分布式系统内部互访通信,

是指分布式网络中部分网络不可用,

但系统依然正常对外提供服务

上图中 G1,G2是两台服务器,G1 向 G2 发送一条消息,G2 可能无法收到

比如:北京的订单系统,访问上海的库存系统

分区容错性是指分区具有容错性,我们可以尽可能的提高容错性,但是无法避免,

如果发生失败,就要在A和C之间做出选择。 要么停止系统进行错误恢复,要么继续服务但是降低一致性,所以我们说只能保证AP或CP。

在互相隔离的空间中,提供数据服务的系统。 CAP抽象:不同空间的数据,在同一时间,状态一致。


C:代表状态一致 A:代表同一时间 P:代表不同空间

CP

不同空间中的数据,如果要求他们所有状态一致,则必然不在同一时间。

AP

不同空间中,如果要求同一时间都可以从任意的空间拿到数据,则必然数据的状态不一致。

CA

不同空间的数据,如果要求任意时间都可以从任意空间拿到状态一致的数据,则空间数必然为1.

要强一致性的地方:

  • 唯一ID生成, 这种性能很差. 并发不高.
  • 对一致性要求比较高的系统,例如银行转账

要高可用: 最终一致, 即有可能读到脏数据. 但是一段时间之后总是能够读到新数据.

Zookeeper和Eureka

zookeepr

保证CP,即任何时刻对zookeeper的访问请求能得到一致性的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务的可用性。从实际情况来分析,在使用zookeeper获取服务列表时,如果zk正在选举或者zk集群中半数以上的机器不可用,那么将无法获取数据。所以说,zk不能保证服务可用性。

eureka

保证AP,eureka在设计时优先保证可用性,每一个节点都是平等的,一部分节点挂掉不会影响到正常节点的工作,不会出现类似zk的选举leader的过程,客户端发现向某个节点注册或连接失败,会自动切换到其他的节点,只要有一台eureka存在,就可以保证整个服务处在可用状态,只不过有可能这个服务上的信息并不是最新的信息。

BASE 理论

eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(StrongConsistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。

ACM国际大学生程序设计竞赛(英文全称:ACM International Collegiate Programming Contest(简称ACM-ICPC或ICPC))

Basically Available

基本可用

在分布式系统出现故障的时候,允许损失部分可用性,支持分区失败,即保证核心可用。

Soft State

软状态

接受一段时间的状态不同步,及中间状态,而改中间状态不影响系统整体可用性。这里的中间状态就是CAP理论中的数据不一致性。

Eventually Consistent

最终一致性

上面说软状态,然后不可能一直是软状态,必须有个时间期限。在期限过后系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值。

强一致性



在高并发场景下,当系统中的一些功能组件出现异常,无法继续提供服务器的时候,为了保证整体系统可用性,可以牺牲一部分功能依旧提供有损服务

SLA

服务等级定义 SLA(Service Level Agreement)是判定压测是否异常的重要依据。压测过程中,通过监控核心服务状态的 SLA 指标数据,您可以更直观地了解压测业务的状态。

SLA则是服务商与您达成的正常运行时间保证。

详见

https://help.aliyun.com/document_detail/111729.html?spm=a2c4g.11186623.3.3.19693e74AnPY9O

SLA 分为网络服务/云服务提供商的在线保证率和项目自身故障率

6个9

2个9 = (1-99%)X24 X 365 = 87.6 小时 = 3.65天

3个9 = (1-99.9%)X24 X 365 = 8.76 小时

4个9 = (1-99.99%)X24 X 365 = 0.876 小时 = 52.56分钟

5个9 = (1-99.999%)X24 X 365 = 0.0876 小时 = 5.256分钟

6个9 = (1-99.9999%)X24 X 365 = 0.00876 小时 = 0.5256分钟 = 31秒

AP

12306 强一致性

降级处理

兜底数据

默认值: 设置安全的默认值,不会引起数据问题,比如库存为0

静态值:请求的页面或api无法返回数据,提供一套静态数据展示,比如加载失败提示重试,或默认菜单

缓存: 缓存无法更新便使用旧的缓存

限流降级

当流量洪峰到达的时候,对于丢弃的用户可以提供友好的提示

比如提示用户当前繁忙稍后重试等

超时降级

对调用的数据设置超时时间,当调用失败,对服务降级

重试/自动处理

客户端高可用:提供多个可调用的服务地址

微服务重试:dubbo重试机制

API调用重试:当达到重试次数后,增加访问标记,服务降级,异步探测服务是否恢复。

WEB端:在服务不可用时,web端增加重试按钮或自动重试可以提供更友好的体验。

自动重试需设置重试次数和数据幂等处理

降级开关

在服务调用方设置一个flag,标记服务是否可用

存储在第三方,配置文件、数据库、redis、zookeeper中。

数据组装降级

多库/多维度组装JSON/XML时,如果有一些不重要的数据无法获取或数据出错,可以忽略继续。

爬虫和机器人

分析机器人行为:短时间连续操作,agent,行为轨迹、拖拽(模拟登陆/秒杀/灌水)

爬虫:引到到静态页或缓存页

读降级

在一个请求内,多级缓存架构下,后端缓存或db不可用,可以使用前端缓存或兜底数据

写降级

在cap原理和BASE理论中写操作存在于数据一致性这个环节,

降级的目的是为了提供高可用性,在多数的互联网架构中,可用性是大于数据一致性的。

所以丧失写入数据同步,通过上面的理论,我们也能勉强接受数据最终一致性。

高并发场景下,写入操作无法及时到达或抗压,可以异步消费数据/cache更新/log等方式

前端降级

当系统出现问题的时候,尽量让请求隔离在离用户最近的位置,避免无效链路访问

在后端服务部分或完全不可用的时候,可以使用本地缓存或兜底数据

在一些特殊场景下,对数据一致性要求不高的时候,比如秒杀、抽奖等可以做假数据

js降级

在js中埋降级开关,在访问不到达,系统阈值的时候可以避免发送请求

接入层

可以在接入层,在用户请求还没到达服务的时候,通过、Nginx + Lua、Haproxy + lua

过滤无效请求和服务降级

应用层降级

参考常老师项目中的springcloud

片段降级

页面中异步加载的数据,有一部分无法得到

js、css无法加载 -> 兜底 css

静态化处理

在活动前可以通过静态化技术,把原来需要调用多个动态接口的页面整体缓存下来保存成一个静态文件

当动态服务无法支撑的时候,降级为静态化服务

静态文件内尽量不去异步加载数据

静态文件包含可变内容,可以使用模板技术定时生成更新

提前预埋

APP 浏览器 js/css缓存大促前