单调读是什么
单调读是一种会话保证:同一会话内的读取不会出现时光倒流,如果已经读到某个版本的数据,后续读取不会返回更旧的版本。它要解决的问题出现在多副本架构中:负载均衡把请求随机分发到不同副本,用户先看到新数据,刷新后又看到旧数据,观感上像是数据被回滚,业务人员据此做出错误判断。
怎么实现
常见做法有三类:会话粘性,让同一会话固定访问同一副本组;版本过滤,读取请求携带已见的最小版本,返回更旧版本时丢弃并重试;读取通道固定,分页查询全程走同一副本,避免跨页切换。实现后要监控版本回退的重试比例,比例偏高通常说明副本同步延迟过大或存在不健康副本,应回到复制链路处理。
基本信息
| 问题场景 | 多副本轮询读取:先读到新数据,再读到旧副本上的旧数据 |
|---|---|
| 实现方式 | 会话固定副本、按版本过滤、读取时携带最小可见版本 |
| 关联保证 | 常与读己之写一起组成会话级读保证 |
| 适用读路径 | 主从复制、多副本分片与就近读取的只读副本 |
| 监控指标 | 版本回退重试比例,偏高说明副本延迟或不健康 |
实现手段对照
| 手段 | 做法 | 代价 |
|---|---|---|
| 会话粘性 | 同一会话固定访问同一副本组 | 副本故障时需要迁移会话 |
| 版本过滤 | 响应版本低于已见版本即重试 | 每次回退增加一次重试开销 |
| 通道固定 | 分页查询全程不切换副本 | 负载均衡效果有所下降 |
| 最小版本参数 | 读取请求携带已见版本号 | 需要服务端支持版本比较 |
典型使用场景
- 列表页翻页与详情页之间来回切换,避免看到版本回退
- 异地多副本就近读取,用户跨地域访问时不出现数据倒退
- 只读副本承接报表类查询,同一会话结果集保持稳定
- 会话级保证组合使用:读己之写配合单调读覆盖常见预期
分页查询跨越多个副本时,单调读缺失会导致结果集中出现重复或遗漏条目,这类问题容易被误判为数据被他人修改。
仅靠客户端重试无法根治单调读问题:副本复制延迟持续增大时,重试只会进一步增加延迟,应从复制链路与副本健康度入手。