Go库存扣减实现有多少方法,具体怎么做
导读:今天就跟大家聊聊有关“Go库存扣减实现有多少方法,具体怎么做”的内容,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 Go库存扣减的几种实现方法 这里使用了 grpc...
今天就跟大家聊聊有关“Go库存扣减实现有多少方法,具体怎么做”的内容,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Go库存扣减的几种实现方法
这里使用了 grpc、proto、gorm、zap、go-redis、go-redsync 等 package
Go Mutex 实现
var m sync.Mutexfunc (*InventoryServer) LockSell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) { tx := global.DB.Begin() m.Lock() for _, good := range req.GoodsInfo { var i model.Inventory if result := global.DB.Where(& model.Inventory{ Goods: good.GoodsId} ).First(& i); result.RowsAffected == 0 { tx.Rollback() // 回滚 return nil, status.Errorf(codes.InvalidArgument, "未找到此商品的库存信息。") } if i.Stocks good.Num { tx.Rollback() return nil, status.Errorf(codes.ResourceExhausted, "此商品的库存不足") } i.Stocks -= good.Num tx.Save(& i) } tx.Commit() m.Unlock() return & emptypb.Empty{ } , nil}
MySQL 悲观锁实现
func (*InventoryServer) ForUpdateSell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) { tx := global.DB.Begin() for _, good := range req.GoodsInfo { var i model.Inventory if result := tx.Clauses(clause.Locking{ Strength: "UPDATE", } ).Where(& model.Inventory{ Goods: good.GoodsId} ).First(& i); result.RowsAffected == 0 { tx.Rollback() return nil, status.Errorf(codes.InvalidArgument, "未找到此商品的库存信息。") } if i.Stocks good.Num { tx.Rollback() return nil, status.Errorf(codes.ResourceExhausted, "此商品的库存不足") } i.Stocks -= good.Num tx.Save(& i) } tx.Commit() return & emptypb.Empty{ } , nil}
MySQL 乐观锁实现
func (*InventoryServer) VersionSell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) { tx := global.DB.Begin() for _, good := range req.GoodsInfo { var i model.Inventory for { // 并发请求相同条件比较多,防止放弃掉一些请求 if result := global.DB.Where(& model.Inventory{ Goods: good.GoodsId} ).First(& i); result.RowsAffected == 0 { tx.Rollback() return nil, status.Errorf(codes.InvalidArgument, "未找到此商品的库存信息.") } if i.Stocks good.Num { tx.Rollback() // 回滚 return nil, status.Errorf(codes.ResourceExhausted, "此商品的库存不足") } i.Stocks -= good.Num version := i.Version + 1 if result := tx.Model(& model.Inventory{ } ). Select("Stocks", "Version"). Where("goods = ? and version= ?", good.GoodsId, i.Version). Updates(model.Inventory{ Stocks: i.Stocks, Version: version} ); result.RowsAffected == 0 { zap.S().Info("库存扣减失败!") } else { break } } } tx.Commit() // 提交 return & emptypb.Empty{ } , nil}
Redis 分布式锁实现
func (*InventoryServer) RedisSell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) { // redis 分布式锁 pool := goredis.NewPool(global.Redis) rs := redsync.New(pool) tx := global.DB.Begin() for _, good := range req.GoodsInfo { mutex := rs.NewMutex(fmt.Sprintf("goods_%d", good.GoodsId)) if err := mutex.Lock(); err != nil { return nil, status.Errorf(codes.Internal, "redis:分布式锁获取异常") } var i model.Inventory if result := global.DB.Where(& model.Inventory{ Goods: good.GoodsId} ).First(& i); result.RowsAffected == 0 { tx.Rollback() return nil, status.Errorf(codes.InvalidArgument, "未找到此商品的库存信息") } if i.Stocks good.Num { tx.Rollback() return nil, status.Errorf(codes.ResourceExhausted, "此商品的库存不足") } i.Stocks -= good.Num tx.Save(& i) if ok, err := mutex.Unlock(); !ok || err != nil { return nil, status.Errorf(codes.Internal, "redis:分布式锁释放异常") } } tx.Commit() return & emptypb.Empty{ } , nil}
测试
涉及到服务、数据库等环境,此测试为伪代码
func main() { var w sync.WaitGroup w.Add(20) for i := 0; i 20; i++ { go TestForUpdateSell(& w) // 模拟并发请求 } w.Wait()} func TestForUpdateSell(wg *sync.WaitGroup) { defer wg.Done() _, err := invClient.Sell(context.Background(), & proto.SellInfo{ GoodsInfo: []*proto.GoodsInvInfo{ { GoodsId: 16, Num: 1} , //{ GoodsId: 16, Num: 10} , } , } ) if err != nil { panic(err) } fmt.Println("库存扣减成功")}
关于“Go库存扣减实现有多少方法,具体怎么做”的内容就介绍到这,感谢各位的阅读,相信大家对Go库存扣减实现有多少方法,具体怎么做已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注网络,小编将为大家输出更多高质量的实用文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Go库存扣减实现有多少方法,具体怎么做
本文地址: https://pptw.com/jishu/653307.html