文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go库存扣减怎么实现

2023-06-26 06:42

关注

这篇文章主要介绍了Go库存扣减怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇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库存扣减怎么实现”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