一. 用go语言自带的锁。
下面代码为抢购Api
。
//锁
var mu sync.Mutex
//抢购Api
func (this *RushController) Purchase() {
//商品ID
goods_id := int64(1)
//加锁
mu.Lock()
//结束时解锁
defer mu.Unlock()
//orm
o := orm.NewOrm()
//读取商品信息
m := models.Goods{Id: goods_id}
err := o.Read(&m)
if err != nil{
code,_ := beego.AppConfig.Int("paramError")
this.ErrorJson(code, "数据错误")
}
//检查库存
if m.Sku <= 0{
code,_ := beego.AppConfig.Int("systemError")
this.ErrorJson(code, "该商品已售罄")
}
//更新库存
m.Sku--
_,err = o.Update(&m)
//订单入库
order := models.Order{
UserId: 1,
GoodsId: goods_id,
CreateTime: time.Now().Unix(),
}
o.Insert(&order)
//返回
arr := make(map[string]interface{})
this.SuccessJson(arr)
}
二. 用go语言的channel。
下面代码为处理订单进程
代码。
//订单channel
var chOrders chan models.Order = make(chan models.Order)
// 抢购code
const (
buySuccess = iota // 抢购成功
buyFail // 抢购失败
)
// 单线程死循环,专注处理数据更新
func RunRush() {
for {
//接收订单
order := <-chOrders
//orm
o := orm.NewOrm()
//读取商品信息
m := models.Goods{Id: order.GoodsId}
o.Read(&m)
if m.Sku <= 0 {
//无库存,通知回调失败
order.Callback <- buyFail
}else{//有库存
//更新库存
m.Sku -= 1
o.Update(&m)
//订单入库
o.Insert(&order)
//通知回调成功
order.Callback <- buySuccess
}
}
}
下面代码为抢购Api
。
//抢购Api
func (this *RushController) Purchase() {
//商品ID
goods_id := int64(1)
//orm
o := orm.NewOrm()
//读取商品信息
m := models.Goods{Id: goods_id}
err := o.Read(&m)
if err != nil{
code,_ := beego.AppConfig.Int("paramError")
this.ErrorJson(code, "数据错误")
}
//检查库存
if m.Sku <= 0{
code,_ := beego.AppConfig.Int("systemError")
this.ErrorJson(code, "该商品已售罄")
}
// 构造一个回调的channel
callback := make(chan uint)
//订单
order := models.Order{
UserId: 1,
GoodsId: goods_id,
CreateTime: time.Now().Unix(),
Callback: callback,
}
// 把订单发送给channel
chOrders <- order
// 回调的channel等待处理结果
code := <- callback
if code == buySuccess{
//抢购成功
arr := make(map[string]interface{})
this.SuccessJson(arr)
}else{
//抢购失败
code,_ := beego.AppConfig.Int("systemError")
this.ErrorJson(code, "抢购失败")
}
}
总结
优点:利用go语言自带的锁和channel,解决了并发抢购超卖的问题,实现快速,成本低。
缺点:阻塞是一个办法,但不是非常好的解决方案,它简单粗暴,没有队列的削峰填谷那般巧妙,单纯靠 加锁 用于小并发没事,高并发 加锁就是灾难,用户都在等待。。。
有什么高见欢迎大佬们在评论区指点。