jjzjj

CAP特性与BASE理论

itzzx 2023-04-16 原文

CAP特性

​ CAP理论是在设计分布式系统的过程中,处理数据一致性问题时必须考虑的理论,一个分布式系统最多只能同时满足一致性(Consistence)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

2000年7月Eric Brewer教授仅仅提出来的是一个猜想,2年后,麻省理工学院的Seth Gilbert和Nancy Lynch从理论上证明了CAP理论,并且而一个分布式系统最多只能满足CAP中的2项。之后,CAP理论正式成为分布式计算领域的公认定理

比如Redis他就是 AP 特性(所以它才能搞可用)、 Zookeeper就是CP特性

C(一致性Consistency)

​ 所有节点在同一时间的看到的数据相同、即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致,不能存在中间状态。

分布式环境中,一致性是指多个副本之间能否保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处理一致的状态。


.png)

一致性又可分为强一致性和弱一致性&最终一致性

强一致性

​ 如果的确能像上面描述的那样时刻保证客户端看到的数据都是一致的,那么称之为强一致性、比如12306就是强一致性的、用户下单购票之后,必须要所有节点同步扣除票余额才算订票成功,避免超票的情况

最终一致性

​ 允许中间状态、只要经过一段时间后,通过定时或者其他方式、数据最终是一致性的,则称为最终一致性(比如我们生活中看到的评论这些就可以使用最终一致性)

弱一致性

​ 允许存在部门数据不一致


A(可用性Availability)

​ 服务器一直是可用的、不会出现错误、即使我数据不一致,我也会返回老的数据给你看,但是不能保证数据是否最新的

从两个维度去考虑

  • 有限时间内

    ​ 比如有一个用户下单了一个操作、必须在指定的时间内给用户响应结果、强调1s法则,不能为了保证分布式事务的一致性,需要10分钟才能处理完,10分钟才给用户响应结果、在互联网应用显然是不能接受的。

  • 返回正常结果

    ​ 客户请求了服务器、在处理用户请求的时候、服务器发生了异常,不能直接丢给用户一个 Exception、或者超时时间太长了。

客户端请求服务器的时候、服务器需要做很多处理耗时长、如果要保证A可用性的话、就可以使用异步的方式、提前给客户响应结果

P(分区容错性Partition)

​ 即使系统的某个分区遇到严重的故障,系统能继续提供服务。仍然需要能够保证对外提供满足一致性和可用性的服务、除非是整个网络环境都发生了故障

网络分区,是指分布式系统中,不同的节点分布在不同的子网络(机房/异地网络)中,由于一些特殊的原因导致这些子网络之间出现网络不连通的状态,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干孤立的区域。组成一个分布式系统的每个节点的加入与退出都可以看做是一个特殊的网络分区。

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

CAP的应用

放弃P(Partition tolerance)

放弃分区容错性的话,则放弃了分布式,放弃了系统的可扩展性、相当于就是一个单体应用了

放弃A(Availability)

​ 放弃可用性的话、架构模式就是CP 、在遇到网络分区或者其他故障的时候、为了保证数据的一致性、则需要等待一定的时间或者是直接无法使用

放弃C(Consistency)

​ 放弃一致性(指的是强一致性)、架构模式就是AP、无法保证系统数据的实时一致性、在数据达到最终一致性时,有个时间窗口,在时间窗口内,数据是不一致的。

对于分布式系统来说,P是不能放弃的,因此架构师通常是在可用性和一致性之间权衡。

CAP总结

​ 目前大多数大型系统应用都是分布式部署的、分布式场景下中的数据一致性问题一直是一个比较重要的话题。

基于CAP理论、很多系统在设计之初就要对着三者做出取舍、任何一个分布式系统都无法同时满足一致性(Consistency)可用性(Availability)分区容错性(Partition tolerance) 、最多只能同时满足两项。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证最终一致性

疑问解答

为什么分布式系统中无法同时保证一致性和可用性?

​ 首先一个前提,对于分布式系统而言,分区容错性是一个最基本的要求,因此基本上我们在设计分布式系统的时候只能从一致(Consistency)和可用性(Awailability)之间进行取舍

  • 如果保证了一致性(C):对于节点N1和N2,当往N1里写数据时,N2上的操作必须被暂停,只有当N1同步数据到N2时才能对N2进行读写请求,在N2被暂停操作期间客户端提交的请求会收到失败或超时。显然,这与可用性是相反的。
  • 如果保证了可用性(A):那就不能暂停N2的读写操作,但同时N1在写数据的话,这就违背了一致性的要求。

CAP和ACID中的A和C有什么区别?

A的区别

  • ACID中的A指的是原子性(Atomicity)、表示事务被视为一个不可分割的最小工作单元、事务中的所有操作要么全部提交成功,要么全部失败回滚;

  • CAP中的A指的是可用性(Availability) 、是指集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求;

C的区别

  • ACID一致性是有关数据库规则,指的是在执行事务前后,事务外访问数据的时候,数据是一致的,要么看到的是成功的,要么看到的是失败的结果,不会多任务查询到的数据不一样

  • CAP的一致性是分布式多服务器之间复制数据令这些服务器拥有同样的数据,由于网速限制,这种复制在不同的服务器上所消耗的时间是不固定的,集群通过组织客户端查看不同节点上还未同步的数据维持逻辑视图,这是一种分布式领域的一致性概念

ACID里的一致性指的是事务执行前后,数据库完整性,而CAP的一致性,指的是分布式节点的数据的一致性。背景不同,无从可比

