如何设计一个秒杀系统(一)

本文深入探讨秒杀系统的业务及代码逻辑,介绍如何利用事务、乐观锁、令牌桶算法等技术解决高并发下的库存超卖问题,以及通过Redis和RabbitMQ优化系统性能。

目录

秒杀的业务逻辑

秒杀的代码逻辑

基于事务的秒杀

悲观锁解决多线程并发事务问题


 

秒杀中应用的技术点

 

1.事务操作:校验库存、扣除库存、创建订单一气呵成

2.乐观锁:防止多线程并发下商品超卖

3.令牌桶算法:实现限流、RabbitMQ、Hystrix、Sentinel均可以实现同样的功能

4.Redis:隐藏秒杀接口、限制用户秒杀频率

5.基于RabbitMQ实现消息的异步处理

 

 

秒杀的业务逻辑

 

首先看数据库

有两张表,一张订单表,一张库存表。库存表中的count字段代表“一开始一共有多少库存”、sale字段代表“已售了多少” 、version用来记录“乐观锁的版本号”

再来看业务

“秒杀”代表这抢购,抢购就先查库存是否有剩余然后创建订单,后面可能还要支付啊,取消订单退回库存等一系列事务操作。

 

 

秒杀的代码逻辑

 

请求进来后先走Controller,在Service层依次校验库存、扣除库存、创建订单。最新持久化到DB中

 

 

基于事务的秒杀

 

我们来看Service,增加事务注解是为了保证多个对数据库的操作同步。

@Service
@Transactional
public class msServiceImpl implements msService {
    @Autowired
    private StockDAO stockDAO;

    @Autowired
    private OrderDAO orderDAO;

    @Override
    public int kill(Integer id){
        //根据商品id校验库存
        Stock stock = stockDAO.checkStock(id);
        if(stock.getSale().equals(stock.getCount())){
            throw new RuntimeException("库存不足");
        }else {
            //扣除库存
            stock.setSale(stock.getSale()+1);
            stockDAO.updataSale(stock);
            //创建订单
            Order order = new Order();
            order.setSid(stock.getId()).setName(stock.getName()).setCreateDate(new Date());
            orderDAO.createOrder(order);
            return order.getId();
        }
    }
}

我们自己测试时,也确实不会有问题。但当我们用Jmeter等测试工具模拟上千并发时,就会出现多线程的问题了,库存和订单记录都会莫名其妙的多上百条,学过多线程的朋友应该知道,这是因为我们没有使用锁操作。

 

 

悲观锁解决多线程并发事务问题

 

我们引入了Sychronized锁,也叫做悲观锁。

在Service的方法上添加synchronized关键字之后,你会发现订单表和库存表的数量仍然对不上。

public synchronized int kill(Integer id){}

这是使用Sychronized的一个大坑。注意:我们在类上添加了事务操作Transactional,又在方法上添加了Sychronized锁机制。程序运行时走的是2个同步,当事务执行完时,此时老的线程由于释放Sychronized锁,新线程拿着sychronized锁来了。 当事务准备提交时,带着刚来的新线程提交了一份,当这个新线程执行完毕后,事务又把它提交了一份。这就造成了数据重复。

 

因此,如果想要用悲观锁解决线程同步的问题,一定要确保synchronized操作在transactional之前,我们可以把sychronized放在controller中

悲观锁会给一个进程上锁,其他所有进程都处于阻塞状态,浪费了程序性能也降低了用户体验。下一篇我们从乐观锁开始搞起

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值