去掉枷锁

This commit is contained in:
李子铭 2025-03-21 13:38:51 +08:00
parent ab031b6048
commit 73a23aef4a
6 changed files with 130 additions and 62 deletions

1
go.mod
View File

@ -32,6 +32,7 @@ require (
gopkg.in/yaml.v2 v2.4.0
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.25.12
gorm.io/hints v1.1.2
)
require (

10
go.sum
View File

@ -128,7 +128,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@ -184,6 +183,9 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -461,9 +463,15 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o=
gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=

View File

@ -13,49 +13,49 @@ import (
func (v *VoucherBiz) CmbOrder(ctx context.Context, req *bo.OrderCreateReqBo) (orderNo string, err error) {
ctx, cancel := context.WithTimeout(ctx, 25*time.Second)
defer cancel()
c := vo.CmbOrderLockKey.BuildCache([]string{req.OutBizNo, req.Type.String()})
//c := vo.CmbOrderLockKey.BuildCache([]string{req.OutBizNo, req.Type.String()})
err = lock.NewMutex(v.rdb.Rdb, c.TTL).Lock(ctx, c.Key, func(ctx context.Context) error {
//err = lock.NewMutex(v.rdb.Rdb, c.TTL).Lock(ctx, c.Key, func(ctx context.Context) error {
order, err := v.OrderRepo.GetByOutBizNo(ctx, vo.OrderTypeCmb, req.OutBizNo)
order, err := v.OrderRepo.GetByOutBizNo(ctx, vo.OrderTypeCmb, req.OutBizNo)
if err != nil && !err2.IsDbNotFound(err) {
return err
}
if err != nil && !err2.IsDbNotFound(err) {
return orderNo, err
}
if order != nil {
if order != nil {
if order.Status.IsFail() {
if order.Status.IsFail() {
if err = v.orderRetry(ctx, order); err != nil {
return orderNo, err
if err = v.orderRetry(ctx, order); err != nil {
return err
}
}
orderNo = order.OrderNo
return nil
}
product, err := v.ProductRepo.GetByProductNo(ctx, req.ProductNo)
if err != nil {
return err
}
if !product.Channel.IsWeChat() {
return err2.ErrorCmbProductNotSupported("只支持微信")
}
order, err = v.order(ctx, req, product)
if err != nil {
return err
}
orderNo = order.OrderNo
return orderNo, err
}
product, err := v.ProductRepo.GetByProductNo(ctx, req.ProductNo)
if err != nil {
return orderNo, err
}
return nil
})
if !product.Channel.IsWeChat() {
return orderNo, err2.ErrorCmbProductNotSupported("只支持微信")
}
order, err = v.order(ctx, req, product)
if err != nil {
return orderNo, err
}
orderNo = order.OrderNo
return orderNo, nil
return
}
func (v *VoucherBiz) CmbQuery(ctx context.Context, orderNo string) (resp *v1.CmbQueryReply, err error) {
@ -130,29 +130,19 @@ func (v *VoucherBiz) CmbProductQuery(ctx context.Context, productNo string) (rep
inputFormat := time.RFC3339
if wechatResp.AvailableBeginTime != nil {
// 解析开始时间
availableBeginTime, _ := time.Parse(inputFormat, *wechatResp.AvailableBeginTime)
reps.StartTime = availableBeginTime.Format(time.DateTime)
reps.SaleStartTime = reps.StartTime
reps.SaleStartTime = reps.StartTime
}
if wechatResp.AvailableEndTime != nil {
// 解析结束时间
availableEndTime, _ := time.Parse(inputFormat, *wechatResp.AvailableEndTime)
reps.EndTime = availableEndTime.Format(time.DateTime)
reps.SaleEndTime = reps.EndTime
}
if wechatResp.StartTime != nil {
// 批次激活开启时间
s, _ := time.Parse(inputFormat, *wechatResp.StartTime)
reps.SaleStartTime = s.Format(time.DateTime)
}
if wechatResp.StopTime != nil {
// 批次永久停止时间
e, _ := time.Parse(inputFormat, *wechatResp.StopTime)
reps.SaleEndTime = e.Format(time.DateTime)
reps.SaleEndTime = reps.EndTime
}
reps.Amount = fmt.Sprintf("%d", *wechatResp.StockUseRule.FixedNormalCoupon.CouponAmount)

View File

@ -1,42 +1,52 @@
package data
import (
"context"
"errors"
"fmt"
"google.golang.org/protobuf/types/known/durationpb"
"gorm.io/gorm"
"gorm.io/hints"
"sync"
"testing"
"time"
"voucher/internal/biz/vo"
"voucher/internal/conf"
"voucher/internal/data/model"
)
func Test_db(t *testing.T) {
maxLifetime := durationpb.New(300) // 5分钟
func Test_gorm_db(t *testing.T) {
data := &conf.Data_Database{
Driver: "mysql",
Source: "root:lansexiongdi6,@tcp(47.97.27.195:3306)/voucher?parseTime=True&loc=Local",
MaxIdle: 50, // 空闲连接池
MaxOpen: 100, // 最大连接数
MaxLifetime: maxLifetime,
Source: "root:lsxddb123.@tcp(47.108.53.72:3306)/voucher?parseTime=True&loc=Local",
MaxIdle: 20, // 空闲连接池
MaxOpen: 200, // 最大连接数
MaxLifetime: durationpb.New(60), // 5分钟
IsDebug: false,
}
gormDb, cleanup := db(data)
defer cleanup()
start2 := time.Now()
concurrency := 10 // 调整并发数
errCount := 0
var wg sync.WaitGroup
const concurrency = 2 // 调整并发数
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
go func(i int) {
defer wg.Done()
var m model.Product
tx := gormDb.Model(model.Product{}).Where(model.Product{ProductNo: "000"}).First(&m)
ctx := context.Background()
var info model.Order
tx := gormDb.
WithContext(ctx).
Model(model.Order{}).
//Clauses(hints.UseIndex("udx_out_biz_no_type")).
Where(model.Order{Type: vo.OrderTypeCmb.GetValue(), OutBizNo: fmt.Sprintf("174252390990605ngywYrSAGE83e1%d", i)}).
First(&info)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
t.Errorf("未找到记录")
@ -45,9 +55,50 @@ func Test_db(t *testing.T) {
errCount += 1
}
}
}()
}(i)
}
wg.Wait()
fmt.Printf("\n--------------连接请求,总请求耗时: %v,总数: %d, 失败次数: %d--------------\n", time.Since(start2), concurrency, errCount)
t.Logf("\n--------------连接请求,总请求耗时: %v,总数: %d, 失败次数: %d--------------\n", time.Since(start2), concurrency, errCount)
}
func Test_db(t *testing.T) {
maxLifetime := durationpb.New(300) // 5分钟
data := &conf.Data_Database{
Driver: "mysql",
Source: "root:lansexiongdi6,@tcp(47.97.27.195:3306)/voucher?parseTime=True&loc=Local",
MaxIdle: 2, // 空闲连接池
MaxOpen: 10, // 最大连接数
MaxLifetime: maxLifetime,
IsDebug: false,
}
gormDb, cleanup := db(data)
defer cleanup()
start2 := time.Now()
errCount := 0
const concurrency = 2
for i := 0; i < concurrency; i++ {
ctx := context.Background()
var info model.Order
tx := gormDb.
WithContext(ctx).
Model(model.Order{}).
Clauses(hints.ForceIndex("udx_out_biz_no_type")).
Where(model.Order{Type: vo.OrderTypeCmb.GetValue(), OutBizNo: fmt.Sprintf("174252390990605ngywYrSAGE83e1%d", i)}).
First(&info)
if tx.Error != nil {
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
t.Errorf("未找到记录")
} else {
fmt.Printf("请求错误: %v\n", tx.Error)
errCount += 1
}
}
}
t.Logf("\n--------------连接请求,总请求耗时: %v,总数: %d, 失败次数: %d--------------\n", time.Since(start2), concurrency, errCount)
}

View File

@ -0,0 +1,18 @@
package helper
import (
"context"
"time"
)
// valueOnlyContext 包装一个只有value的context
type valueOnlyContext struct{ context.Context }
func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return }
func (valueOnlyContext) Done() <-chan struct{} { return nil }
func (valueOnlyContext) Err() error { return nil }
// CopyValueCtx 复制一个只有value的context
func CopyValueCtx(ctx context.Context) context.Context {
return valueOnlyContext{ctx}
}

View File

@ -77,6 +77,10 @@ func (s *VoucherService) CmbOrder(ctx http.Context) error {
func (v *VoucherService) cmbOrder(ctx http.Context) (string, error) {
//var ctxCopy http.Context
//copy(ctx, ctxCopy)
bodyBytes, err := io.ReadAll(ctx.Request().Body)
if err != nil {
return "", err2.ErrorCmbParamFail(err.Error())
@ -184,11 +188,7 @@ func (s *VoucherService) CmbQuery(ctx http.Context) error {
bizReply, err := s.cmbQuery(ctx)
if err != nil {
//se := errors.FromError(err)
//
//if len(se.Reason) == 0 {
// se.Reason = err2.CmbErr_CMB_UNKNOWN.String()
//}
req.RespCode = vo.CmbResponseStatusFail.GetValue()
req.RespMsg = err.Error()
req.BizContent = ""