分库分表后,唯一索引失效了,幂等怎么办
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
订单表按 user_id 分了 16 片。订单号全局唯一,同一个用户还是在 3 秒里下了三单。 三单都成功了。三笔库存都扣了。 我们一直以为订单号唯一就够了。 01 唯一索引,只在单库生效 分库分表之后,唯一索引是每个分片自己的约束,不是全局约束。 订单号唯一,挡的是重复主键。挡不住同一用户对同一活动重复下单。 这是两个不同的唯一性。 一个是主键唯一,一个是业务唯一。分片之后,前者还在,后者没了。 很多人是在出了重复单之后,才第一次意识到这件事。 02 先分清三种唯一 大部分重复下单,缺的是第二种。 大部分重复提交,缺的是第三种。 先分清缺哪一种,再谈方案。混在一起,就会写出一个什么都防不住的唯一索引。 我见过一个索引,把订单号、用户 ID、时间戳全塞进去。它确实唯一,但业务上毫无意义。 03 四层方案
图 1 分库分表后的四层幂等防线 第一层是幂等号,客户端生成 requestId,服务端落库前去重。它挡的是同一个请求被提交两次。 第二层是路由表,业务键到分片。同一用户必须落在同一片,后面的本地约束才有意义。 第三层是分片内唯一索引,用户 ID 加业务键。只要分片键选的是 user_id,这一层就能生效。 第四层是异步对账,发现漏网的重复单,关单或退款。 关键不在方案多,在分片键。分片键选对了,跨片问题根本不会出现。 选错了,就得用下面这些更贵的办法补。 04 三种跨分片校验,代价不一样 三种都能用,但没有一种比选对分片键更便宜。 广播查询在 16 片时还能忍,到了 64 片就是灾难。 双写听起来简单,两个分片写成功一个失败一个的时候,你还是要面对不一致。 05 落地顺序 先定分片键,再定业务唯一键,然后补幂等号,最后上对账。 顺序反了,就会先写一堆补偿代码,再回头发现分片键选错。 分片键要满足两个条件,高频查询带它,业务唯一约束也带它。 只满足第一个,查询快了,约束还是空的。 这两个条件通常冲突。冲突的时候,先保约束,再想办法解决查询。 06 最后 那三单退了两单,库存回滚了一次。 后来我们把活动 ID 也放进了分片键的组合,同一用户同一活动必然同片,唯一索引终于能拦住。 分库分表不是把表拆开,是把数据库帮你保证的东西,一条条接回应用层。 接漏一条,线上就会替你发现。 阅读原文:点击这里 该文章在 2026/10/28 10:34:46 编辑过 |
关键字查询
相关文章
正在查询... |