admin管理员组

文章数量:1130349

秒杀超卖现象:在高并发下,多个线程并发更新库存,导致库存为负的情况。

我搜集了一些资料,整理了一下,秒杀可选方案主要有以下三种:

1.超卖原因

一个简单的订单表

create table orders (
      sku_id int PRIMARY KEY,
      count int
)

一个/buy接口

begin()
count = db.Query(`select count  from orders where sku_id = '123'`)
if count < 0 {
    fmt.Println("卖光了")
    return ;
}
db.Exec(`update orders set count = count -1 where sku_id = '123'`)
commit()

由于sql 支持并行加上事务的隔离性,所以当多个事务并行时,select出来的值并不一定准确的,进而update之后的值也就不正确了。

方案一数据库悲观锁

数据库设置字段为无符号型
当并发超卖时直接报异常
通过捕获异常提示已经售空。

方案二:数据库悲观锁

采用排他锁
当用户同时到达更新操作,同时到达的用户一个个执行
在当前这个update语句commit之前,其他用户等待执行

解决方法:

begin()
update orders set count = count -1 where count > 0 and sku_id = '123'
commit()

这里是利用了update造成的行级锁,避免了超卖的问题。

优点:确保了线程安全。

缺点:高并发场景下会导致多个请求一直等待,数据库性能下降,系统的链接数上升,负载飙升,影响系统的平均响

秒杀超卖现象:在高并发下,多个线程并发更新库存,导致库存为负的情况。

我搜集了一些资料,整理了一下,秒杀可选方案主要有以下三种:

1.超卖原因

一个简单的订单表

create table orders (
      sku_id int PRIMARY KEY,
      count int
)

一个/buy接口

begin()
count = db.Query(`select count  from orders where sku_id = '123'`)
if count < 0 {
    fmt.Println("卖光了")
    return ;
}
db.Exec(`update orders set count = count -1 where sku_id = '123'`)
commit()

由于sql 支持并行加上事务的隔离性,所以当多个事务并行时,select出来的值并不一定准确的,进而update之后的值也就不正确了。

方案一数据库悲观锁

数据库设置字段为无符号型
当并发超卖时直接报异常
通过捕获异常提示已经售空。

方案二:数据库悲观锁

采用排他锁
当用户同时到达更新操作,同时到达的用户一个个执行
在当前这个update语句commit之前,其他用户等待执行

解决方法:

begin()
update orders set count = count -1 where count > 0 and sku_id = '123'
commit()

这里是利用了update造成的行级锁,避免了超卖的问题。

优点:确保了线程安全。

缺点:高并发场景下会导致多个请求一直等待,数据库性能下降,系统的链接数上升,负载飙升,影响系统的平均响

本文标签: 场景解决方案秒杀下超卖