利用go特性实现高并发接口

一. 用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,解决了并发抢购超卖的问题,实现快速,成本低。

  缺点:阻塞是一个办法,但不是非常好的解决方案,它简单粗暴,没有队列的削峰填谷那般巧妙,单纯靠 加锁 用于小并发没事,高并发 加锁就是灾难,用户都在等待。。。

  有什么高见欢迎大佬们在评论区指点。

你可能感兴趣的:(go,go)