系统设计中的强一致性 vs 最终一致性

发布: (2026年5月2日 GMT+8 23:22)
9 分钟阅读
原文: Dev.to

Source: Dev.to

为什么这在分布式系统中很重要(以及你为何需要了解它)

现代软件很少局限于单台机器。它分布在多个服务器和地区,以保持对所有用户的快速和可靠。
这种分布很强大,但它带来了 一致性 的挑战:当你在不同服务器上拥有数据的多个副本时,你必须决定 这些副本如何保持同步

你处理一致性的方式决定了系统在负载或网络故障下的行为。作为开发者或架构师,你必须 有意地选择一致性模型——否则系统会为你做出选择,往往在最不方便的时候。

一致性在分布式系统中的体现

一致性 与时机有关。
“在我保存一条数据后,其他人多久能看到更新?”

把它想象成一个群聊:

模型用户看到的内容
强一致性每个人在完全相同的时间看到完全相同顺序的每条消息。没有人能回复他们还没看到的消息。
最终一致性有些人看到消息的时间可能比其他人晚几秒。最终所有人都会看到相同的历史,但在短暂的时间里,“真相”会有所不同。

在它们之间的选择并非纯技术问题;它是 具有架构后果的业务决策

注意:不是 单节点数据库中的 ACID 一致性。
ACID 描述的是状态转换;分布式一致性 描述的是这些状态变化 何时 可见。

强一致性

强一致性保证 一旦写入数据,随后所有的读取都会返回该新值,无论用户连接到哪台服务器。

工作原理

  • leader / primary node 对写入进行排序。
  • Synchronous replication 到副本。
  • Quorums(多数同意)在写入成功前必须达成。

写入只有在系统能够保证任何后续读取都会看到它时才被视为成功。

常见后果

  • 写入必须等待 确认。
  • 读取可能阻塞,直到系统确认最新状态。
  • 网络分区会降低可用性(系统倾向于正确性而非在线可用性)。

正确性至关重要的场景

场景为何需要强一致性
你转账银行余额绝不能出现错误,即使是一瞬间。
你购买最后一件商品电商库存、限时抢购、票务预订——两个人不能买到同一个最后的座位。
你失去或获得访问权限权限变更必须即时传播(例如撤销管理员权限)。
你触发使用限制API 速率限制或订阅上限必须精确执行。
你切换关键开关功能标记、紧急关闭开关、安全开关——部分发布可能会快速导致生产故障。

强一致性的好处

  • 可预测性: 行为类似单节点数据库。
  • 安全性: 没有用户会看到过时或错误的值。
  • 正确性优先于可用性: 当需要权衡时,系统选择“正确性”。

Eventual Consistency

Eventual consistency allows different servers to hold different versions of the data for a short window. The system promises that “eventually” all copies will converge, but it does not wait for convergence before completing the request.

How It Works

  • Asynchronous replication – 写入记录在一台服务器上,请求会立即返回“Success”。
  • Background synchronization 将数据复制到其他副本。
  • Conflict‑resolution strategies 处理分歧的更新。

The system prioritizes availability, low latency, and partition tolerance. Stale reads are possible, but the system stays responsive.

When Slight Staleness Is Acceptable

场景为什么最终一致性是可以接受的
You refresh your feed你刷新动态
You open an analytics dashboard你打开分析仪表盘
You get recommendations你获取推荐
You search for something你搜索某些内容
You receive notifications你收到通知

Benefits (Eventual Consistency)

  • Performance: 极其快速,因为没有协调延迟。
  • Resilience: 即使许多节点出现分区,系统仍能接受写入并提供读取。
  • Scalability: 在大规模(例如全球服务)下表现良好。

Trade‑offs

  • Confusion: 用户在刷新后可能看到过时的数据。
  • Complexity: 开发者必须在不同副本上出现并发更新时处理冲突。

实际案例:DynamoDB

Amazon DynamoDB 默认是 最终一致性。写入后,读取可能会返回陈旧的数据,但你可以在每个请求上请求 强一致性

// Write (eventual consistency)
await dynamodb.put({
  TableName: "Users",
  Item: {
    userId: "42",
    email: "new@email.com"
  }
});
// The write succeeds, but replicas may not all be updated yet.

// Strongly consistent read (optional)
const result = await dynamodb.get({
  TableName: "Users",
  Key: { userId: "42" },
  ConsistentRead: true   // Guarantees the latest committed value
});
  • 默认(最终一致性): 延迟更低,可用性更高。
  • StrongRead 标志: 以稍微增加的延迟和可用性换取数据的新鲜度保证。

选择合适的模型

  1. 确定业务需求 – 瞬时不一致是无害的还是灾难性的?
  2. 将场景映射到一致性需求 – 使用上面的表格作为快速参考。
  3. 利用每次操作的选择 – 许多服务(例如 DynamoDB、Cosmos DB)允许你为每个请求选择一致性。
  4. 为冲突解决进行设计 – 如果选择最终一致性,需规划如何合并分歧的更新。

通过了解 何时 以及 何地 应用每种模型,你可以避免过度设计(始终强一致)或保护不足(始终最终一致)的系统。

祝架构愉快!

await dynamodb.get({
  TableName: "Users",
  Key: { userId: "42" },
  ConsistentRead: true
});

你可以保证收到最新提交的值,但代价是更高的延迟和吞吐量使用。

在设计下一个功能时,问问自己:“如果用户看到的是五秒前的数据,最糟糕的情况是什么?”

  • 如果答案是 “没什么大不了的,” 请选择 最终一致性,享受额外的速度。
  • 如果答案是 “我们会失去金钱或信任,” 则坚持使用 强一致性

强一致性 将正确性置于可用性之上。
最终一致性 将可用性和可扩展性置于即时性之上。

有意识地权衡这些取舍,你构建的系统不仅在技术上可靠,而且与用户的真实需求保持一致。

0 浏览
Back to Blog

相关文章

阅读更多 »

什么是分布式系统?

引言 “分布式系统”是当今常用的概念。第一次遇到它时,可能会觉得令人生畏,但核心思想很简单,而且…