|
@@ -5,6 +5,7 @@ import (
|
|
|
"eta/eta_api/utils"
|
|
|
"fmt"
|
|
|
"github.com/go-redis/redis/v8"
|
|
|
+ "time"
|
|
|
)
|
|
|
|
|
|
const (
|
|
@@ -37,15 +38,53 @@ func AcquireLock(key string, expiration int, Holder string) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-func Lock() error {
|
|
|
- if !AcquireLock("test", 10, "test") {
|
|
|
- return fmt.Errorf("加锁失败")
|
|
|
+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)
|
|
|
+ }
|
|
|
}
|
|
|
- return nil
|
|
|
}
|
|
|
+
|
|
|
+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
|