站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        詳解Go庫存扣減如何實現(xiàn)的(多種方法)

        本文由golang教程欄目給大家介紹關(guān)于Go 庫存扣減的幾種實現(xiàn)方法,希望對需要的朋友有所幫助!

        Go 庫存扣減的幾種實現(xiàn)方法

        這里使用了 grpc、proto、gorm、zap、go-redis、go-redsync 等 package

        Go Mutex 實現(xiàn)
        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 悲觀鎖實現(xiàn)
        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 樂觀鎖實現(xiàn)
        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 { // 并發(fā)請求相同條件比較多,防止放棄掉一些請求             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 分布式鎖實現(xiàn)
        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}

        測試

        涉及到服務(wù)、數(shù)據(jù)庫等環(huán)境,此測試為偽代碼

        func main() {   var w sync.WaitGroup   w.Add(20)   for i := 0; i < 20; i++ {       go TestForUpdateSell(&w) // 模擬并發(fā)請求   }   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("庫存扣減成功")}

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 国产精品无码素人福利| 亚洲综合精品网站在线观看| 久久乐国产精品亚洲综合| 国产精品多人p群无码| 亚洲性日韩精品国产一区二区| 999国产精品色在线播放| 国精品无码一区二区三区在线| 国产小呦泬泬99精品| 久久国产精品-久久精品| 久久精品国产亚洲AV无码麻豆| 久久免费99精品国产自在现线| 中文字幕亚洲精品| 6一12呦女精品| 精品无码久久久久久尤物| 亚洲av无码成人精品国产| 久久97久久97精品免视看| 老司机69精品成免费视频| www.亚洲精品| 99免费精品视频| 欧美精品欧美人与动人物牲交| 亚洲精品线路一在线观看| 欧美成人精品一区二区综合| 99久久精品免费看国产| 91午夜精品亚洲一区二区三区| 久久精品国产91久久综合麻豆自制 | 中文字幕精品一区二区三区视频| 国产午夜精品一区二区三区不卡 | 真实国产精品vr专区| 伊在人亚洲香蕉精品区麻豆| 无码AV动漫精品一区二区免费| 精品亚洲视频在线观看| 久久99国产精品成人欧美| 老子影院午夜精品无码| 日韩人妻无码精品无码中文字幕| 欧美黑人巨大videos精品| 欧美午夜精品一区二区三区91 | 久久97久久97精品免视看| 精品欧美激情在线看| 久久久久99精品成人片三人毛片 | 在线观看亚洲精品国产| 亚洲日韩精品无码专区网站|