Skip to content

ACID vs BASE:对立统一的哲学

1983 年,Jim Gray 在论文中提出了 ACID 事务模型。

2000 年,eBay 的架构师 Dan Pritchett 提出了 BASE 理论。

这两套理论,一个统治了数据库世界 40 年,一个支撑了互联网公司 20 年的高速增长。

它们是对立的吗?还是说,它们根本就不是在解决同一个问题?

ACID:传统数据库的「完美主义」

ACID 代表:

Atomicity(原子性):要么全做,要么全不做
Consistency(一致性):事务前后,数据都是合法的
Isolation(隔离性):并发事务互不干扰
Durability(持久性):事务提交后,数据不会丢失

传统数据库工程师会告诉你:这四个特性是数据库的「德智体美」。

原子性

sql
BEGIN TRANSACTION;
UPDATE account SET balance = balance - 1000 WHERE user_id = 'A';
UPDATE account SET balance = balance + 1000 WHERE user_id = 'B';
COMMIT;
-- 或者 ROLLBACK

如果第二条 SQL 执行失败,第一条也会回滚。你不用担心「钱扣了但没到账」的情况。

一致性

java
/**
 * ACID 一致性约束
 */
public class AccountTransfer {
    
    /**
     * 转账前后,账户总额不变
     */
    public void transfer(String fromUser, String toUser, BigDecimal amount) {
        Connection conn = dataSource.getConnection();
        try {
            conn.setAutoCommit(false); // 开启事务
            
            // 扣款
            String sql1 = "UPDATE account SET balance = balance - ? WHERE id = ? AND balance >= ?";
            // 存款
            String sql2 = "UPDATE account SET balance = balance + ? WHERE id = ?";
            
            // ACID 保证:
            // - Atomicity:两条 SQL 要么都成功,要么都失败
            // - Consistency:余额不能为负(由 CHECK 约束保证)
            // - Isolation:并发时不会导致余额错误
            // - Durability:提交后即使宕机也不会丢失
            
            execute(sql1, amount, fromUser, amount);
            execute(sql2, amount, toUser);
            
            conn.commit();
        } catch (Exception e) {
            conn.rollback();
            throw e;
        } finally {
            conn.close();
        }
    }
}

ACID 的核心假设:数据库是一个单一的、可靠的、不变的状态机。

BASE:现代分布式系统的「实用主义」

BASE 代表:

Basically Available(基本可用):系统保证可用,但可能降级
Soft state(软状态):数据状态可能随时变化
Eventually consistent(最终一致):在没有新操作的情况下,系统最终会一致

互联网公司的困境

2000 年左右,eBay 遇到了问题:

用户量:千万级
单库上限:几百万行
需求:7x24 小时服务,任何节点故障不能影响用户

如果继续用 ACID 数据库垂直扩展,会遇到:

  1. 单机性能瓶颈
  2. 单点故障导致全站不可用
  3. 跨机房部署几乎不可能

所以 eBay 的架构师想:能不能放弃一些东西,换取可用性和可扩展性?

BASE 理论由此诞生。

BASE 的核心思想

java
/**
 * BASE 系统示例:订单服务
 */
public class OrderServiceBASE {
    
    /**
     * 基本可用:订单创建立即成功
     * 
     * 假设:
     * - 用户下单
     * - 库存服务压力过大
     * - 订单服务仍然响应「订单已创建」
     * - 库存扣减异步进行
     */
    public Order createOrder(OrderRequest request) {
        Order order = new Order();
        order.setStatus("CREATED");
        
        // 立即返回,订单创建成功
        orderRepository.save(order);
        
        // 异步处理库存扣减
        messageQueue.send("inventory:deduct", order);
        
        return order;
    }
    
    /**
     * 软状态:订单状态是中间状态
     */
    public void handleInventoryCallback(InventoryResult result) {
        if (result.isSuccess()) {
            order.setStatus("PAID");
        } else {
            order.setStatus("CANCELLED");
            // 补偿退款
            refundService.refund(order);
        }
        orderRepository.update(order);
    }
}

从 ACID 到 BASE 的演进

时间线演进:

1990s:单体数据库统治一切

2000s:互联网爆发,数据量爆炸

2000s-2010s:分库分表 + 最终一致性

2010s-至今:NewSQL(尝试融合 ACID + BASE)

为什么互联网公司选择 BASE?

对比维度ACIDBASE
数据一致性强一致最终一致
可用性低(故障时拒绝服务)高(故障时降级服务)
可扩展性垂直扩展有限水平扩展容易
实现复杂度
适用场景金融、订单社交、搜索、缓存

ACID vs BASE 对比表

