程式碼
.
.
.
const redisMutexLockExpTime = 15
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 > 10 {
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
}
}
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 utils.AnyToInt64(do) == 1 {
return true, err
} else {
return false, err
}
}
func HandleBalanceDistributedLock(paramA,paramB,requestIdPrefix string) (cb func(), err error){
lockKey := fmt.Sprintf("%s:xxx_lock:%s", paramA, paramB)
requestId := GetDistributedLockRequestId(requestIdPrefix)
lockOk := TryGetDistributedLock(lockKey, requestId, true)
if !balanceLockOk {
return nil, errors.New("系統繁忙,請稍後再試")
}
cb = func() {
_, _ = ReleaseDistributedLock(lockKey, requestId)
}
return cb, nil
}
使用示例
cb, err := HandleBalanceDistributedLock(c.GetString("mid"), utils.IntToStr(user.Info.Uid), "acq_reward")
if err != nil {
return err
}
if cb != nil {
defer cb()
}
參考
部落格:redis應用系列一:分散式鎖正確實現姿勢
本作品採用《CC 協議》,轉載必須註明作者和本文連結
Was mich nicht umbringt, macht mich stärker