Loading... ```golang // ------------------------------------ // - redis锁 // ------------------------------------ redisLock := redis.NewRedisLock(l.svcCtx.Config.Redis.NewRedis(), "updateOrderStatus") redisLock.SetExpire(1) // 过期时间 if ok, err := redisLock.Acquire(); !ok || err != nil { logx.Error("当前有其它用户正在操作,请稍后重试:", err) return nil } defer func() { recover() // 释放锁 _, _ = redisLock.Release() }() ``` > NewRedisLock 路径 `github.com\zeromicro\go-zero@v1.3.4\core\stores\redis\redislock.go` ```golang package redis import ( "math/rand" "strconv" "sync/atomic" "time" red "github.com/go-redis/redis/v8" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stringx" ) const ( randomLen = 16 tolerance = 500 // milliseconds millisPerSecond = 1000 lockCommand = `if redis.call("GET", KEYS[1]) == ARGV[1] then redis.call("SET", KEYS[1], ARGV[1], "PX", ARGV[2]) return "OK" else return redis.call("SET", KEYS[1], ARGV[1], "NX", "PX", ARGV[2]) end` delCommand = `if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end` ) // A RedisLock is a redis lock. type RedisLock struct { store *Redis seconds uint32 key string id string } func init() { rand.Seed(time.Now().UnixNano()) } // NewRedisLock returns a RedisLock. func NewRedisLock(store *Redis, key string) *RedisLock { return &RedisLock{ store: store, key: key, id: stringx.Randn(randomLen), } } // Acquire acquires the lock. func (rl *RedisLock) Acquire() (bool, error) { seconds := atomic.LoadUint32(&rl.seconds) resp, err := rl.store.Eval(lockCommand, []string{rl.key}, []string{ rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance), }) if err == red.Nil { return false, nil } else if err != nil { logx.Errorf("Error on acquiring lock for %s, %s", rl.key, err.Error()) return false, err } else if resp == nil { return false, nil } reply, ok := resp.(string) if ok && reply == "OK" { return true, nil } logx.Errorf("Unknown reply when acquiring lock for %s: %v", rl.key, resp) return false, nil } // Release releases the lock. func (rl *RedisLock) Release() (bool, error) { resp, err := rl.store.Eval(delCommand, []string{rl.key}, []string{rl.id}) if err != nil { return false, err } reply, ok := resp.(int64) if !ok { return false, nil } return reply == 1, nil } // SetExpire sets the expiration. func (rl *RedisLock) SetExpire(seconds int) { atomic.StoreUint32(&rl.seconds, uint32(seconds)) } ``` 最后修改:2022 年 08 月 12 日 © 允许规范转载 打赏 赞赏作者 微信 赞 2 如果觉得我的文章对你有用,请随意赞赏
1 条评论
正儿八经分布式锁还得看dtm 简单易上手 此处就是展示一下更简单便捷的小锁