dengbiao 6 months ago
parent
commit
0f55003a71
4 changed files with 122 additions and 35 deletions
  1. +7
    -0
      rule/one_circles/md/app_redis_key.go
  2. +5
    -35
      rule/one_circles/one_circles_deal_available_green_energy_points.go
  3. +84
    -0
      rule/one_circles/svc/svc_now_price_redis_mutex_lock.go
  4. +26
    -0
      rule/one_circles/svc/svc_price.go

+ 7
- 0
rule/one_circles/md/app_redis_key.go View File

@@ -0,0 +1,7 @@
package md

// 缓存key统一管理, %s格式化为masterId
const (
OneCirclesNowPriceUpdateLock = "%s:one_circles_now_price" // 当前价格(能拿到锁才能更新价格)
DealOneCirclesNowPriceRequestIdPrefix = "%s:one_circles_now_price:%d"
)

+ 5
- 35
rule/one_circles/one_circles_deal_available_green_energy_points.go View File

@@ -449,44 +449,14 @@ func DealAvailableGreenEnergyCoin(session *xorm.Session, kind int, amount, amoun
//更新 `one_circles_green_energy_basic_setting` 表
if chain.NowPrice != nowPriceValue {
chain.NowPrice = nowPriceValue
_, err := db.OneCirclesGreenEnergyBasicSettingUpdate(session, chain.Id, chain, "now_price")
if err != nil {
return err
}
//// 新增 / 更新 one_circles_green_energy_price 记录
//date := now.Format("2006-01-02")
//hour := zhios_order_relate_utils.IntToStr(now.Hour())
//oneCirclesGreenEnergyPrice, err := db.OneCirclesGreenEnergyPriceGetOneByParamsBySession(session, date, hour)
//if err != nil {
// return err
//}
//if oneCirclesGreenEnergyPrice == nil {
// oneCirclesGreenEnergyPrice = &model.OneCirclesGreenEnergyPrice{
// Price: nowPriceValue,
// Date: date,
// Hour: hour,
// }
// insertId, err1 := db.OneCirclesGreenEnergyPriceInsertBySession(session, oneCirclesGreenEnergyPrice)
// if err1 != nil {
// return err1
// }
// if insertId <= 0 {
// return errors.New("插入 one_circles_green_energy_price 失败")
// }
//} else {
// oneCirclesGreenEnergyPrice.Price = nowPriceValue
// _, err1 := db.OneCirclesGreenEnergyPriceUpdate(session, oneCirclesGreenEnergyPrice.Id, oneCirclesGreenEnergyPrice, "price")
// if err1 != nil {
// return err1
// }
// //if updateAffected <= 0 {
// // return errors.New("更新 one_circles_green_energy_price 失败")
// //}
//}
}
_, err := db.OneCirclesGreenEnergyBasicSettingUpdate(session, chain.Id, chain)
if err != nil {
return err
}

//插入 `one_circles_available_green_energy_points_flow` 记录
_, err := db.OneCirclesAvailableGreenEnergyPointsFlowInsert(session, &oneCirclesAvailableGreenEnergyPointsFlow)
_, err = db.OneCirclesAvailableGreenEnergyPointsFlowInsert(session, &oneCirclesAvailableGreenEnergyPointsFlow)
if err != nil {
return err
}


+ 84
- 0
rule/one_circles/svc/svc_now_price_redis_mutex_lock.go View File

@@ -0,0 +1,84 @@
package svc

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/one_circles/md"
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/cache"
"errors"
"fmt"
"math/rand"
"reflect"
"time"
)

const redisMutexLockExpTime = 15

// TryGetDistributedLock 分布式锁获取
// requestId 用于标识请求客户端,可以是随机字符串,需确保唯一
func TryGetDistributedLock(lockKey, requestId string, isNegative bool) bool {
if isNegative { // 多次尝试获取
retry := 1
for {
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX")
// 获取锁成功
if err == nil && ok == "OK" {
return true
}
// 尝试多次没获取成功
if retry > 99 {
return false
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000)))
retry += 1
}
} else { // 只尝试一次
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX")
// 获取锁成功
if err == nil && ok == "OK" {
return true
}

return false
}
}

// ReleaseDistributedLock 释放锁,通过比较requestId,用于确保客户端只释放自己的锁,使用lua脚本保证操作的原子型
func ReleaseDistributedLock(lockKey, requestId string) (bool, error) {
luaScript := `
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end`

do, err := cache.Do("eval", luaScript, 1, lockKey, requestId)
fmt.Println(reflect.TypeOf(do))
fmt.Println(do)
if zhios_order_relate_utils.AnyToInt64(do) == 1 {
return true, err
} else {
return false, err
}
}

func GetDistributedLockRequestId(prefix string) string {
return prefix + zhios_order_relate_utils.IntToStr(rand.Intn(100000000))
}

// HandleDistributedLock 处理余额更新时获取锁和释放锁 如果加锁成功,使用语句 ` defer cb() ` 释放锁
func HandleDistributedLock(masterId, requestIdPrefix string) (cb func(), err error) {
// 获取余额更新锁
balanceLockKey := fmt.Sprintf(md.OneCirclesNowPriceUpdateLock, masterId)
requestId := GetDistributedLockRequestId(requestIdPrefix)
balanceLockOk := TryGetDistributedLock(balanceLockKey, requestId, true)
if !balanceLockOk {
return nil, errors.New("系统繁忙,请稍后再试")
}

cb = func() {
_, _ = ReleaseDistributedLock(balanceLockKey, requestId)
}

return cb, nil
}

+ 26
- 0
rule/one_circles/svc/svc_price.go View File

@@ -0,0 +1,26 @@
package svc

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/one_circles/md"
"fmt"
"time"
"xorm.io/xorm"
)

func GetPrice(engine *xorm.Engine, masterId string) (basic *model.OneCirclesGreenEnergyBasicSetting, cb func(), err error) {
requestIdPrefix := fmt.Sprintf(md.DealOneCirclesNowPriceRequestIdPrefix, masterId, time.Now().UnixMicro())
cb, err = HandleDistributedLock(masterId, requestIdPrefix)
if err != nil {
return
}
basic, err = db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{
"key": "is_open",
"value": 1,
})
if err != nil {
return
}
return
}

Loading…
Cancel
Save