Base理论

​ BASE是CAP理论的延伸、对于一致性(Consistency)我们采用的方案是保证最终一致性。

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

Basically Available(基本可用)

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

  • 响应时间上的损失、出现故障的时候,响应时间增加
  • 限流、当流量高峰的时候、限流保证系统的稳定性

Soft State(软状态)

​ 接受一段时间的状态不同步,及中间状态,而改中间状态不影响系统整体可用性。这里的中间状态就是CAP理论中的数据不一致性、允许系统在不同节点的数据副本之间进行数据同步的过程存在延时

最终一致性(Eventually consistency)

​ 系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态、其本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性

主要是对AP的补充。牺牲数据的强一致性,来保证数据的可用性,虽然存在中间装填,但数据最终一致、允许数据在一段时间内是不一致的,但最终达到一致状态

有关CAP特性与BASE理论的更多相关文章

  1. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  2. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  3. ruby-on-rails - Rails 基本 Base64 身份验证 - 2

    我正在尝试复制此GETcurl请求:curl-D--XGET-H"Authorization:BasicdGVzdEB0YXByZXNlYXJjaC5jb206NGMzMTg2Mjg4YWUyM2ZkOTY2MWNiNWRmY2NlMTkzMGU="-H"Content-Type:application/json"http://staging.example.com/api/v1/campaigns在Ruby中,通过电子邮件+apikey生成身份验证:auth="Basic"+Base64::encode64("test@example.com:4c3186288ae23fd9661c

  4. ruby-on-rails - 在 rails 中显示 base64 编码的图像 - 2

    我正在向我的Controller发送一个base64图像并按原样保存它。现在我需要显示该图像。这是我要显示的内容,但未显示图像:"/>为了编码,我使用了这个java脚本函数encodeURIComponent();我的编码图像格式:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/........ 最佳答案 你不需要解码base64应该可以 关于ruby-on-rails-在rails中显示base64编码的图像,我们在StackOve

  5. ruby-on-rails - Ruby 中属性和 base_attributes 之间的区别? - 2

    我见过几个模型定义了一个静态方法self.base_attributes{:object=>[]}end还有一些模型定义了静态方法self.attributes@@attributes={}end属性和基本属性到底有什么区别? 最佳答案 在您的示例中,您无需了解更多代码,self.attributes方法使用类变量(@@attributes),这意味着您可以添加在运行时给它更多的属性。因为您的base_attributes是硬编码的。我怀疑你看到的是这样的东西:base_attributes.merge(attributes)这可能

  6. ruby-on-rails - Rspec Controller 在 Rails 中测试继承自 AbstractController::Base 的 Controller - 2

    我正在为我未构建的应用程序编写Controller测试,因此这绝对是一个学习过程。这是我第一次遇到直接继承自AbstractController::Base的Controller。显然,它的行为与其他Controller不同。其格式大致为:classSchwadGenericController我尝试了正常测试,这是我目前要让任何事情发生的地方。require'rails_helper'describeSchwadGenericControllerdo#before(:each)do#SchwadGenericController.skip_authorize_resource#end

  7. ruby-on-rails - 从 Rails 上的 base64 编码图像中检索文件名和内容类型 - 2

    我正在尝试检索以base64编码格式接收的图像的内容类型和文件名。这是使用base64编码图像执行POST请求的代码require'net/http'require"rubygems"require'active_support'url=URI.parse('http://localhost:3000/')image=ActiveSupport::Base64.encode64(open("public/images/rails.png").to_a.join)post_params={'image'=>image}Net::HTTP.post_form(url,post_params

  8. ruby - Sinatra::Base.condition 实际上做了什么? - 2

    我遇到了sinatracondition方法,但对它的工作原理感到困惑。我有一段代码:defauthuserconditiondoredirect'/login'unlessuser_logged_in?endend它检查用户是否登录了某些路由,示例路由:get'/',:auth=>:userdoerb:indexenduser_logged_in?方法定义在项目lib目录下的帮助文件中:defuser_logged_in?ifsession[:user]@user=session[:user]return@userendreturnnilend所以,问题是:conditionbloc

  9. ruby - Ruby中Base的元类和Derived类的元类是什么关系? - 2

    在Ruby中,我们可以在单例方法中使用super来调用对应父类(superclass)的单例方法,如下面的代码所示。classBasedefself.class_methodputs"Baseclassmethod"endendclassDerived但是,我似乎不太明白Derived.class_method中对super的调用如何到达Base.class_method。我假设class_method是在他们的元类上定义的,这是否意味着他们的元类具有父/子关系?(我无法通过实验完全证实这一点)更新:我问这个问题是因为我记得在某处看到基类和派生类的元类之间存在某种关系(但我找不到它不再

  10. c# - 与 C# 相比,您会强调 Ruby 的哪些语言特性? - 2

    我正在就Ruby语言和环境向.NET(C#)开发团队进行一系列演讲。我把它当作一个机会来强调Ruby相对于C#的优势。首先,我想在进入环境之前专注于语言本身(RoR与ASPMVC等)。你会介绍Ruby语言的哪些特性? 最佳答案 我刚才在一个.NET用户组做了一个关于IronRuby的演讲,遇到了类似的问题。我关注的事情是:鸭子打字。没有什么比ListstringList=newList()更愚蠢的了;表达力强,语法简洁。简单的事情,比如省略括号、数组和散列文字等(结合鸭子类型,你会得到string_list=[]这显然更好)。所有的

随机推荐