redis sku有版本号设计,拿到,消费(版本号不一致要强制更新的逻辑)

一个简单的下单流程包括,商品校验,订单计价,扣库存,保存订单。其中扣库存的并发问题是整个流程中最麻烦,最复杂的环节,可以说聚集了所有的智慧和头发。

[](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27fed60fbe504eada90deee12a00d7f7~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?)

解决扣库存并发问题,很容易让人想到加锁,加锁的目的是为了限制同步代码块并发,进一步的保证原子性,可见性和重排序,实现数据一致性。

单机加 jvm 锁,分布式加分布式锁。这让我不禁想起分布式系统一句黑话,分布式系统中,没有什么问题是不能通过增加中间环节解决的,但解决一个问题常常会带来另外的问题,是的,你没听错,以空间换时间,以并发换数据一致性,在这里,锁粒度和范围对并发影响是最直接的,设计的时候尽可能的缩小锁粒度和范围,一般粒度是 skuId,范围尽量减小。

锁时长,锁过期是另外两个不得不考虑的问题。最麻烦的锁过期,常用解决方案是依赖 redission 的看门狗机制,相当于定时任务给锁续命,但粗暴续命会增加 rt,同时增加其他请求的阻塞时长。

尽量避免牺牲并发的方案!

尽量避免牺牲并发的方案!

尽量避免牺牲并发的方案!

一次偶然的机会,我的同事向我推荐了 Google 的 chubby。为什么我们不能用悲观锁+乐观锁的组合呢?在锁过期的时候,乐观锁兜底,不影响请求 rt,也能保证数据一致性。这是个不错的方案,适合简单的场景!

一次偶然的机会,一条公式冲击我的大脑,redis = 高性能 + 原子性。机智的你肯定知道加锁就是为了保证原子性,基于 redis 实现分布式锁也是因为 redis 的原子性和高性能(想想什么情况用 mysql 和 zk),如果我用 redis 代替锁,是不是既能保证扣库存的原子性,同时因为没有锁,又不需要考虑加锁带来的问题。

说干就干,马上画个图。(图片被掘金压缩,有点糊,我上传到图床,点击能跳转到图床看清晰的,如果看不清楚图片,联系我,给我留言

我把订单流程分为5大块,有点复杂,且听我细细道来。

Untitled

Order process:

扣库存是限制订单并发的瓶颈,依靠 redis 的原子性保证数据一致性,高性能提升并发

2pc

基于二阶段提交思想,第一步首先插入 INIT 状态的订单

冷热路由