欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

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

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

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

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

          Go Mutex 實(shí)現(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 悲觀鎖實(shí)現(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 樂觀鎖實(shí)現(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 分布式鎖實(shí)現(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號