package redislock import ( "context" "fmt" "time" "github.com/zeromicro/go-zero/core/stores/redis" ) // Lock is a small Redis lease. Value must uniquely identify the worker that // owns it; Release uses a Lua compare-and-delete to avoid deleting a renewed // lease owned by another worker. type Lock struct { client *redis.Redis key string owner string ttl time.Duration } func New(conf redis.RedisConf, key, owner string, ttl time.Duration) *Lock { return &Lock{client: redis.MustNewRedis(conf), key: key, owner: owner, ttl: ttl} } func (l *Lock) Acquire(ctx context.Context) (bool, error) { if l == nil || l.client == nil || l.key == "" || l.owner == "" { return false, fmt.Errorf("invalid redis lock") } seconds := int(l.ttl.Seconds()) if seconds < 1 { seconds = 1 } return l.client.SetnxExCtx(ctx, l.key, l.owner, seconds) } func (l *Lock) Release(ctx context.Context) error { if l == nil || l.client == nil { return fmt.Errorf("invalid redis lock") } _, err := l.client.EvalCtx(ctx, ` if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0 `, []string{l.key}, l.owner) return err }