golang redis 分布式锁

随机value 防止释放其他服务的锁 不可重入分布式锁

import (
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"github.com/go-redis/redis/v7"
	"time"
)


//分布式锁实现(不可重入)
type RedisLock struct {
	LockKey string
	value   string
}

//保证原子性
var delScript = `
if redis.call('get',KEYS[1])==ARGV[1] then
	return redis.call('del',KEYS[1])
else
	return 0
end
`

func (rl *RedisLock) Lock(client *redis.Client, timeout int) error {
	//随机数
	if client == nil {
		return errors.New("redis client is nil")
	}
	b := make([]byte, 16)
	_, err := rand.Read(b)
	if err != nil {
		return err
	}
	rl.value = base64.StdEncoding.EncodeToString(b)
	ok, err := client.SetNX(rl.LockKey, rl.value, time.Duration(timeout)*time.Second).Result()
	if err !=nil && !ok {
		errMsg := fmt.Sprintf("lock filed")
		return errors.New(errMsg)
	} else if err == nil {
		return nil
	} else {
		errMsg := fmt.Sprintf("redis lock fail err: %v", err)
		return errors.New(errMsg)
	}
}

//解锁
func (rl *RedisLock) Unlock(client *redis.Client) error {
	if client == nil {
		return errors.New("redis client is nil")
	}
	_, err := client.Eval(delScript, []string{rl.LockKey},[]string{rl.value}).Result()
	return err
}
posted @ 2021-06-02 23:37  海拉尔  阅读(242)  评论(0编辑  收藏  举报