Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

测试一些常见的显示

其他语言代码块

1
2
3
4
5
6
public void rollbackStock(Long skuId, Long userId) {
if (result == 0) {
log.warn("活动已结束,跳过 Redis 回补,skuId={}", skuId);
// DB 库存还是要回补的,但 Redis 不动
}
}

行内代码块

rollbackStock(Long skuId, Long userId)

列表 & 加粗 & 高亮

  • EXISTS 判断必须在 Lua 里:如果在 Java 里先 EXISTS 再调用回补,两步之间不原子,Key 可能刚好在中间被清理
  • DB 库存还是要回补DB 是数据的最终事实源,跟活动是否结束无关;只有 Redis 不补
  • 可以加日志:返回 0 时记录”活动结束未回补”,便于对账

引用

解决方案:CAS 乐观锁

两个 SQL 都加上 WHERE status=0 条件:

1
2
3
4
-- 支付回调
UPDATE order SET status=1 WHERE id=X AND status=0
-- 关单任务
UPDATE order SET status=2 WHERE id=X AND status=0

MySQL 的行锁会让两个 UPDATE 串行执行,先到的成功(rows=1),后到的因为 status 已经不是 0 而失败(rows=0)。然后业务代码判断 rows > 0 决定是否继续后续逻辑。

三种竞态情况都能正确处理

场景 支付先到 关单先到
数据库行为 支付成功(status=1),关单失败 关单成功(status=2),支付失败
业务后果 用户已支付,正常 订单关闭,支付回调拒绝(要触发退款)

一级

二级

三级

四级

五级

这是一个特别长的标题–hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh