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-05-10 15:32