123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- package lock
- import (
- "context"
- "eta/eta_api/utils"
- "fmt"
- "github.com/go-redis/redis/v8"
- "time"
- )
- const (
- lockName = "lock:"
- )
- var (
- ctx = context.Background()
- )
- func AcquireLock(key string, expiration int, Holder string) bool {
- script := redis.NewScript(`local key = KEYS[1]
- local clientId = ARGV[1]
- local expiration = tonumber(ARGV[2])
- if redis.call("EXISTS", key) == 0 then
- redis.call("SET", key, clientId, "EX", expiration)
- return 1
- else
- return 0
- end`)
- lockey := fmt.Sprintf("%s%s", lockName, key)
- result, err := script.Run(ctx, utils.Rc.RedisClient(), []string{lockey}, Holder, expiration).Int()
- if err != nil {
- fmt.Printf("加锁失败:err: %v", err)
- return false
- }
- if result == 1 {
- return true
- }
- return false
- }
- func TryLock(key string, expiration int, Holder string, timeout time.Duration) error {
- redisCtx, cancel := context.WithTimeout(context.Background(), timeout)
- defer cancel()
- for {
- select {
- case <-redisCtx.Done():
- return fmt.Errorf("等待超时")
- default:
- if AcquireLock(key, expiration, Holder) {
- // 启动异步续约
- go renewLock(key, Holder, expiration)
- return nil
- }
- // 等待重试
- time.Sleep(50 * time.Millisecond)
- }
- }
- }
- func renewLock(key, holder string, expiration int) {
- for {
- time.Sleep(5 * time.Second)
- script := redis.NewScript(`
- local key = KEYS[1]
- local clientId = ARGV[1]
- local expiration = tonumber(ARGV[2])
- if redis.call("get", KEYS[1]) == ARGV[1] then
- redis.call("SET", key, clientId, "EX", expiration)
- return 1
- else
- return 0
- end
- `)
- lockey := fmt.Sprintf("%s%s", lockName, key)
- result, err := script.Run(context.Background(), utils.Rc.RedisClient(), []string{lockey}, holder, expiration).Result()
- if err != nil {
- fmt.Println("锁续期失败:", err)
- return
- }
- if result.(int64) == 0 {
- fmt.Println("持有者变更,停止监听")
- return
- }
- fmt.Printf("锁续期成功")
- }
- }
- func ReleaseLock(key string, holder string) bool {
- script := redis.NewScript(`
- if redis.call("get", KEYS[1]) == ARGV[1] then
- return redis.call("del", KEYS[1])
- else
- return 0
- end
- `)
- lockey := fmt.Sprintf("%s%s", lockName, key)
- result, err := script.Run(ctx, utils.Rc.RedisClient(), []string{lockey}, holder).Int()
- if err != nil {
- fmt.Printf("解锁失败:err: %v", err)
- return false
- }
- if result == 1 {
- return true
- }
- return false
- }
|