首页/开发/系统分析与架构设计速查/读己之写(Read Your Writes)

读己之写(Read Your Writes)

会话级一致性保证:用户提交写入后,自己的后续读取能看到该结果;常见实现是写后一段时间内路由到主库或用会话令牌绑定数据版本。

读己之写是什么

读己之写(Read Your Writes)是一种会话级一致性保证:用户提交写入之后,自己发起的后续读取一定能看到这次写入的结果。它出现在读写分离与多副本架构里——写请求走主库、读请求走从库,当复制存在延迟时,刚提交的数据可能查不到。问题的表现非常具体:用户点完保存立刻刷新页面,看到的是旧内容,于是反复提交,反而制造更多脏数据。

基本信息

一致性层级会话级保证,不是全局强一致
触发场景写主库、读从库,或读请求被路由到不同副本
实现手段会话粘性、写后读主、客户端携带版本号或时间戳
需要配套复制延迟监控,延迟升高时自动放宽策略
产品侧缓解提交成功后展示本地已确认数据,不立即回查服务端

典型使用场景

  • 保存后跳转详情页:编辑完成立刻打开,必须看到刚提交的内容
  • 下单后查看订单列表:新订单不能从列表里消失,否则用户重复下单
  • 配置变更生效:管理端改完配置立即验证,读到的应是新值
  • 多步骤表单:前一步的写入是后一步读取的前提,链路内不能读旧值
  • 审核后查看状态:审核动作完成,自己看到的应已是新状态
  • 跨端提醒:同账号在另一设备提交后,本机刷新需保持一致口径

写后读主示意(伪代码)

写后读主示意(伪代码)
# 写入成功后给会话打一个短期标记
on_write_success: session[user_id].read_master_until = now + 5s

# 读取时按标记决定路由
if now < session[user_id].read_master_until:
    route = MASTER                  # 短期强制读主库
else:
    route = REPLICA                 # 常规读从库,并校验版本
    if replica.version < session[user_id].last_write_version:
        route = MASTER              # 版本落后时回退主库
# 版本号由写入返回,客户端在会话中携带

实现手段对比

手段做法代价
会话粘性同一会话固定走同一副本副本故障时该会话体验中断,负载不均
写后读主写入后一段时间内该会话读主库主库压力上升,窗口长度需要按延迟标定
版本号校验写返回版本,读时比对副本版本需要副本暴露位点信息,实现成本高
客户端兜底写成功后前端暂存结果并据此渲染仅缓解观感,服务端数据仍可能不一致
策略窗口要与复制延迟监控联动:固定写死 5 秒在延迟升高时照样读到旧数据,延迟 30 秒时也只是把问题推后。
跨用户可见的数据(例如同事刚改的配置)不属于读己之写范畴,需要单独设计一致性策略,不要用同一个短窗口假设覆盖所有场景。

易错点

  • 读写分离后不做任何会话保证:用户频繁看到旧数据,重复提交制造脏数据
  • 统一写后读主且窗口过长:主库压力上升,读扩展收益被抵消
  • 只在前端兜底、服务端不处理:换端或清缓存后问题复现
  • 把会话保证当成全局一致:跨用户场景仍读到旧值,问题归因错误

数据来源与参考

  • Terry 等《Session Guarantees for Weakly Consistent Replicated Data》(1994)
  • 《数据密集型应用系统设计》(Kleppmann)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