go-redis
https://redis.uptrace.dev/zh/guide/
使用golang语言写一段代码,实现操作redis,实现分布式锁,释放锁时要保证执行操作的客户端就是加锁的客户端
package main
import (
"fmt"
"github.com/go-redis/redis"
"strconv"
"time"
)
type RedisLock struct {
client *redis.Client
key string
value string
expiration time.Duration
}
func NewRedisLock(client *redis.Client, key string, value string, expiration time.Duration) *RedisLock {
return &RedisLock{
client: client,
key: key,
value: value,
expiration: expiration,
}
}
func (r *RedisLock) Acquire() bool {
result, err := r.client.SetNX(r.key, r.value, r.expiration).Result()
if err != nil {
fmt.Println("Error acquiring lock:", err)
return false
}
return result
}
func (r *RedisLock) Release() bool {
script := `
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end`
result, err := r.client.Eval(script, []string{r.key}, r.value).Int64()
if err != nil {
fmt.Println("Error releasing lock:", err)
return false
}
return result == 1
}
func main() {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
lock := NewRedisLock(client, "my-lock", strconv.Itoa(time.Now().Nanosecond()), time.Second*10)
acquired := lock.Acquire()
if !acquired {
fmt.Println("Could not acquire lock")
return
}
defer lock.Release()
fmt.Println("Lock acquired")
// Do some work here
time.Sleep(time.Second * 5)
fmt.Println("Work done")
}
这段代码定义了一个名为RedisLock的类型,其中包含client、key、value和expiration字段。client表示Redis客户端连接,key表示要获取的锁的键名,value表示要获取锁的值(通常是一个随机的字符串或数字),expiration则表示锁的过期时间。
NewRedisLock函数用于创建一个新的RedisLock实例。它需要传入一个Redis客户端连接、要获取的锁的键名、要获取的锁的值和锁的过期时间。
Acquire方法用于获取锁。它使用Redis的SETNX命令来设置键值对,如果该键不存在则设置成功,否则设置失败。如果获取成功,返回true,否则返回false。
Release方法用于释放锁。它使用Lua脚本来判断当前锁是否由该客户端持有,如果是,则删除该键,并返回true;否则返回false。
在主函数中,我们首先创建一个Redis客户端实例,然后创建一个RedisLock实例,并尝试获取锁。如果获取不到锁,则直接退出程序。如果获取到锁,则执行一些工作,最后调用Release方法来释放锁。
作者:海马 创建时间:2023-09-22 08:22
最后编辑:海马 更新时间:2024-12-22 19:32
最后编辑:海马 更新时间:2024-12-22 19:32