You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
1.5 KiB
70 lines
1.5 KiB
package dao |
|
|
|
import ( |
|
"context" |
|
"math/rand" |
|
"time" |
|
|
|
"go-common/library/cache/redis" |
|
"go-common/library/log" |
|
) |
|
|
|
func randomString(l int) string { |
|
str := "0123456789abcdefghijklmnopqrstuvwxyz" |
|
bytes := []byte(str) |
|
result := []byte{} |
|
r := rand.New(rand.NewSource(time.Now().UnixNano())) |
|
for i := 0; i < l; i++ { |
|
result = append(result, bytes[r.Intn(len(bytes))]) |
|
} |
|
return string(result) |
|
} |
|
|
|
// Lock . |
|
func (d *Dao) Lock(ctx context.Context, realKey string, ttl int, retry int, retryDelay int) (gotLock bool, lockValue string, err error) { |
|
|
|
if retry <= 0 { |
|
retry = 1 |
|
} |
|
lockValue = "locked:" + randomString(5) |
|
retryTimes := 0 |
|
conn := d.redis.Get(ctx) |
|
defer conn.Close() |
|
|
|
for ; retryTimes < retry; retryTimes++ { |
|
var res interface{} |
|
res, err = conn.Do("SET", realKey, lockValue, "PX", ttl, "NX") |
|
if err != nil { |
|
log.Error("redis_lock failed:%s:%s", realKey, err.Error()) |
|
break |
|
} |
|
|
|
if res != nil { |
|
gotLock = true |
|
break |
|
} |
|
time.Sleep(time.Duration(retryDelay * 1000)) |
|
} |
|
return |
|
} |
|
|
|
// UnLock . |
|
func (d *Dao) UnLock(ctx context.Context, realKey string, lockValue string) (err error) { |
|
conn := d.redis.Get(ctx) |
|
defer conn.Close() |
|
res, err := redis.String(conn.Do("GET", realKey)) |
|
if err != nil { |
|
log.Error("redis_unlock get error:%s:%v", realKey, err) |
|
return |
|
} |
|
if res != lockValue { |
|
err = ErrUnLockGet |
|
return |
|
} |
|
|
|
_, err = conn.Do("DEL", realKey) |
|
if err != nil { |
|
log.Error("redis_unlock del error:%s:%v", realKey, err) |
|
} |
|
return |
|
}
|
|
|