为您推荐:
精华内容
最热下载
问答
  • 5星
    866B qq_33064191 2021-08-16 14:35:51
  • 5星
    7.18MB GZXGYZ 2021-03-19 23:49:43
  • 5星
    248KB GZXGYZ 2021-03-25 08:27:42
  • 5星
    228KB GZXGYZ 2021-03-19 21:52:40
  • 5星
    11.72MB GZXGYZ 2021-03-19 21:21:29
  • 2000年7月,加州大学伯克利分校的Eric Brewer教授在ACM PODC会议上提出...之后,CAP理论正式成为分布式计算领域的公认定理。 无论你是一个系统架构师,还是一个普通开发,当你开发或者设计一个分布式系统的时候,...

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

    无论你是一个系统架构师,还是一个普通开发,当你开发或者设计一个分布式系统的时候,CAP理论是无论如何也绕不过去的。本文就来介绍一下到底什么是CAP理论,如何证明CAP理论,以及CAP的权衡问题。

    CAP理论概述

    CAP理论:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

    Teorema-CAP-2

    读者需要注意的的是,CAP理论中的CA和数据库事务中ACID的CA并完全是同一回事儿。两者之中的A都是C都是一致性(Consistency)。CAP中的A指的是可用性(Availability),而ACID中的A指的是原子性(Atomicity),切勿混为一谈。

    CAP的定义

    Consistency 一致性

    一致性指“all nodes see the same data at the same time”,即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致,所以,一致性,说的就是数据一致性。分布式的一致性

    对于一致性,可以分为从客户端和服务端两个不同的视角。从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。

    一致性是因为有并发读写才有的问题,因此在理解一致性的问题时,一定要注意结合考虑并发读写的场景。

    从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。

    三种一致性策略

    对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。

    如果能容忍后续的部分或者全部访问不到,则是弱一致性。

    如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。

    CAP中说,不可能同时满足的这个一致性指的是强一致性。

    Availability 可用性

    可用性指“Reads and writes always succeed”,即服务一直可用,而且是正常响应时间。

    对于一个可用性的分布式系统,每一个非故障的节点必须对每一个请求作出响应。所以,一般我们在衡量一个系统的可用性的时候,都是通过停机时间来计算的。

    可用性分类可用水平(%)年可容忍停机时间
    容错可用性99.9999<1 min
    极高可用性99.999<5 min
    具有故障自动恢复能力的可用性99.99<53 min
    高可用性99.9<8.8h
    商品可用性99<43.8 min

    通常我们描述一个系统的可用性时,我们说淘宝的系统可用性可以达到5个9,意思就是说他的可用水平是99.999%,即全年停机时间不超过 (1-0.99999)*365*24*60 = 5.256 min,这是一个极高的要求。

    好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。一个分布式系统,上下游设计很多系统如负载均衡、WEB服务器、应用代码、数据库服务器等,任何一个节点的不稳定都可以影响可用性。

    Partition Tolerance分区容错性

    分区容错性指“the system continues to operate despite arbitrary message loss or failure of part of the system”,即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

    分区容错性和扩展性紧密相关。在分布式应用中,可能因为一些分布式的原因导致系统无法正常运转。好的分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,或者是机器之间有网络异常,将分布式系统分隔未独立的几个部分,各个部分还能维持分布式系统的运作,这样就具有好的分区容错性。

    简单点说,就是在网络中断,消息丢失的情况下,系统如果还能正常工作,就是有比较好的分区容错性。

    CAP的证明

    intro_thumb

    如上图,是我们证明CAP的基本场景,网络中有两个节点N1和N2,可以简单的理解N1和N2分别是两台计算机,他们之间网络可以连通,N1中有一个应用程序A,和一个数据库V,N2也有一个应用程序B2和一个数据库V。现在,A和B是分布式系统的两个部分,V是分布式系统的数据存储的两个子数据库。

    在满足一致性的时候,N1和N2中的数据是一样的,V0=V0。在满足可用性的时候,用户不管是请求N1或者N2,都会得到立即响应。在满足分区容错性的情况下,N1和N2有任何一方宕机,或者网络不通的时候,都不会影响N1和N2彼此之间的正常运作。

    scenario1_thumb

    如上图,是分布式系统正常运转的流程,用户向N1机器请求数据更新,程序A更新数据库Vo为V1,分布式系统将数据进行同步操作M,将V1同步的N2中V0,使得N2中的数据V0也更新为V1,N2中的数据再响应N2的请求。

    这里,可以定义N1和N2的数据库V之间的数据是否一样为一致性;外部对N1和N2的请求响应为可用行;N1和N2之间的网络环境为分区容错性。这是正常运作的场景,也是理想的场景,然而现实是残酷的,当错误发生的时候,一致性和可用性还有分区容错性,是否能同时满足,还是说要进行取舍呢?

    作为一个分布式系统,它和单机系统的最大区别,就在于网络,现在假设一种极端情况,N1和N2之间的网络断开了,我们要支持这种网络异常,相当于要满足分区容错性,能不能同时满足一致性和响应性呢?还是说要对他们进行取舍。

    scenario2_thumb

    假设在N1和N2之间网络断开的时候,有用户向N1发送数据更新请求,那N1中的数据V0将被更新为V1,由于网络是断开的,所以分布式系统同步操作M,所以N2中的数据依旧是V0;这个时候,有用户向N2发送数据读取请求,由于数据还没有进行同步,应用程序没办法立即给用户返回最新的数据V1,怎么办呢?

    有二种选择,第一,牺牲数据一致性,保证可用性。响应旧的数据V0给用户;

    第二,牺牲可用性,保证数据一致性。阻塞等待,直到网络连接恢复,数据更新操作M完成之后,再给用户响应最新的数据V1。

    这个过程,证明了要满足分区容错性的分布式系统,只能在一致性和可用性两者中,选择其中一个。

    CAP权衡

    通过CAP理论及前面的证明,我们知道无法同时满足一致性、可用性和分区容错性这三个特性,那要舍弃哪个呢?

    我们分三种情况来阐述一下。

    CA without P

    这种情况在分布式系统中几乎是不存在的。首先在分布式环境下,网络分区是一个自然的事实。因为分区是必然的,所以如果舍弃P,意味着要舍弃分布式系统。那也就没有必要再讨论CAP理论了。这也是为什么在前面的CAP证明中,我们以系统满足P为前提论述了无法同时满足C和A。

    比如我们熟知的关系型数据库,如My Sql和Oracle就是保证了可用性和数据一致性,但是他并不是个分布式系统。一旦关系型数据库要考虑主备同步、集群部署等就必须要把P也考虑进来。

    其实,在CAP理论中。C,A,P三者并不是平等的,CAP之父在《Spanner,真时,CAP理论》一文中写到:

    如果说Spanner真有什么特别之处,那就是谷歌的广域网。Google通过建立私有网络以及强大的网络工程能力来保证P,在多年运营改进的基础上,在生产环境中可以最大程度的减少分区发生,从而实现高可用性。

    从Google的经验中可以得到的结论是,无法通过降低CA来提升P。要想提升系统的分区容错性,需要通过提升基础设施的稳定性来保障。

    所以,对于一个分布式系统来说。P是一个基本要求,CAP三者中,只能在CA两者之间做权衡,并且要想尽办法提升P。

    CP without A

    如果一个分布式系统不要求强的可用性,即容许系统停机或者长时间无响应的话,就可以在CAP三者中保障CP而舍弃A。

    一个保证了CP而一个舍弃了A的分布式系统,一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统。

    设计成CP的系统其实也不少,其中最典型的就是很多分布式数据库,他们都是设计成CP的。在发生极端情况时,优先保证数据的强一致性,代价就是舍弃系统的可用性。如Redis、HBase等,还有分布式系统中常用的Zookeeper也是在CAP三者之中选择优先保证CP的。

    无论是像Redis、HBase这种分布式存储系统,还是像Zookeeper这种分布式协调组件。数据的一致性是他们最最基本的要求。一个连数据一致性都保证不了的分布式存储要他有何用?

    在我的Zookeeper介绍(二)——Zookeeper概述一文中其实介绍过zk关于CAP的思考,这里再简单回顾一下:

    ZooKeeper是个CP(一致性+分区容错性)的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性。但是它不能保证每次服务请求的可用性,也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果。ZooKeeper是分布式协调服务,它的职责是保证数据在其管辖下的所有服务之间保持同步、一致。所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了。

    AP wihtout C

    要高可用并允许分区,则需放弃一致性。一旦网络问题发生,节点之间可能会失去联系。为了保证高可用,需要在用户访问时可以马上得到返回,则每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。

    这种舍弃强一致性而保证系统的分区容错性和可用性的场景和案例非常多。前面我们介绍可用性的时候说到过,很多系统在可用性方面会做很多事情来保证系统的全年可用性可以达到N个9,所以,对于很多业务系统来说,比如淘宝的购物,12306的买票。都是在可用性和一致性之间舍弃了一致性而选择可用性。

    你在12306买票的时候肯定遇到过这种场景,当你购买的时候提示你是有票的(但是可能实际已经没票了),你也正常的去输入验证码,下单了。但是过了一会系统提示你下单失败,余票不足。这其实就是先在可用性方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲,会影响一些用户体验,但是也不至于造成用户流程的严重阻塞。

    但是,我们说很多网站牺牲了一致性,选择了可用性,这其实也不准确的。就比如上面的买票的例子,其实舍弃的只是强一致性。退而求其次保证了最终一致性。也就是说,虽然下单的瞬间,关于车票的库存可能存在数据不一致的情况,但是过了一段时间,还是要保证最终一致性的。

    对于多数大型互联网应用的场景,主机众多、部署分散,而且现在的集群规模越来越大,所以节点故障、网络故障是常态,而且要保证服务可用性达到N个9,即保证P和A,舍弃C(退而求其次保证最终一致性)。虽然某些地方会影响客户体验,但没达到造成用户流程的严重程度。

    适合的才是最好的

    上面介绍了如何CAP中权衡及取舍以及典型的案例。孰优孰略,没有定论,只能根据场景定夺,适合的才是最好的。

    对于涉及到钱财这样不能有一丝让步的场景,C必须保证。网络发生故障宁可停止服务,这是保证CA,舍弃P。比如前几年支付宝光缆被挖断的事件,在网络出现故障的时候,支付宝就在可用性和数据一致性之间选择了数据一致性,用户感受到的是支付宝系统长时间宕机,但是其实背后是无数的工程师在恢复数据,保证数数据的一致性。

    对于其他场景,比较普遍的做法是选择可用性和分区容错性,舍弃强一致性,退而求其次使用最终一致性来保证数据的安全。这其实是分布式领域的另外一个理论——BASE理论。我们下一篇文章再来介绍。

    总结

    无论你是一个架构师,还是一个普通开发,在设计或开发分布式系统的时候,不可避免的要在CAP中做权衡。需要根据自己的系统的实际情况,选择最适合自己的方案。

    参考资料:

    CAP和BASE理论

    CAP原理的证明

    一文带你重新审视CAP理论与分布式系统设计

    拓展阅读:

    CAP理论

    (全文完)
    欢迎关注HollisChuang微信公众账号

    如未加特殊说明,此网站文章均为原创,转载必须注明出处。HollisChuang’s Blog » 分布式系统的CAP理论

    分享到: 更多 ( 4)
    收藏文章
    有事没事说两句…
    表情删除后不可恢复,是否删除
    取消
    确定
    图片正在上传,请稍后…
    取消上传
    评论内容为空!
                <!-- 放置cbox发布状态 -->
                <!-- 提示条 -->
                <!-- 零评论提示条 -->
                <div class="list-comment-empty-w">
    
                </div>
                <!-- 提示连接到快站社区 -->
                <!-- <div class="list-comment-kuaizhan-w">
                    <div node-type="kuaizhan-prompt" class="kuaizhan-prompt-w">
                        <span class="prompt-text-w">点击查看更多精彩内容</span>
                    </div>
                </div> -->
                <!--关闭评论-->
                <div class="list-close-comment-w">
    
                </div>
            </div>
        </div>
    </div>
    

    • 评论
    5人参与,5条评论
    • 最新评论
    2018年7月6日 10:21 斑驳的时光 [广东省网友]

    最近在公司实习,遇到分布式相关的东西,需要一下zookeeper相关的知识,看了你一系列文章,真的写的很好,受教了。

    举报 回复
    2018年5月19日 14:45 醉温柔 [北京市网友]

    写的真好,学习了,转载了

    举报 回复
    2017年9月10日 0:10 小明6号1224 [湖北省武汉市网友]

    谢谢

    举报 回复
    2016年6月17日 10:33 坏坏的可乐 [北京市网友]

    文章很赞

    举报 回复
    2016年2月17日 14:54 阿杜 [上海市网友]

    文章很赞,向你学习

    举报 回复

            HollisChuang正在使用畅言
                        </a>
        </div>
    </div>
    <div node-type="cy-to-shequ" class="cy-redirect-btn">
        <span class="cy-redirect-text">去社区看看吧</span><i class="cy-right-arrow"></i>
    </div>
    <div node-type="cy-to-hots" class="cy-redirect-btn">
        <span class="cy-redirect-text">去热评看看吧</span><i class="cy-right-arrow"></i>
    </div>
    <div class="cy-to-shequ-float"></div>
    



    关闭
















    按钮

    内容不能为空!



    立刻说两句吧!
    查看5条评论







    •     <li node-type="notice-message" data-alias="message" data-type="message" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">你收到<i>0</i>条新通知</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
      
          <li node-type="notice-support" data-alias="support" data-type="support" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">你有<i>0</i>条评论收到赞同</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
      
          <li node-type="notice-reply" data-alias="reply" data-type="reply" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">你有<i>0</i>条新回复</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
      
          <li node-type="notice-hots" data-alias="hots" data-type="hots" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">本日畅言热评新鲜出炉啦!</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
      
          <li node-type="notice-task" data-alias="task" data-type="task" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">你有<i>0</i>个任务已完成</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
      
          <li node-type="notice-history" data-alias="history" data-type="history" data-static="static" class="nt-item" style=" display: none ">
              <div class="nt-logo"></div>
              <a node-type="notice-content" class="nt-text" href="javascript:void(0);">你收获<i>0</i>个畅言足迹</a>
              <a class="nt-close" href="javascript:void(0);"></a>
          </li>
              </ul>
      


    if(window.screen.width > 960) {
    (function(){var appid = 'cyrFnsBtC',conf = 'prod_957fbae232bab98fce4551fdee712071';
    var doc = document,
    s = doc.createElement('script'),
    h = doc.getElementsByTagName('head')[0] || doc.head || doc.documentElement;
    s.type = 'text/javascript';
    s.charset = 'utf-8';
    s.src = ' http://assets.changyan.sohu.com/upload/changyan.js?conf=' + conf + '&appid=' + appid;
    h.insertBefore(s,h.firstChild);
    })()
    } else {
    (function(){
    var expire_time = parseInt((new Date()).getTime()/(5*60*1000));
    var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
    var script_version = document.createElement("script"),script_cyan = document.createElement("script");
    script_version.type = script_cyan.type = "text/javascript";
    script_version.charset = script_cyan.charset = "utf-8";
    script_version.onload = function(){
    script_cyan.id = 'changyan_mobile_js';
    script_cyan.src = ' http://changyan.itc.cn/upload/mobile/wap-js/changyan_mobile.js?client_id=cyrFnsBtC&conf=prod_957fbae232bab98fce4551fdee712071&version=cyan_resource_version';
    head.insertBefore(script_cyan, head.firstChild);
    };
    script_version.src = ' http://changyan.sohu.com/upload/mobile/wap-js/version.js?='+expire_time;
    head.insertBefore(script_version, head.firstChild);
    })();
    1. 文章很赞,向你学习[/强]

              </article>
          </li><!-- #comment-## -->
          <li class="comment odd alt thread-odd thread-alt depth-1" id="li-comment-331">
              <article id="comment-331" class="comment">
                  <footer class="comment-meta">
                      <cite class="comment-author vcard">
                          <span class="fn">坏坏的可乐</span> on <a rel="nofollow" href="http://www.hollischuang.com/archives/666#comment-331"><time pubdate="" datetime="2016-06-17T10:33:23+00:00">2016年6月17日 at 上午10:33</time></a> <span class="says">said:</span>                   </cite>
                  </footer>
      
                  <div class="comment-content"><p>文章很赞</p>
      

            </article>
        </li><!-- #comment-## -->
        <li class="comment even thread-even depth-1" id="li-comment-645">
            <article id="comment-645" class="comment">
                <footer class="comment-meta">
                    <cite class="comment-author vcard">
                        <span class="fn">小明6号1224</span> on <a rel="nofollow" href="http://www.hollischuang.com/archives/666#comment-645"><time pubdate="" datetime="2017-09-10T00:10:20+00:00">2017年9月10日 at 上午12:10</time></a> <span class="says">said:</span>                    </cite>
                </footer>
    
                <div class="comment-content"><p>谢谢</p>
    

            </article>
        </li><!-- #comment-## -->
        <li class="comment odd alt thread-odd thread-alt depth-1" id="li-comment-850">
            <article id="comment-850" class="comment">
                <footer class="comment-meta">
                    <cite class="comment-author vcard">
                        <span class="fn">醉温柔</span> on <a rel="nofollow" href="http://www.hollischuang.com/archives/666#comment-850"><time pubdate="" datetime="2018-05-19T14:45:24+00:00">2018年5月19日 at 下午2:45</time></a> <span class="says">said:</span>                  </cite>
                </footer>
    
                <div class="comment-content"><p>写的真好,学习了,转载了</p>
    

            </article>
        </li><!-- #comment-## -->
        <li class="comment even thread-even depth-1" id="li-comment-938">
            <article id="comment-938" class="comment">
                <footer class="comment-meta">
                    <cite class="comment-author vcard">
                        <span class="fn">斑驳的时光</span> on <a rel="nofollow" href="http://www.hollischuang.com/archives/666#comment-938"><time pubdate="" datetime="2018-07-06T10:21:24+00:00">2018年7月6日 at 上午10:21</time></a> <span class="says">said:</span>                    </cite>
                </footer>
    
                <div class="comment-content"><p>最近在公司实习,遇到分布式相关的东西,需要一下zookeeper相关的知识,看了你一系列文章,真的写的很好,受教了。</p>
    

            </article>
        </li><!-- #comment-## -->
            </ol>
    
            </div>
    </div>
    
    展开全文
    MOVIE14 2018-09-17 14:30:01
  • 如何正确理解CAP理论?在大数据领域,被业界广泛谈及的CAP理论存在着一些关键性的认知误区,而只有全面地考察与分析分布式环境中的各种场景,我们才能真正正确地理解它。目前,CAP(Consistency一致性、Availability...

    如何正确理解CAP理论?

    在大数据领域,被业界广泛谈及的CAP理论存在着一些关键性的认知误区,而只有全面地考察与分析分布式环境中的各种场景,我们才能真正正确地理解它。

    目前,CAP(Consistency一致性、Availability可用性、Partition-tolerance分区可容忍性)理论普遍被当作是大数据技术的理论基础。同时,根据该理论,业界有一种非常流行、非常“专业”的认识,那就是:关系型数据库设计选择了C(一致性)与A(可用性),NoSQL数据库设计则不同。其中,HBase选择了C(一致性)与P(分区可容忍性),Cassandra选择了A(可用性)与P(分区可容忍性)。

    该说法现在似乎已经成为一种经典认知,无论是初学大数据技术,还是已经有了相当经验的技术人员,都将其奉为真理。大家大概是认为,从CAP这样著名的理论推导出来的结论,当然是权威而又正确的,最起码在形式上感觉是专业而又严肃的。有人甚至还将这种认知画成一个三角形图,三个顶点分别是C、A、P,三条边分别是关系型数据库、HBase与Cassandra,这样一来,CAP理论就显然更加神圣了。

    实际上,这种认识是不准确的,甚至是不正确的。暂且不说深入的分析与研究,只要先从表面上简单分析一下,你就能发现问题:难道说从理论上讲Cassandra就一定比HBase的可用性更高吗?而要要彻底搞清楚这个问题,还得先从CAP理论本身开始研究。

    常见的理解及分析

    目前流行的、对CAP理论解释的情形是从同一数据在网络环境中的多个副本出发的。为了保证数据不会丢失,在企业级的数据管理方案中,一般必须考虑数据的冗余存储问题,而这应该是通过在网络上的其他独立物理存储节点上保留另一份、或多份数据副本来实现的(如附图所示)。因为在同一个存储节点上的数据冗余明显不能解决单点故障问题,这与通过多节点集群来提供更好的计算可用性的道理是相同的。

    附图 CAP理论示意图

    其实,不用做严格的证明也可以想见,如附图的情况,数据在节点A、B、C上保留了三份,如果对节点A上的数据进行了修改,然后再让客户端通过网络对该数据进行读取。那么,客户端的读取操作什么时候返回呢?

    有这样两种情况:一种情况是要求节点A、B、C的三份数据完全一致后返回。也就是说,这时从任何一个网络节点读取的数据都是一样的,这就是所谓的强一致性读。很明显,这时数据读取的Latency要高一些(因为要等数据在网络中的复制),同时A、B、C三个节点中任何一个宕机,都会导致数据不可用。也就是说,要保证强一致性,网络中的副本越多,数据的可用性就越差;

    另一种情况是,允许读操作立即返回,容忍B节点的读取与A节点的读取不一致的情况发生。这样一来,可用性显然得到了提高,网络中的副本也可以多一些,唯一得不到保证的是数据一致性。当然,对写操作同样也有多个节点一致性的情况,在此不再赘述。

    可以看出,上述对CAP理论的解释主要是从网络上多个节点之间的读写一致性出发考虑问题的。而这一点,对于关系型数据库意味着什么呢?当然主要是指通常所说的Standby(关于分布式事务,涉及到更多考虑,随后讨论)情况。对此,在实践中我们大多已经采取了弱一致性的异步延时同步方案,以提高可用性。这种情况并不存在关系型数据库为保证C、A而放弃P的情况;而对海量数据管理的需求,关系型数据库扩展过程中所遇到的性能瓶颈,似乎也并不是CAP理论中所描述的那种原因造成的。那么,上述流行的说法中所描述的关系型数据库为保证C、A而牺牲P到底是在指什么呢?

    因此,如果根据现有的大多数资料对CAP理论的如上解释,即只将其当作分布式系统中多个数据副本之间的读写一致性问题的通用理论对待,那么就可以得出结论:CAP既适用于NoSQL数据库,也适用于关系型数据库。它是NoSQL数据库、关系型数据库,乃至一切分布式系统在设计数据多个副本之间读写一致性问题时需要遵循的共同原则。

    更深入的探究:两种重要的分布式场景

    在本文中我们要说的重点与核心是:关于对CAP理论中一致性C的理解,除了上述数据副本之间的读写一致性以外,分布式环境中还有两种非常重要的场景,如果不对它们进行认识与讨论,就永远无法全面地理解CAP,当然也就无法根据CAP做出正确的解释。但可惜的是,目前为止却很少有人提及这两种场景:那就是事务与关联。

    先来看看分布式环境中的事务场景。我们知道,在关系型数据库的事务操作遵循ACID原则,其中的一致性C,主要是指一个事务中相关联的数据在事务操作结束后是一致的。所谓ACID原则,是指在写入/异动资料的过程中,为保证交易正确可靠所必须具备的四个特性:即原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)和持久性(Durability)。

    例如银行的一个存款交易事务,将导致交易流水表增加一条记录。同时,必须导致账户表余额发生变化,这两个操作必须是一个事务中全部完成,保证相关数据的一致性。而前文解释的CAP理论中的C是指对一个数据多个备份的读写一致性。表面上看,这两者不是一回事,但实际上,却是本质基本相同的事物:数据请求会等待多个相关数据操作全部完成才返回。对分布式系统来讲,这就是我们通常所说的分布式事务问题。

    众所周知,分布式事务一般采用两阶段提交策略来实现,这是一个非常耗时的复杂过程,会严重影响系统效率,在实践中我们尽量避免使用它。在实践过程中,如果我们为了扩展数据容量将数据分布式存储,而事务的要求又完全不能降低。那么,系统的可用性一定会大大降低,在现实中我们一般都采用对这些数据不分散存储的策略。

    当然,我们也可以说,最常使用的关系型数据库,因为这个原因,扩展性(分区可容忍性P)受到了限制,这是完全符合CAP理论的。但同时我们应该意识到,这对NoSQL数据库也是一样的。如果NoSQL数据库也要求严格的分布式事务功能,情况并不会比关系型数据库好多少。只是在NoSQL的设计中,我们往往会弱化甚至去除事务的功能,该问题才表现得不那么明显而已。

    因此,在扩展性问题上,如果要说关系型数据库是为了保证C、A而牺牲P,在尽量避免分布式事务这一点上来看,应该是正确的。也就是说:关系型数据库应该具有强大的事务功能,如果分区扩展,可用性就会降低;而NoSQL数据库干脆弱化甚至去除了事务功能,因此,分区的可扩展性就大大增加了。

    再来看看分布式环境中的关联场景。初看起来,关系型数据库中常用的多表关联操作与CAP理论就更加不沾边了。但仔细考虑,也可以用它来解释数据库分区扩展对关联所带来的影响。对一个数据库来讲,采用了分区扩展策略来扩充容量,数据分散存储了,很显然多表关联的性能就会下降,因为我们必须在网络上进行大量的数据迁移操作,这与CAP理论中数据副本之间的同步操作本质上也是相同的。

    因此,如果要保证系统的高可用性,需要同时实现强大的多表关系操作的关系型数据库在分区可扩展性上就遇到了极大的限制(即使是那些采用了各种优秀解决方案的MPP架构的关系型数据库,如TeraData,Netezza等,其水平可扩展性也是远远不如NoSQL数据库的),而NoSQL数据库则干脆在设计上弱化甚至去除了多表关联操作。那么,从这一点上来理解“NoSQL数据库是为了保证A与P,而牺牲C”的说法,也是可以讲得通的。当然,我们应该理解,关联问题在很多情况下不是并行处理的优点所在,这在很大程度上与Amdahl定律相符合。

    所以,从事务与关联的角度来关系型数据库的分区可扩展性为什么受限的原因是最为清楚的。而NoSQL数据库也正是因为弱化,甚至去除了像事务与关联(全面地讲,其实还有索引等特性)等在分布式环境中会严重影响系统可用性的功能,才获得了更好的水平可扩展性。

    那么,如果将事务与关联也纳入CAP理论中一致性C的范畴的话,问题就很清楚了:关于“关系型数据库为了保证一致性C与可用性A,而不得不牺牲分区可容忍性P”的说法便是正确的了。但关于“NoSQL选择了C与P,或者A与P”的说法则是错误的,所有的NoSQL数据库在设计策略的大方向上都是选择了A与P(虽然对同一数据多个副本的读写一致性问题的设计各有不同),从来没有完全选择C与P的情况存在。

    结论

    现在看来,如果理解CAP理论只是指多个数据副本之间读写一致性的问题,那么它对关系型数据库与NoSQL数据库来讲是完全一样的,它只是运行在分布式环境中的数据管理设施在设计读写一致性问题时需要遵循的一个原则而已,却并不是NoSQL数据库具有优秀的水平可扩展性的真正原因。而如果将CAP理论中的一致性C理解为读写一致性、事务与关联操作的综合,则可以认为关系型数据库选择了C与A,而NoSQL数据库则全都是选择了A与P,但并没有选择C与P的情况存在。这才是用CAP理论来支持NoSQL数据库设计正确认识。

    其实,这种认识正好与被广泛认同的NoSQL的另一个理论基础相吻合,即与ACID对着干的BASE(基本可用性、软状态与最终一致性)。因为BASE的含义正好是指“NoSQL数据库设计可以通过牺牲一定的数据一致性和容错性来换取高性能的保持甚至提高”,即NoSQL数据库都应该是牺牲C来换取P,而不是牺牲A。可用性A正好是所有NoSQL数据库都普遍追求的特性。

    展开全文
    weixin_39958631 2020-12-20 12:31:49
  • https://blog.csdn.net/youanyyou/article/details/78990000

    https://blog.csdn.net/youanyyou/article/details/78990000

    展开全文
    joys_m 2021-03-25 17:09:01
  • CAP 理论指的就是,在分布式系统中 C、A、P 这三个特征不能同时满足,只能满足其中两 个。 网络中有两台服务器 Server1 和 Server2,分别部署了数据库 DB1 和 DB2, 这两台机器组成一个服务集群,DB1 和 DB2 两个...

    C 代表 Consistency,一致性,是指所有节点在同一时刻的数据 是相同的,即更新操作执行结束并响应用户完成后,所有节点存储的数据会保持相同。

    A 代表 Availability,可用性,是指系统提供的服务一直处于可用状态, 对于用户的请求可即时响应。

    P 代表 Partition Tolerance,分区容错性,是指在分布式系统遇到 网络分区的情况下,仍然可以响应用户的请求。网络分区是指因为网络故障导致网络不连 通,不同节点分布在不同的子网络中,各个子网络内网络正常。

    在电商系统中,假设 C 与 A 和 B 的网络都不通了,A 和 B 是相通的。也就是说,形成了两 个分区{A, B}和{C},在这种情况下,系统仍能响应用户请求。

    CAP 理论指的就是,在分布式系统中 C、A、P 这三个特征不能同时满足,只能满足其中两 个。

    网络中有两台服务器 Server1 和 Server2,分别部署了数据库 DB1 和 DB2, 这两台机器组成一个服务集群,DB1 和 DB2 两个数据库中的数据要保持一致,共同为用户 提供服务。用户 User1 可以向 Server1 发起查询数据的请求,用户 User2 可以向服务器 Server2 发起查询数据的请求,它们共同组成了一个分布式系统。

    在满足一致性 C 的情况下,Server1 和 Server2 中的数据库始终保持一致,即 DB1 和 DB2 内容要始终保持相同; 在满足可用性 A 的情况下,用户无论访问 Server1 还是 Server2,都会得到即时响应; 在满足分区容错性 P 的情况下,Server1 和 Server2 之间即使出现网络故障也不会影响 Server1 和 Server2 分别处理用户的请求。

    当用户发起请求时,收到请求的服务器会及时响应,并将用户更新的数据同步到另一台服务 器,保证数据一致性。

    在实际场景中,网络环境不 可能百分之百不出故障,比如网络拥塞、网卡故障等,会导致网络故障或不通,从而导致节 点之间无法通信,或者集群中节点被划分为多个分区,分区中的节点之间可通信,分区间不 可通信。 这种由网络故障导致的集群分区情况,通常被称为“网络分区”。 在分布式系统中,网络分区不可避免,因此分区容错性 P 必须满足。

    假设在满足P的情况下,Server1 和 Server2 之间网络出现故障,User1 向 Server1 发送请求,将数据库 DB1 中的数据 a 由 1 修改为 2,而 Server2 由于与 Server1 无法连接导致数据无法同步, 所以 DB2 中 a 依旧是 1。这时,User2 向 Server2 发送读取数据 a 的请求时,Server2 无法给用户返回最新数据,

    处理方式有如下两种。 第一种处理方式是,保证一致性 C,牺牲可用性 A:Server2 选择让 User2 的请求阻塞, 一直等到网络恢复正常,Server1 被修改的数据同步更新到 Server2 之后,即 DB2 中数据 a 修改成最新值 2 后,再给用户 User2 响应。第二种处理方式是,保证可用性 A,牺牲一致性 C:Server2 选择将旧的数据 a=1 返回给 用户,等到网络恢复,再进行数据同步。

    比如对于涉及钱的交易时,数据的一致性至关重要,因此保 CP 弃 A 应该是最佳选择。而对于其他场景,大多数情况下的做法是选择 AP 而牺牲 C,因为很多情况下不需要太强的 一致性(数据始终保持一致),只要满足最终一致性即可。 最终一致性指的是,不要求集群中节点数据每时每刻保持一致,在可接受的时间内最终能达 到一致就可以了。

    分布式事务中基于分布式 消息的最终一致性方案对事务的处理,就是选择 AP 而牺牲 C 的例子。 这个方案中,在应用节点之间引入了消息中间件,不同节点之间通过消息中间件进行交互, 比如主应用节点要执行修改数据的事务,只需要将信息推送到消息中间件,即可执行本地的 事务,而不需要备应用节点同意修改数据才能真正执行本地事务,备应用节点可以从消息中 间件获取数据。

    在分布式系统中,现在的网络基础设施无法做到始终保持稳定,网络分区(网络不连通)难 以避免。牺牲分区容错性 P,就相当于放弃使用分布式系统。既然分布式系统不能采用这种策略,那单点系统毫无疑问就需要满足 CA 特性了。比如关系 型数据库 DBMS(比如 MySQL、Oracle)部署在单台机器上,因为不存在网络通信问 题,所以保证 CA 就可以了。

    如果一个分布式场景需要很强的数据一致性,或者该场景可以容忍系统长时间无响应的情况 下,保 CP 弃 A 这个策略就比较适合。 一个保证 CP 而舍弃 A 的分布式系统,一旦发生网络分区会导致数据无法同步情况,就要 牺牲系统的可用性,降低用户体验,直到节点数据达到一致后再响应用户。

    保证 CP 的系统有很多,典型的有 Redis、HBase、ZooKeeper 等。

    ZooKeeper 集群包含多个节点(Server),这些节点会通过分布式选举算法选出一个 Leader 节点。在 ZooKeeper 中选举 Leader 节点采用的是 ZAB 算法。

    在 ZooKeeper 集群中,Leader 节点之外的节点被称为 Follower 节点,Leader 节点会专 门负责处理用户的写请求: 具体示意图如下所示: 当用户向节点发送写请求时,如果请求的节点刚好是 Leader,那就直接处理该请求;如果请求的是 Follower 节点,那该节点会将请求转给 Leader,然后 Leader 会先向所 有的 Follower 发出一个 Proposal,等超过一半的节点同意后,Leader 才会提交这次写 操作,从而保证了数据的强一致性。

    比如当出现网络分区时,如果其中一个分区的节点数大于集群总节点数的一半,那么这个分区可 以再选出一个 Leader,仍然对用户提供服务,但在选出 Leader 之前,不能正常为用户提 供服务;如果形成的分区中,没有一个分区的节点数大于集群总节点数的一半,那么系统不 能正常为用户提供服务,必须待网络恢复后,才能正常提供服务。

    这种设计方式保证了分区容错性,但牺牲了一定的系统可用性。

    如果一个分布式场景需要很高的可用性,或者说在网络状况不太好的情况下,该场景允许数 据暂时不一致,那这种情况下就可以牺牲一定的一致性了。 网络分区出现后,各个节点之间数据无法马上同步,为了保证高可用,分布式系统需要即刻 响应用户的请求。但,此时可能某些节点还没有拿到最新数据,只能将本地旧的数据返回给 用户,从而导致数据不一致的情况。 适合保证 AP 放弃 C 的场景有很多。比如,很多查询网站、电商系统中的商品查询等,用 户体验非常重要,所以大多会保证系统的可用性,而牺牲一定的数据一致性。

    采用保 AP 弃 C 的系统也有很多,比如 Eureka、Cassandra。

    CAP 和 ACID 的“C”“A”是一样的吗?

    CAP 中的 C 强调的是数据的一致性,也就是集群中节点之间通过复制技术保证每个节点 上的数据在同一时刻是相同的。 ACID 中的 C 强调的是事务执行前后,数据的完整性保持一致或满足完整性约束。也就 是不管在什么时候,不管并发事务有多少,事务在分布式系统中的状态始终保持一致。

    CAP 中的 A 指的是可用性(Availability),也就是系统提供的服务一直处于可用状态, 即对于用户的请求可即时响应。 ACID 中的 A 指的是原子性(Atomicity),强调的是事务要么执行成功,要么执行失败。

    展开全文
    weixin_34765773 2021-01-28 02:28:44
  • 274KB weixin_43839579 2019-02-12 18:28:34
  • 304KB weixin_38618540 2021-02-27 03:09:26
  • qq_24313635 2019-11-02 14:00:14
  • liyunfei5839 2021-04-21 22:37:26
  • 79KB weixin_38576045 2021-01-07 07:42:12
  • xindoo 2020-10-28 23:46:56
  • qq_27093465 2020-09-18 17:57:05
  • qq_25956141 2018-09-12 22:09:17

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,879
精华内容 12,351
关键字:

cap理论