package lock import ( "context" "errors" "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 { script := redis.NewScript(` local session = ARGV[1] local current = redis.call("hget", KEYS[1], session) if current then local count = tonumber(current) if count > 0 then redis.call("hincrby", KEYS[1], session, 1) return 1 else return 0 end else redis.call("hset", KEYS[1], session, 1) redis.call("expire", KEYS[1], 10) return 1 end `) start := time.Now() for { result, err := script.Run(context.Background(), utils.Rc.RedisClient(), []string{key}, Holder).Result() if err != nil { return err } if result.(int64) == 1 { //go renewLock() return nil } if time.Since(start) >= timeout { return errors.New("获取锁超时") } time.Sleep(200 * time.Millisecond) } } // //func renewLock() { // for { // time.Sleep(5 * time.Second) // // script := redis.NewScript(1, ` // local session = ARGV[1] // local current = redis.call("hget", KEYS[1], session) // if current then // local count = tonumber(current) // if count > 0 then // redis.call("expire", KEYS[1], 10) // return 1 // else // return 0 // end // else // return 0 // end // `) // // result, err := script.Run(r.ctx, r.client, []string{r.key}, r.session).Result() // if err != nil { // fmt.Println("Failed to renew lock:", err) // return // } // // if result.(int64) == 0 { // fmt.Println("Lock not held by current client, stopping renewal") // return // } // } //} 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 }