特性ACIDBASE
一致性模型强一致最终一致
可用性故障时不可用故障时降级可用
性能受限于锁和两阶段提交高吞吐、低延迟
数据完整性严格保证允许暂时不一致
事务类型传统 RDBMSNoSQL、分布式系统
代表系统MySQL、Oracle、PostgreSQLCassandra、DynamoDB、MongoDB
设计哲学预防一切错误接受错误、快速恢复

两者并非对立

这是最重要的认知:ACID 和 BASE 不是互斥的,它们可以在同一个系统中并存。

java
/**
 * 混合策略:OLTP 用 ACID,OLAP 用 BASE
 */
public class HybridDatabaseStrategy {
    
    /**
     * 联机事务处理(OLTP):金融、订单、库存
     * 需要强一致性,用 ACID
     */
    public void handleOLTP(Order order) {
        // 使用关系型数据库(MySQL/PostgreSQL)
        // 保证强一致性
        transactionTemplate.execute(status -> {
            orderService.create(order);
            inventoryService.deduct(order);
            paymentService.process(order);
            return null;
        });
    }
    
    /**
     * 联机分析处理(OLAP):统计、报表、推荐
     * 需要高吞吐,允许最终一致,用 BASE
     */
    public void handleOLAP(AnalyticsQuery query) {
        // 使用数据仓库或 NoSQL
        // 异步写入,定期聚合
        asyncQueue.send("analytics", query);
    }
}

实际案例:电商系统的混合架构

┌─────────────────────────────────────────────────────┐
│                    用户请求                          │
└─────────────────────────────────────────────────────┘

          ┌─────────────┴─────────────┐
          ▼                           ▼
    ┌───────────────┐          ┌───────────────┐
    │   商品搜索     │          │   订单交易     │
    │   (BASE)      │          │   (ACID)      │
    └───────────────┘          └───────────────┘
          │                           │
          ▼                           ▼
    ┌───────────────┐          ┌───────────────┐
    │   Elasticsearch │         │   MySQL       │
    │   最终一致      │          │   强一致       │
    └───────────────┘          └───────────────┘

哲学层面的思考

ACID 体现的是「预防哲学」:尽可能在事前避免所有错误。

BASE 体现的是「恢复哲学」:接受错误会发生,但在发生后快速恢复。

ACID 的隐喻:完美的婚姻,从不吵架
BASE 的隐喻:真实的婚姻,吵架但能修复

哪种更好?取决于你追求的是什么。

银行追求「每一笔交易都正确」,用 ACID。

互联网追求「服务永远在线」,用 BASE。

面试问题:如何回答「你们系统用 ACID 还是 BASE?」

这个问题没有标准答案,关键是展示你的思考过程:

错误回答:背书「我们用 BASE」或「我们用 ACID」,不给理由。

正确回答框架

  1. 先分析业务场景:什么数据?什么操作?对一致性的容忍度?
  2. 再给出选择:为什么选这个?
  3. 如果有混合策略:哪些模块用 ACID,哪些用 BASE?为什么?

示范回答

"我们系统采用了分层策略。核心交易链路(订单、支付、库存)使用 MySQL 的 ACID 事务,保证资金不丢失。具体来说,转账操作会先检查余额、冻结金额、然后执行扣款,全程在一个事务内完成,任何一步失败都会回滚。

非核心链路(商品搜索、浏览量统计、用户画像)使用最终一致性。这些数据允许短暂不一致,比如用户看到搜索结果页的商品价格和实际价格有几分钟延迟,我们通过价格高亮、实时查询等方式处理。

这种分层设计让我们兼顾了资金安全和系统可用性。"

面试追问:CAP 和 ACID/BASE 的关系

这是进阶追问:CAP 中的 C(一致性)和 ACID 中的 C(一致性)是一个意思吗?

答案是:不完全一样。

一致性CAP 中的 CACID 中的 C
定义线性一致性,所有节点看到同一时刻的数据数据库完整性约束
范围分布式系统层面单机数据库层面
保证操作层面的顺序业务规则层面的合法
ACID 的 C = 数据必须满足「业务规则」+「约束」+「触发器」
CAP 的 C = 数据必须「所有节点在同一时间看到相同的值」

总结

ACID 和 BASE 是分布式系统设计的两极:

  1. ACID:完美主义,强一致,但扩展性差
  2. BASE:实用主义,高可用,但需要补偿机制
  3. 现代趋势:NewSQL 尝试融合两者(如 Spanner、CockroachDB)
  4. 工程实践:混合使用,核心链路用 ACID,辅助链路用 BASE

"理解 ACID 和 BASE 的关系,就是理解分布式系统设计的本质:没有银弹,只有权衡。知道在什么场景下选择什么策略,是一个分布式工程师成熟的标志。"

基于 VitePress 构建