前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库If-Match If-Unmodified-Since 412 乐观并发
HTHTTP缓存与代理

HTTP 的 If-Match 和 If-Unmodified-Since 如何用条件请求防止并发写覆盖(丢失更新)?

在更新请求中携带前次读取得到的ETag或时间戳,服务器校验通过才执行写入,条件失败时返回412,从而阻断并发覆盖。

前端进阶之旅 · 一题精讲更新于 2026.09.05
HTTP#缓存与代理#缓存#并发编程
先看核心答案
理解线索

乐观并发控制

  1. 前置条件写在请求头,服务器校验通过才执行。
  2. 验证器ETag或时间值,标识当前状态。
  3. 412失败条件不匹配时拒绝请求。

只适用于已存在资源,新建资源用If-None-Match: *等。

核心回答

先记住这个答案

客户端先GET获取资源的ETag或最后修改时间,更新请求带上If-Match或If-Unmodified-Since,服务器在写入前校验该标识是否仍匹配;若不匹配说明资源已被他人修改,返回412。这样后提交的写请求不会覆盖先提交的结果,客户端需重取数据再重试。

  • 写前校验失败返回412,阻断旧版本覆盖。
  • If-Match要求强ETag,秒级时间戳可能漏判。
  • GET时携带验证器,PUT时带回,机制需前后一致。

条件头在写请求中的判定过程

If-Match携带一个或多个ETag值,用强比较;当前资源的ETag与任一值相等才放行。If-Unmodified-Since携带HTTP日期,要求资源最后修改时间不晚于该时间。若同时携带两者,服务器仅校验If-Match,不匹配即返回412;若仅携带If-Unmodified-Since,当最后修改时间不晚于该时间时才继续,否则中止并返回412。

客户端A、B先后GET同一文档,各自获得相同验证器。A先提交PUT,请求带If-Match,服务器校验匹配并更新资源与ETag;B后提交同样条件,服务器比对发现已不匹配,返回412拒绝。于是只有A的更新生效,B获知冲突后可重新读取最新版再决策。

编辑文档的并发冲突

文档/doc/1当前ETag为v2。两个客户端同时读取并编辑。客户端1提交PUT,带If-Match: v2,服务器确认当前仍是v2,执行更新并设新ETag为v3。客户端2随后提交相同If-Match: v2,服务器发现当前已经是v3,返回412并附最新ETag。

客户端2收到412后不立即重试,而是提示用户有他人修改,可选择重新加载或合并。服务器在写入前做条件检查,保证同一版本只能成功提交一次,彻底杜绝后写覆盖先写。若不使用条件头,两个请求都会成功,后者的数据会覆盖前者。

适用边界与易失效条件

If-Unmodified-Since依赖服务器Last-Modified时间,精度仅到秒。两次修改若发生在同一秒,后一次不会触发412,造成静默覆盖。若服务器未提供该时间或客户端缓存了旧值,条件也失效,需依赖ETag才能可靠检测。

If-Match要求强验证器,弱ETag(W/...)不可用。若服务器只提供弱ETag或验证器不唯一,If-Match将无法区分两次修改。此时应调整ETag生成策略,确保内容变化必然产生新强ETag,或在响应头显式声明允许的验证方式。

回答前,多想一步

容易答错的地方

认为If-Match可无条件代替If-Unmodified-Since
两者机制不同:If-Match基于ETag精确判断内容变没变,If-Unmodified-Since只比较秒级时间,同秒内第二次修改无法察觉。高并发写必须用If-Match,不能盲目替换。
在创建资源时误用If-Match
新建资源没有现存的ETag,If-Match要求资源已存在,否则会失败。创建应使用If-None-Match: *确保不存在才创建,避免重复创建或覆盖已有数据。
试着用自己的话回答

面试官还会怎么问?

服务器收到If-Match和If-Unmodified-Since都返回412时,客户端应该怎么做?

412表示预条件失败,说明资源已被他人修改。客户端应放弃本次提交,重新GET获取最新版本,合并改动后再带新ETag重试,避免盲目覆盖。

If-Match允许使用*通配符吗?

允许。If-Match: *要求资源已存在,否则条件失败;常用于更新已存在资源,不用于新建。防止新建覆盖(即资源已存在时创建)应使用If-None-Match: *。具体见RFC9110。

多主复制或分布式系统中,HTTP条件请求能否解决跨节点并发?

不能。HTTP条件请求依赖单个服务器的一致状态,分布式需借助版本向量或事务机制。若节点间状态不同步,条件校验可能在本地通过却全局冲突。

从一道题,走向一组知识

把知识连起来

缓存与代理

HTTP 缓存如何计算响应的当前 Age,经过多级代理时 Age 头与 Date 头怎样参与计算?

同属「缓存与代理」专题,接着看 HTTP Age 头计算 多级代理 Date RFC9111 在具体场景中的处理方式。

缓存与代理

HTTP 缓存中「新鲜度」和「验证」分别解决什么问题,命中缓存的完整判定流程是怎样的?

同属「缓存与代理」专题,接着看 HTTP 缓存 fresh stale 验证 流程 在具体场景中的处理方式。

参考资料

  • RFC 9110 - HTTP Semantics

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 条件头在写请求中的判定过程
  3. 编辑文档的并发冲突
  4. 适用边界与易失效条件
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