123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- 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
- }
|