redsync的使用问题
集成之后如果库存不足系统也会强行报错
相关代码:
func (s *Service) Sell(ctx context.Context, request *inventorypb.SellInfoRequest) (*emptypb.Empty, error) {
tx := s.DB.Begin()
for _, goodsInfo := range request.GoodsInfo {
mutex := s.RedSync.NewMutex(fmt.Sprintf("inv_%d", goodsInfo.GoodsId))
if err := mutex.Lock(); err != nil {
s.Logger.Error("can not get redis lock", zap.Error(err))
return nil, status.Error(codes.Internal, "")
}
var inv model.Inventory
res := s.DB.Where(&model.Inventory{GoodsID: goodsInfo.GoodsId}).First(&inv)
if res.Error != nil {
s.Logger.Error("can not get inv", zap.Error(res.Error))
return nil, status.Error(codes.Internal, "")
}
if res.RowsAffected == 0 {
// 没有该商品的库存信息
tx.Rollback()
return nil, status.Error(codes.NotFound, "")
}
if inv.Stocks < goodsInfo.Num {
// 现有库存小于购买数量
tx.Rollback()
return nil, status.Error(codes.ResourceExhausted, "")
}
// 数据库真实扣减小于预期扣减,超卖问题
inv.Stocks -= goodsInfo.Num
tx.Save(&inv)
if ok, err := mutex.Unlock(); !ok || err != nil {
s.Logger.Error("redis can not unlock")
return nil, status.Error(codes.Internal, "")
}
}
tx.Commit()
return &emptypb.Empty{}, nil
}
func TestConcurrentSell(t *testing.T) {
client := initClient()
var wg sync.WaitGroup
for i := 0; i < 20; i ++ {
wg.Add(1)
go func() {
_, err := client.Sell(context.Background(), &inventorypb.SellInfoRequest{
GoodsInfo: []*inventorypb.GoodsInvInfoRequest{
{
GoodsId: 421,
Num: 1,
},
},
})
if err != nil {
t.Error(err)
}
wg.Done()
}()
}
wg.Wait()
}
37
收起
正在回答 回答被采纳积分+1
1回答
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星