分布式系统不得不说的CAP定理

21天学会C语言?3天学会弹钢琴?

放弃一切错误方法,从今天开始“刻意练习”,

因为这才是最强大的,也是唯一正确的学习方法。

--《刻意练习》Anders Ericsson

引言

CAP问题已经成了计算机科学中一个研究领域,之前说到分布式系统有哪些优势时讲到三个提升:

1.系统可用性提升。

2.系统并发能力提升

3.系统容错能力提升。

那么这三方面在实施起来可以同时满足吗?答案是不能,设计分布式系统的时候,设计者需要理解一个重要的理论概念,CAP定理。

BASE: Basically Available(基本可用), Soft state(软状态)和 Eventually consistent(最终一致性)

2012年Brewer发表了一篇文章,重新解释了他对CAP定理的理解:

  1. 首先,网络分区的发生是小概率事件,当网络没有发生分区的时候没有任何理由放弃C或者A

  2. 其次,在同一个系统中C和A的选择可能发生多次,不同的子系统可以做不一样的选择,当条件不同时做出的选择可以不一样,例如:不同的操作、数据、用户可能会导致不同的选择

  3. 最后,这三个属性不是0和1的选择,而是线性的。可用性很明显可以从0%到100%,其实一致性甚至分区容忍性也是有差别的

CAP分别代表什么吗?

关于CAP,它是2000 年 7 月,加州大学伯克利分校的 Eric Brewer 教授在 ACM PODC 会议上提出 CAP 猜想。2 年后,麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP。之后,CAP 理论正式成为分布式计算领域的公认定理。

  1. C的全拼是 Consistency,代表一致性的意思。

  2. A的全拼是Availability,代表可用性的意思。

  3. P的全拼是Partition tolerance,代表分区容错性的意思。

三选二:CP、AP、CA

一个分布式系统最多同时满足一致性 (Consistency),可用性 (Availability) 和分区容忍性 (Partition Tolerance) 这三项中的两项。

  • 同时满足一致性(C)和可用性(A)就要牺牲掉容错性(P)

  • 同时满足可用性(A)和分区容错性(P)就要牺牲掉一致性(C)

  • 同时满足一致性(C)和分区容错性(P)就要牺牲掉可用性(A)

这三个象限,只能同时满足其中两个圆圈的交集。

举个例子

Redis Cluster高可用架构举例:redis就能会将数据分片到多个实例(按照slot存储)中,即一个机房分担一部分数据。Master 负责写,Master会自动同步到 Slava。

Reids去中心集群架构优点:

  1. 无中心架构:三机房部署,其中一主一从构成一个分片,之间通过异步复制同步数据,异步复制存在数据不一致的时间窗口,保证高性能的同时牺牲了部分一致性一旦某个机房掉线,则分片上位于另一个机房的 slave 会被提升为 master 从而可以继续提供服务,

  2. 可扩展性:可线性扩展到1000多个节点,节点可动态添加或删除。

  3. 降低运维成本,提高系统的扩展性和可用性。

分析,这个分布式架构中满足了CAP中哪个两个定理?

优点1中讲到,三机房部署,每个机房有一主一从,即一个 Master 对应一个 Slave ,但是你会发现,机房1中的 Master 1  连接的 Slave 在机房2,机房2中的 Master 2  连接的 Slave 在机房3,机房3中的 Master 3  连接的 Slave 在机房1,这样构成一个环,为什么要这样设计?

假设:机房断电or火灾or其他各种原因,反正就是机房1所有机器都不能用了。

这个时候那机房1的全部数据都不能访问了吗?这显然是我们不希望的。前面已经说了Master 负责写,Master会自动同步到 Slava,如果 Master写服务宕机,Slave 读服务会被提升为 master ,也就是说机房1的数据在机房2的Slava2上还有备份,数据还在,在宕机的master没有恢复前 Slave 要同时承担读写服务,虽然累一点,但是还能用,这样设计是为了提高可用性(A),和容错性(P)。系统准许你一台机器或者整个机房都宕机。系统仍然能。

公众号【转行程序员】回复”加群“,我会拉你进技术群。

但是你会发现,单个机房如果距离很远, Master 1  的数据同步到 Slave2 上是跨机房,跨机房同步肯定不如同机房块,这样一来 Slave2 负责的读就会有延迟,Master1 要更新的数据还没有同步到他在另一个机房的备份前,读操作就是不一致的,这样设计显然是牺牲掉一致性(C)。相信这样分析应该能理解CAP定理了。

进一步分析:

让同一组 Master - Slave 放在一个机房,同机房复制数据不是更快?这样能不能解决数据一致(C)问题,答案是能,还有更好的解决一致性的办法就是不要Master - Slave 组合,就一台机器,一台机器同时担任读写请求,没有延迟不存在数据一致性问题。这是时候如果宕机了怎么办?这样的架构下,那就真的是不可用了,解决了一致性(C)却牺牲了可用性(A)和容错性(P),太不划算了。

总之,分布式系统下,CAP确实无法同时满足,在Reids去中心集群架构中,最优的解决方案还是满足可用性(A)和分区容错性(P)就要牺牲掉一致性(C),即使跨机房同步数据,延迟也不过1s,数据不一致的问题只出现在1s内,日常开发中,很少遇到要求强一致性的场景。例如订单系统,用户更新了订单支付状态,读订单状态是在从库,有什么读场景等不来这一秒?

如果真的必须要求强一致性,那可能就必须调整分布式架构方案来。

总结

本文主要讲解了CAP定理的概念,为什么要学习这个概念,设计高可用分布式系统时,你必须知道系统的短处,懂得CAP能让你根据实际情况有舍有得。面试会被经常问到,比如,你说你使用了消息队列,解决了系统耦合问题,提高了响应速度,那面试官问题:使用消息队列有啥缺点?如果你知道CAP定理这个问题还难吗?

显然消息的延迟会带来数据不一致问题。理想情况下消息不丢失那数据会最终一致,你能保证消息不丢失吗?如何解决机问题,如果是我,我会选择“最终一致性”,就是说不管消息延迟多久甚至丢失,设计一个离线定时任务,定期去扫描两个系统的数据,有不一致的情况就主动刷新同步,这样保证最终一致。

参考资料

  • CAP theorem – Wikipedia

  • CAP Twelve Years Later: How the “Rules” Have Changed

联系我

VX搜索【转行程序员】回复”加群“,我会拉你进技术群。讲真的,在这个群,哪怕您不说话,光看聊天记录也是一种成长。阿里/腾讯/百度资深工程师、Google技术大神、IBM工程师、还有我王炸、敖丙、各路大牛都在,有任何不明白的都进群提问。

最后,觉得王炸的文章不错就来个三连吧:关注 转发 点赞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[PAT乙级]1021 个位数统计

输入格式: 每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。 输出格式: 对 N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。 输入样例:…

Largest Rectangle in a Histogram (动态规划+奇思妙想单调栈)求最大矩状图面积

感觉动态规划都是玄妙的很,思维题吧(单调栈思维) 题解:让求最大矩形面积,宽为1,暴力超时 可以发现 当第i-1个比第i个高的时候 比第i-1个高的所有也一定比第i个高 于是可以用到动态规划的思想 令l…

ASP.NET Core分布式项目实战(详解oauth2授权码流程)--学习笔记

最近公司产品上线,通宵加班了一个月,一直没有更新,今天开始恢复,每日一更,冲冲冲任务13:详解oauth2授权码流程我们即将开发的产品有一个用户 API,一个项目服务 API,每个服务都需要认…

C++类模板中的static成员

从类模板实例化的每一个模板类有自己的类模板数据成员&#xff0c;该模板的所有对象共享一个static数据成员。 代码如下: #include <iostream> using namespace std;template<typename T> class Person { public:static int a;};template<typename T> int …

C#并发编程之初识并行编程

写在前面之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容&#xff0c;因为手中商城的重构工作量较大&#xff0c;一时之间无法抽出时间。近日&#xff0c;这套系统已有阶段性成果&#xff0c;所以准备写一下Parallel的相关内容&#xff0c;正好也延续之前的…

java 下拉列表 枚举_「Java三分钟」精准而优雅——枚举类详解

关注我&#xff0c;每天三分钟&#xff0c;带你轻松掌握一个Java相关知识点。1.为什么要用枚举你在读一个老工程代码时&#xff0c;是否经常看见有几个类&#xff0c;里面放着成百上千的静态常量&#xff0c;场面相当恐怖&#xff0c;而且如果不加注释&#xff0c;很多你都不知…

Not so Mobile(二叉树递归输入同时建树){天平}

题意&#xff1a; 给出一个大天平&#xff0c;大天平中还有许多小天平&#xff0c;求出所有的天平是否平衡&#xff1b;平衡条件为wldl wrdr&#xff1b; 题目 Before being an ubiquous communications gadget, a mobile was just a structure made of strings and wires …

在阿里云函数计算上部署.NET Core 3.1

使用阿里云ECS或者其他常见的VPS服务部署应用的时候&#xff0c;需要手动配置环境&#xff0c;并且监测ECS的行为&#xff0c;做补丁之类的&#xff0c;搞得有点复杂。好在很多云厂商&#xff08;阿里云、Azure等&#xff09;提供了Serverless服务&#xff0c;借助于Serverless…

java 持续交付_【Java架构:持续交付】一篇文章搞掂:Jenkins

