← 返回并发与锁
🔁 幂等性
重复执行结果不变 —— 用户连点两次只扣一次钱
❌ 不幂等(扣两次)
用户点支付 → 网络超时 → 用户再点 → 扣了两次钱
✅ 幂等(只扣一次)
用户点支付 → 带唯一 requestId → 再点带同样的 requestId → 第二次发现已处理,直接返回成功
// ✅ 方案1:唯一索引(数据库层,最可靠)
try {
orderDao.insert(order); // requestId 建唯一索引
payDao.deduct(money);
} catch (DuplicateKeyException e) {
return "已支付"; // requestId 已存在,已处理过
}
// ✅ 方案2:Redis 标记(应用层,快)
boolean isNew = redis.setIfAbsent("pay:"+requestId, "1", 24, HOURS);
if (!isNew) return "已支付"; // key 已存在=已处理
// ✅ 方案3:Token 机制(前端先获取一次性token)
// 前端先 GET /token → 提交时带token → 后端 redis.del(token) → 返回1才处理
// ✅ 方案4:状态机(业务层)
int n = orderDao.updateStatus(id, "UNPAID", "PAID");
// WHERE status='UNPAID' → 只能改一次,再调返回0
if (n == 0) return "已支付";
天然幂等:GET、DELETE、PUT(指定ID全量更新)。非幂等:POST(新增)。写接口(资金/订单/支付)必须强制幂等!
四种方案:① 唯一索引(DB层,最可靠);② Redis setnx(应用层,快);③ Token机制(前端配合);④ 状态机(有状态流转)。核心都是用唯一标识判断"是否处理过"。
并发与锁 · 幂等性 · 全栈资料库