您好,欢迎访问一九零五行业门户网

详解Go库存扣减如何实现的(多种方法)

本文由golang教程栏目给大家介绍关于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库存扣减如何实现的(多种方法)的详细内容。
其它类似信息

推荐信息