场景分析-库存扣减

文章目录

背景

此种业务非常常见,就是对资源的扣减操作,常要达到的要求是就是性能要好,还不能超卖。

方案1,基于数据库乐观锁的方案,并发小

乐观锁通常是通过在数据库表中引入一个版本号(version)字段或时间戳字段来实现的。在执行更新操作时,数据库会检查该字段是否在本次事务开始之后被修改过。如果没有被修改,说明数据没有被其他事务改动,更新就可以成功。如果被修改过,更新就会失败,需要进行重试或处理失败逻辑。

实现步骤

  • 数据库表设计:

在涉及库存操作的表中增加一个 version 字段(整数类型)或 timestamp 字段。这个字段用于记录数据的版本号或最后修改时间。

例如,一个简单的库存表设计如下:

bash 复制代码
复制代码
CREATE TABLE product_stock (
    product_id INT PRIMARY KEY,
    stock INT NOT NULL,
    version INT NOT NULL
);
  • 查询数据:

当用户准备购买某个产品时,首先查询该产品的当前库存和版本号。

bash 复制代码
SELECT stock, version FROM product_stock WHERE product_id = 1;
  • 扣减库存
    在扣减库存时,使用 version 字段进行条件更新。这个更新语句会检查当前的 version 是否和查询时的一致,如果一致,则进行库存扣减和 version 增加操作。
bash 复制代码
UPDATE product_stock
SET stock = stock - 1, version = version + 1
WHERE product_id = 1 AND version = 1;

如果 version 不一致,说明在本次扣减之前,已经有其他事务修改了该记录,更新操作会失败(返回的受影响行数为0),此时需要处理失败逻辑。这里要注意一下,这里本来的update 操作,会触发排它锁,那为啥这里说的是通过乐观锁的机制,那里因为只有WHERE product_id = 1 AND version = 1; 判断这个是乐观锁的机制,只有满足条件后,才会执行加锁的操作,才会有排它锁的说法。

  • 处理并发冲突:

当更新操作失败时,可以选择重试操作。例如,重新查询最新的库存和版本号,然后再次尝试更新。

也可以返回提示用户当前商品库存不足,或直接放弃操作

方案2,基于redis和消息队列的方案,并发高

概念:通过将库存扣减请求写入消息队列(如 Kafka、RabbitMQ)进行异步处理,同时将库存放在 Redis 等缓存中进行快速扣减,最后再异步更新数据库。

实现:

秒杀请求到达时,首先在 Redis 中扣减库存,扣减成功后将请求放入消息队列进行异步处理。

后端消费消息队列中的请求,并最终更新数据库中的库存。

优点:这种方案能够大幅减少对数据库的直接操作压力,提升系统吞吐量

下面是一个结合 Redis 预扣减库存和消息队列的秒杀处理流程:

1.初始化库存:在秒杀开始前,将总库存加载到 Redis 中,例如 stock:product_id 键对应的值为库存数。

bash 复制代码
SET stock:1001 1000

2.扣减库存:用户发起秒杀请求时,首先扣减 Redis 中的库存。

bash 复制代码
DECRBY stock:1001 1

如果库存扣减成功,则将订单请求写入消息队列进行异步处理。否则提示用户秒杀失败。

3.异步处理:后台服务从消息队列中消费订单请求,并最终更新数据库中的库存。

bash 复制代码
// 消费消息队列中的订单请求
public void handleOrder(OrderRequest request) {
    // 根据订单请求,最终更新数据库库存并生成订单
}

4.恢复库存:如果处理订单失败,需要将 Redis 中的库存恢复。

bash 复制代码
INCRBY stock:1001 1

通用优化技巧

  • 分片操作,这里可以理解为mysql的分库分表操作,把mysql 锁的竞争分到多个库表上,也可以在其它环节上就用这个操作,比如把不同的流量打到不同的环境。总之就是要把争抢的资源,分到多个点上去竞争,降低对单一资源的争抢。
  • 提前限流,通过对接口限流,从源头上控制流量。
相关推荐
Cyanto41 分钟前
Spring注解IoC与JUnit整合实战
java·开发语言·spring·mybatis
qq_4338889342 分钟前
Junit多线程的坑
java·spring·junit
gadiaola1 小时前
【SSM面试篇】Spring、SpringMVC、SpringBoot、Mybatis高频八股汇总
java·spring boot·spring·面试·mybatis
写不出来就跑路1 小时前
WebClient与HTTPInterface远程调用对比
java·开发语言·后端·spring·springboot
Cyanto1 小时前
深入MyBatis:CRUD操作与高级查询实战
java·数据库·mybatis
datascome1 小时前
文章发布易优CMS(Eyoucms)网站技巧
数据库·经验分享·爬虫·数据采集·eyoucms·易优cms
麦兜*2 小时前
Spring Boot 集成Reactive Web 性能优化全栈技术方案,包含底层原理、压测方法论、参数调优
java·前端·spring boot·spring·spring cloud·性能优化·maven
天上掉下来个程小白2 小时前
MybatisPlus-06.核心功能-自定义SQL
java·spring boot·后端·sql·微服务·mybatisplus
知了一笑2 小时前
独立开发第二周:构建、执行、规划
java·前端·后端
有想法的py工程师2 小时前
PostgreSQL 锁等待监控,查找等待中的锁
数据库