如何解决Facebook并发请求时MySQL数据库fbid重复插入的问题
针对并发重复插入问题的解决方案
你当前已经配置的fbid字段UNIQUE约束是解决这个问题的核心基础,基于此可以直接做以下优化:
MySQL层面原生解决方案(优先推荐)
- 替换普通INSERT语句为
INSERT IGNORE
不需要保留你当前PHP层的前置存在性校验逻辑,直接执行INSERT IGNORE语句写入数据即可:遇到重复的fbid值时,MySQL会自动忽略本次插入操作,既不会抛出错误,也不会生成重复条目,相比原逻辑还能减少一次SELECT查询开销,性能更优。 - 可选使用
INSERT ... ON DUPLICATE KEY UPDATE语法
如果你遇到重复请求时需要更新该行的部分字段(比如最新请求时间、请求次数等),可以使用该语法:当触发唯一键冲突时会自动执行后续的UPDATE逻辑,不会生成新行,适合有字段更新需求的场景。
应用层补充优化方案(高并发场景可选)
- 加分布式锁兜底
可以在PHP层基于Redis实现细粒度分布式锁,锁的key设置为fbid_${sender},锁过期时间设置为1~3秒即可,只有拿到锁的请求才能执行后续的写入逻辑,从接入层就挡住短时间内的重复并发请求。 - 接入层请求去重
可以在Nginx或者API网关层配置规则,1秒内同一个fbid的相同参数请求只放行第一个到后端服务,减少无效的重复请求消耗后端资源。
原逻辑失效原因说明:
并行的两个请求会同时执行前置存在性查询,此时两个请求都得到记录不存在的结果,随后同时发起写入请求,UNIQUE约束只能保证最终只有一个请求写入成功,另一个会抛出唯一键冲突错误,这就是并发场景下前置校验失效的根本原因,这类场景下依赖数据库的原子操作是最可靠的解决方案。
内容的提问来源于stack exchange,提问作者STeveBobJohn
相关产品推荐
相关产品推荐

