@@ -0,0 +1,7 @@ | |||
package md | |||
// 缓存key统一管理, %s格式化为masterId | |||
const ( | |||
OneCirclesNowPriceUpdateLock = "%s:one_circles_now_price" // 当前价格(能拿到锁才能更新价格) | |||
DealOneCirclesNowPriceRequestIdPrefix = "%s:one_circles_now_price:%d" | |||
) |
@@ -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 | |||
} | |||
@@ -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 | |||
} |
@@ -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 | |||
} |