45 lines
1.2 KiB
Go
45 lines
1.2 KiB
Go
package redisdao
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/global"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// unlockScript 仅当锁值匹配时才删除,防止误删其他持有者的锁
|
|
var unlockScript = redis.NewScript(`
|
|
if redis.call('GET', KEYS[1]) == ARGV[1] then
|
|
return redis.call('DEL', KEYS[1])
|
|
else
|
|
return 0
|
|
end
|
|
`)
|
|
|
|
// TryLock 尝试获取分布式锁(SET NX EX),获取成功返回 true。
|
|
// value 建议传唯一标识(如 request_id / uuid),用于释放时校验持有者。
|
|
func TryLock(ctx context.Context, key, value string, ttl time.Duration) (bool, error) {
|
|
ctx, span := global.Tracer.Start(ctx, "redisdao.TryLock")
|
|
defer span.End()
|
|
|
|
ok, err := global.RedisEngine.SetNX(ctx, key, value, ttl).Result()
|
|
if err != nil {
|
|
span.RecordError(err)
|
|
return false, err
|
|
}
|
|
return ok, nil
|
|
}
|
|
|
|
// Unlock 释放分布式锁,仅当 value 匹配时才删除;锁不存在或不属于自己时静默返回。
|
|
func Unlock(ctx context.Context, key, value string) error {
|
|
ctx, span := global.Tracer.Start(ctx, "redisdao.Unlock")
|
|
defer span.End()
|
|
|
|
if err := unlockScript.Run(ctx, global.RedisEngine, []string{key}, value).Err(); err != nil {
|
|
span.RecordError(err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|