1.1、使用yum安装JDKa、检查系统是否有安装open-jdkrpm -qa |grep javarpm -qa |grep jdkrpm -qa |grep gcj如果没有输入信息表示没有安装。如果安装可以使用rpm -qa | grep java | xargs rpm -e --nodeps 批量卸载所有带有Java的文件 这句命令的关键字是javab、检索yum中包含…

抱歉,请不要把 “业务逻辑层” 理解为 “业务中台”

这是头哥侃码的第197篇原创在IAS2019中台架构峰会上&#xff0c;我曾与一位年轻帅气的技术小伙来了一番有趣的对话。因为和朋友有约&#xff0c;所以我在现场互动结束之后&#xff0c;就急匆匆地跟其他嘉宾打了声招呼&#xff0c;抱着笔记本冲出了会场。但没想到刚到电梯口&…

C++异常处理分析

C异常处理基本语法: 代码如下: #include <iostream> using namespace std;int divide(int x, int y) {if (y 0) throw y;return x / y; }void test01() {//试着去捕获异常try{divide(10, 0);}/*catch (int){cout << "除数为0!" << endl;} */catc…

陌陌的 Service Mesh 探索与实践

Service Mesh Virtual Meetup 是 ServiceMesher 社区和 CNCF 联合主办的线上系列直播。本期为 Service Mesh Virtual Meetup#1 &#xff0c;邀请了四位来自不同公司的嘉宾&#xff0c;从不同角度展开了 Service Mesh 的应用实践分享&#xff0c;分享涵盖来自陌陌和百度的 Servi…

C标准输入流

标准输入流对象cin&#xff0c;重点掌握的函数: cin.get()//一次只能读取一个字符 cin.get(一次参数)//读一个字符 cin.get(两个字符)//可以读字符串 cin.getline() cin.ignore() cin.peek() cin.putback() 标准输入流cin.get() 代码如下: #include <iostream> using n…

Harmonic Number(欧拉公式或技巧打表)LightOJ - 1234(求调和级数的和)

题意&#xff1a;求f(n)1/11/21/31/4…1/n (1 ≤ n ≤ 108).&#xff0c;精确到10-8 (原题在文末&#xff09; 知识点&#xff1a;调和级数(即f(n))至今没有一个完全正确的公式&#xff0c;但欧拉给出过一个近似公式&#xff1a;(n很大时) f(n)≈ln(n)C1/2*n 欧拉常数值&…

教你配置windows上的windbg,linux上的lldb,打入clr内部这一篇就够了

一&#xff1a;背景1. 讲故事前几天公众号里有位兄弟看了几篇文章之后&#xff0c;也准备用windbg试试看&#xff0c;结果这一配就花了好几天&#xff0c;(づ╥﹏╥)づ&#xff0c;我想也有很多跃跃欲试的朋友在配置的时候肯定会遇到这样和那样的问题&#xff0c;所以我觉得有必…

C标准输出流

标准输入流对象cin&#xff0c;重点掌握的函数: cout.flush()//刷新缓冲区 cout.put()//向缓冲区写字符 cout.write()//二进制流的输出 cout.width()//输出格式控制 cout.fill() cout.set(标记) cout.flush() 代码如下: #include <iostream> using namespace std;void…

Autofac在.NET Core 中的使用

前言Autofac 是一款.NET IoC 容器 . 它管理类之间的依赖关系, 从而使应用在规模及复杂性增长的情况下依然可以轻易地修改 。.NET CORE 中也内置了依赖注入&#xff0c;但是有些情况下需要用到Autofac去进行依赖注入&#xff0c;Autofac支持的所有注入方式以外&#xff0c;还支持…

详解.NET Core 依赖注入生命周期

前言.NET Core 自带依赖注入框架&#xff0c;支持三种不同生命周期的注入模式&#xff1a;Singleton 单例模式Scoped 区域模式Transient 瞬时模式但是常常不知道什么时候使用哪种模式才最合适&#xff0c;接下来我就用代码详细解读一下三种模式代码示例首先新建.NET Core API…

[C++STL]string容器用法介绍

string构造函数 代码如下: #include <iostream> #include <string> using namespace std;void test01() {string s1;cout << "s1 " << s1 << endl;const char *str "hello world";string s2(str);cout << "s2…

致敬平凡的程序员--《SOD框架“企业级”应用数据架构实战》自序

“简单就是美”“平凡即是伟大”上面两句话不知道是哪位名人说的&#xff0c;又或者是广大劳动人民总结的&#xff0c;反正我很小的时候就常常听到这两句话&#xff0c;这两句话也成了我的人生格言&#xff0c;而且事实上我也是一个生活过得比较简单的平凡人物&#xff0c;当然…