← 返回题目列表

BASE 理论是什么?和 ACID 是什么关系?

高频 中等 第 12 / 27 题 更新于 2026/10/03
BASEACID最终一致性
学习 AI 实战项目

简化版

ACID 描述一次事务应具备的原子性、一致性、隔离性和持久性;BASE 描述分布式协作中允许基本可用、软状态和最终一致的一类工程取舍。它们不是反义词:常见做法是用本地 ACID 守住单个数据所有者的不变量,再用可靠事件、幂等、补偿和对账让跨服务状态在限定时间内收敛。

详细版

ACID 中的 Consistency 是“事务把数据库从一个满足约束的状态带到另一个满足约束的状态”,既依赖数据库约束,也依赖业务代码;它不等同于 CAP 的线性一致性。隔离级别还决定并发事务能观察到什么,因此不能把“用了 ACID 数据库”直接说成所有并发与跨服务读取都强一致。

BASE 的三个词是 Basically Available、Soft State、Eventually Consistent。它允许系统在故障或异步传播期间出现可解释的中间状态,但必须回答权威事实、最长不一致窗口、收敛机制和超时处置。订单与 outbox 可以在一个 ACID 事务内提交,积分服务再以至少一次消息、消费幂等和对账实现 BASE;这正说明两者可以分层组合。

选择边界取决于业务不变量。余额守恒、库存不为负等条件应尽量在可原子约束的边界内完成;积分、通知、搜索索引等派生数据通常可以异步。所谓“最终一致”若没有时间目标、监控和修复路径,只是永久不一致的借口。

完整版教学

一、先区分两套概念回答的问题

ACID 讨论的是事务提交边界:一组读写如何一起成功或失败,并发执行时互相能看到什么,提交后数据是否能在故障后保留。BASE 讨论的是跨节点、跨服务协作时,系统是否允许降低即时一致性来换取可用性和解耦。

两者抽象层次不同,所以“ACID 还是 BASE”通常是一个错误问题。订单服务内部可以使用 ACID,订单事件传播到积分和搜索服务时再采用 BASE;同一条业务链路能同时出现两者。

记忆钩子:ACID 管一个事务边界怎样正确提交,BASE 管多个自治边界怎样允许中间态并最终收口。

二、ACID 四个属性要说准确

属性核心含义不能过度推导出的结论
Atomicity事务内操作整体提交或整体回滚不能回滚事务外已发送的短信或 HTTP 副作用
Consistency提交前后已定义的不变量仍成立不自动等于 CAP 的线性一致
Isolation并发事务按隔离级别限制相互观察不同隔离级别仍可能允许特定并发现象
Durability已提交结果在承诺的故障模型下保留不代表无备份也能抵抗误删或全部介质损坏

数据库只能自动维护它知道的约束。balance >= 0 若没有条件更新、约束或正确业务代码,事务照样可以原子地提交错误余额;Consistency 不是数据库替开发者证明全部业务规则。

三、BASE 三个词对应哪些工程责任

基本可用是在故障时保住核心能力,允许非核心功能限流、排队或关闭;它不是返回任意结果。软状态是 PENDING、SYNCING、COMPENSATING 等有进入条件和退出路径的中间态,不是无人管理的脏数据。

最终一致要求在停止新写入且通信恢复后,各副本或派生状态能够收敛。工程上至少要有可重放输入、幂等处理、有限重试、死信处置和对账;MQ 在线本身不能证明业务已经一致。

本地 ACID:订单写入 + outbox 事件写入 -> 同事务提交
跨服务 BASE:发布事件 -> 积分消费 -> 幂等入账 -> 失败重试/对账

四、为什么常见答案是“局部 ACID,跨边界收敛”

若订单、库存、积分共用一个跨服务大事务,任何参与者变慢都会延长锁和连接占用,外部系统还可能根本不支持同一事务协议。反过来,若所有约束都异步处理,库存可能先被卖成负数,之后再补偿也无法追回已经履约的商品。

合理边界是先把强不变量放到其数据所有者内部原子完成,再传播结果。库存服务用条件更新保证 available >= quantity,订单服务不直接改库存表;积分作为订单完成后的派生权益可以稍后到账,并向用户展示处理中。

五、用数字检验“最终”是否兑现

假设每秒产生 800 个积分事件,消费能力是 1000 条/秒。故障 5 分钟会积压 800 × 300 = 240000 条;恢复后的净追赶速度是 1000 - 800 = 200 条/秒,清空还需 240000 / 200 = 1200 秒,也就是 20 分钟。

若产品承诺 10 分钟到账,这套容量即使最终能清空也不合格。需要扩容消费、降低持续生产速率或调整承诺,并监控最老事件年龄,而不是只看队列长度。

收敛时间 = 故障积压量 / (恢复消费速率 - 当前生产速率)
前提:恢复消费速率 > 当前生产速率

六、如何决定哪部分不能只用 BASE

判断依据是错误能否补偿、用户能否容忍中间态,以及不变量能否被某个单一所有者原子保护。通知漏发可以补发,搜索索引旧一分钟可以重建;资金凭空增加、同一名额被卖两次则可能无法靠事后修复挽回损失。

这也不意味着资金链路必须用一个全局事务包住所有服务。可先冻结额度或创建不可重复的账务流水,在局部边界内守住资金不变量,再让订单展示、通知等外围状态异步收敛。

七、失败时怎样形成闭环

生产端要解决“业务提交但事件丢失”,可用 outbox 或事务消息;消费端要解决重复投递,用业务唯一键和本地事务;永久失败进入死信后必须有人或自动流程处理。独立对账负责发现协议、程序缺陷或人工操作留下的漏网差异。

监控应包含事件延迟分位数、最老未处理年龄、重试和死信数量、补偿成功率、对账差异数。软状态超过承诺窗口就已经是故障,即便主接口仍返回成功。

八、常见误区与追问

  • 误区:ACID 的 C 就是 CAP 的 C。 前者指事务保持已定义约束,后者通常指线性一致,不能混用。
  • 误区:BASE 是放弃一致性。 它放宽即时一致要求,但仍需在明确时限内收敛并守住核心不变量。
  • 误区:用了关系型数据库就全部满足 ACID。 还要看事务边界、隔离级别、持久化配置和业务约束是否正确。
  • 误区:引入 MQ 就实现了最终一致。 生产丢消息、重复消费、永久失败和业务冲突仍需分别处理。
  • 追问:补偿等同于事务回滚吗? 不等同;补偿是新的、可审计的业务动作,也可能失败并需要幂等重试。
  • 追问:怎样确定一致性窗口? 从用户承诺和风险反推,再用积压量与净消费速度验证恢复容量。
  • 追问:BASE 适合账务吗? 核心账务不变量不能只靠事后修复,但账务结果向订单、报表等系统传播可以最终一致。

九、加强记忆

回答时先把 ACID 与 BASE 放到不同层次:ACID 解释一个事务边界的提交、并发与持久化语义,BASE 解释多个自治边界为何允许中间态以及如何收敛。随后用“本地事务加 outbox、跨服务至少一次投递、消费幂等、补偿对账”的链路说明组合方式,最后用收敛时间和强不变量边界证明方案不是拿“最终一致”掩盖错误。