一致性模型是什么
一致性模型从强到弱依次是线性一致、顺序一致、因果一致、读己之写与最终一致。多数 NoSQL 提供可配置的会话级或读写级别,让业务在性能与一致之间按场景取舍:写用多数派保证不丢,读按场景区分,详情页读主节点、列表页可以接受秒级旧读。把「读己之写」当成系统级默认保证是最常见的误解,换连接或换节点之后它可能就失效了。
基本信息
| 线性一致 | 读到最新已提交写入,写入需要共识,延迟高 |
|---|---|
| 因果一致 | 因果相关的操作顺序可见 |
| 读己之写 | 同一会话能看到自己的写入 |
| 最终一致 | 停止写入后副本收敛,存在旧读窗口 |
| 常见实现 | MongoDB 的 readConcern / writeConcern、Elasticsearch 的实时 GET 与近实时搜索 |
| 所属系统 | 分布式存储通用概念 |
模型与取舍
| 模型 | 保证 | 代价 |
|---|---|---|
| 线性一致 | 读到最新已提交写入 | 写入需共识,延迟高 |
| 因果一致 | 因果相关的操作顺序可见 | 实现复杂,跨分区有成本 |
| 读己之写 | 同一会话看到自己的写入 | 会话粘滞或令牌传递 |
| 最终一致 | 停止写入后副本收敛 | 旧读窗口,需业务容错 |
典型使用场景
- 支付与账务:要求强一致,写读都走多数派
- 详情页:读主节点,保证用户看到刚提交的内容
- 列表页与推荐:可接受秒级旧读,换取吞吐
- 跨机房读:用因果一致或会话粘滞避免自相矛盾的展示
- 幂等校验:靠唯一键设计,不依赖读一致性
配置示例
配置示例
// MongoDB:写多数派 + 读多数派
await db.orders.insertOne(
{ _id: 1, status: "created" },
{ writeConcern: { w: "majority" } } // 写入等待多数派确认
);
db.orders.find({ _id: 1 }).readConcern("majority"); // 读多数派已提交数据
# Elasticsearch:按 ID 读取是实时的,搜索要等 refresh
GET /orders/_doc/1
GET /orders/_search业务侧常见的折中是写用多数派保证不丢,读按场景分:详情页读主节点,列表页可接受秒级旧读。
把「读己之写」当系统级默认保证,换节点或换连接池后可能失效,需要在代码里显式选择会话或读级别。
在最终一致的窗口内做二次判断(例如判断是否重复提交)会得到错误结论,幂等键要独立设计,不能依赖读到最新数据。