数据库幂等设计:保障系统一致性的关键机制
做后端开发这些年,我越来越意识到一个看似“小细节”的设计——幂等性,其实直接关系到系统的生死。尤其是在微服务满天飞、网络环境复杂的今天,一次支付扣了两次钱?订单莫名其妙生成了两条?这些都不是代码写得不好,而是没把幂等这件事想明白。
今天就来聊聊【数据库幂等设计】,它是怎么帮我们在风浪中稳住数据底线的。
幂等到底是个啥?
先说人话:不管你干多少遍,结果都一样。
就像你按电梯按钮,第一次按下它亮了,之后你再狂拍十下,它也不会变成二十楼——这就是幂等。
在接口和数据库操作里也一样:
GET /user/123:查一次是张三,查十次还是张三 → 天然幂等。PUT /user/123:更新用户信息,每次都是“覆盖”,不会叠加 → 通常幂等。POST /orders:创建订单,点一次生成一单,点两次就是两单 → 非幂等!危险高发区!
我见过最惨的一次,前端按钮没防抖,用户连点三下“支付”,后台真扣了三笔款……客服差点被投诉到辞职。
为啥我们必须重视它?
不是我们不想优雅地处理请求,而是现实太“骨感”:
- 网络抽风:客户端发完请求,半天没回,以为失败了,自动重试。可实际上人家早就处理完了。
- 消息队列“好心办坏事”:Kafka 或 RabbitMQ 在消费失败时会重发消息,你以为是一条,其实是第三遍了。
- 用户手太快:页面还没跳转,“支付成功”还没弹出来,用户又点了——谁让加载动画太慢呢?
这些问题最后都会落到数据库头上:同一笔交易,被执行了N次怎么办?
轻则数据错乱,重则资损、客诉、背锅。
所以啊,别指望外部不出问题,能做的就是在自己的地盘上筑好防线。
实战中的几种常用方案(附踩坑经验)
1. 唯一索引 + 异常捕获:简单粗暴但有效
这是我最早用的方法,也是新手最容易上手的。
比如做支付记录表:
CREATE TABLE payment (
id BIGINT PRIMARY KEY,
order_no VARCHAR(64) UNIQUE NOT NULL, -- 关键在这里!
amount DECIMAL(10,2),
status TINYINT
);
