PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

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

藏色散人
藏色散人 转载
2022-01-18 16:07:27 2964浏览

本文由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 <h5><span class="header-link octicon octicon-link"></span>MySQL 悲观锁实现</h5><pre class="brush:php;toolbar:false">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 <h5><span class="header-link octicon octicon-link"></span>MySQL 乐观锁实现</h5><pre class="brush:php;toolbar:false">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 <h5><span class="header-link octicon octicon-link"></span>Redis 分布式锁实现</h5><pre class="brush:php;toolbar:false">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 <h4><span class="header-link octicon octicon-link"></span>测试</h4><blockquote><p>涉及到服务、数据库等环境,此测试为伪代码</p></blockquote><pre class="brush:php;toolbar:false">func main() {
  var w sync.WaitGroup
  w.Add(20)
  for i := 0; i 
声明:本文转载于:learnku,如有侵犯,请联系admin@php.cn删除