知识卡片

CAP忽略网络延迟,严苛数据实际只能CA,靠用户分区降低故障影响面

结构图卡

内容

CAP理论有一个隐含且容易被忽视的假设:它忽略了网络延迟。Brewer定义一致性时,默认事务一提交,数据就能瞬间复制到所有节点,但现实中从节点A把数据复制到节点B总要花时间——同机房可能是几毫秒,跨地域机房(比如北京到广州)可能要几十毫秒。这意味着CAP理论里的C在实践中永远不可能完美实现,在数据复制真正完成之前的这段时间窗口里,节点A和节点B的数据必然是不一致的。这几毫秒或几十毫秒的不一致,对多数业务无所谓,但对某些极端严苛的场景(比如涉及金钱的用户余额、涉及抢购的商品库存)却是不可接受的——业务上必须要求强一致性,但技术上分布式场景下完美的一致性根本做不到,因此像”单个用户的余额”“单个商品的库存”这类数据,理论上该选CP,实际上CP都无法真正满足,只能退而求其次选CA——也就是只允许单点写入、其他节点做备份,无法做到分布式多点同时写入。需要澄清的是,这并不意味着这类系统整体无法用分布式架构,只是”单个用户余额、单个商品库存”这一份具体数据无法真正分布式多写,系统整体依然可以走分布式路线——常见做法是按用户做分区,比如用户ID 0~100的数据放Node 1、101~200的放Node 2,客户端按用户ID路由到对应节点,单个用户的读写永远只发生在某一个节点上。这种设计有个明显代价:某个节点故障时,落在这个节点上的用户完全无法读写;但从系统整体看,这个代价是可以接受的——故障影响的只是这一部分用户(比如20%),而不是全部用户,这正是为什么现实中挖掘机挖断光缆导致支付宝出故障时,只有部分用户业务异常,而不是所有用户同时瘫痪。

结构图

flowchart TB
  A["CAP假设:事务提交后数据瞬间复制到所有节点"]
  A --> B["现实:复制总有延迟(几毫秒~几十毫秒)"]
  B --> C["延迟窗口内节点间数据必然不一致<br/>→完美的C在实践中不可能实现"]
  C --> D["对严苛数据(余额/库存):<br/>业务要求强一致性但CP做不到<br/>→只能退化为CA(单点写入+备份,非分布式多写)"]
  D --> E["系统整体仍可分布式:按用户ID分区<br/>Node1管用户0~100,Node2管101~200"]
  E --> F["代价:某节点故障时该节点用户完全无法读写"]
  F --> G["但收益:故障影响范围被限定在一部分用户<br/>而非全体用户(如挖断光缆时支付宝只有部分用户异常)"]

参考来源

- 位置:《从零开始学架构》第23讲《想成为架构师,你必须掌握的CAP细节》"CAP关键细节点"之"CAP是忽略网络延迟的"(源文件:_epub-src/OEBPS/text00002.html) - 结论依据:原文说明"CAP 理论中的 C 在实践中是不可能完美实现的……对于某些严苛的业务场景,例如和金钱相关的用户余额,或者和抢购相关的商品库存……单个用户的余额、单个商品的库存,理论上要求选择 CP 而实际上 CP 都做不到,只能选择 CA",并以用户分区架构说明"这种设计可以降低节点故障时受影响的用户的数量和范围……这也是为什么挖掘机挖断光缆后,支付宝只有一部分用户会出现业务异常",直接支撑本卡片结论与结构图。 - 原始内容:CAP 理论中的 C 在实践中是不可能完美实现的,在数据复制的过程中,节点 A 和节点 B 的数据并不一致……单个用户的余额、单个商品的库存,理论上要求选择 CP 而实际上 CP 都做不到,只能选择 CA……这也是为什么挖掘机挖断光缆后,支付宝只有一部分用户会出现业务异常,而不是所有用户业务异常的原因。