go redis锁
redis经常用作分布式锁,这里记录一个简单的锁代码如下:
package main import ( "crypto/rand" "encoding/base64" "fmt" "github.com/go-redis/redis" "io" "sync" "time" ) func main() { addr := "192.168.100.30:6379" rdb := redis.NewUniversalClient(&redis.UniversalOptions{ Addrs: []string {addr}, Password: "", // no password set DB: 0, // use default DB }) defer func() { _ = rdb.Close() }() key := "gavin-lock" uid, err := Lock(rdb, key, time.Second*1, time.Second*2) if err == nil { _ = Unlock(rdb, key, uid) } } var randMutex sync.Mutex var randBytes []byte // 获取随机字串 func randToken() string { randMutex.Lock() defer randMutex.Unlock() if len(randBytes) == 0 { randBytes = make([]byte, 16) } if _, err := io.ReadFull(rand.Reader, randBytes); err != nil { return "" } return base64.RawURLEncoding.EncodeToString(randBytes) } func Lock(redisClient redis.UniversalClient, lockKey string, acquireTimeOut, lockTimeOut time.Duration) (token string, err error) { token = randToken() var acquireDuration = acquireTimeOut for acquireDuration > 0 { ok, err := redisClient.SetNX(lockKey, token, lockTimeOut).Result() if err != nil { fmt.Printf("redis锁 - 加锁失败 key: %s, token: %s, ttl: %v, err: %v\r\n", lockKey, token, lockTimeOut, err) return "", err } if ok { fmt.Printf("redis锁 - 加锁成功 key: %s, token: %s, ttl: %v\r\n", lockKey, token, lockTimeOut) return token, nil } time.Sleep(time.Millisecond * 100) // next: sleep 500ms acquireDuration -= time.Millisecond * 100 } fmt.Printf("redis锁 - 加锁超时 key: %s, token: %s, ttl: %v\r\n", lockKey, token, acquireTimeOut) return "", fmt.Errorf("获取redis锁超时: %v\r\n", acquireTimeOut) } func Unlock(redisClient redis.UniversalClient, lockKey, token string) error { const script = `if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end` ret, err := redisClient.Eval(script, []string{lockKey}, token).Result() if err != nil { fmt.Printf("redis锁 - 解锁失败 key: %s, token: %s, err: %v\r\n", lockKey, token, err) return err } if v, ok := ret.(int64); ok && v == 1 { fmt.Printf("redis锁 - 解锁成功 key: %s, token: %s\r\n", lockKey, token) return nil } fmt.Printf("redis锁 - 解锁失败 key: %s, token: %s, key已经过期\r\n", lockKey, token) return nil }
windows技术爱好者
标签:
GO
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2017-11-29 C# CancellationTokenSource和CancellationToken的实现
2016-11-29 js for in对象key排序