增加获取当前锁状态方法
This commit is contained in:
parent
ab0612d9b6
commit
5afb8b1aa7
@ -5,6 +5,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,8 +24,8 @@ type RedisLock struct {
|
|||||||
kvt redisCommInfo
|
kvt redisCommInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateRedisLock(c *redis.Client, ctx context.Context, k, v string, ttl int) *RedisLock {
|
func CreateRedisLock(c *redis.Client, ctx context.Context, k string, ttl int) *RedisLock {
|
||||||
return &RedisLock{c, ctx, make(chan struct{}, 1), make(chan struct{}), redisCommInfo{k, v, ttl}}
|
return &RedisLock{c, ctx, make(chan struct{}, 1), make(chan struct{}), redisCommInfo{k, uuid.New().String(), ttl}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisLock) Lock() {
|
func (r *RedisLock) Lock() {
|
||||||
@ -82,6 +84,10 @@ func (r *RedisLock) Unlock() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *RedisLock) IsHeld() bool {
|
||||||
|
return r.client.HExists(r.ctx, r.kvt.key, r.kvt.value).Val()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RedisLock) autoReNewExpire() {
|
func (r *RedisLock) autoReNewExpire() {
|
||||||
defer func() {
|
defer func() {
|
||||||
<-r.lockKeepAliveCh
|
<-r.lockKeepAliveCh
|
||||||
|
@ -3,6 +3,7 @@ package worker
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"goRedisDLM/engine"
|
"goRedisDLM/engine"
|
||||||
"goRedisDLM/redisLock"
|
"goRedisDLM/redisLock"
|
||||||
"log"
|
"log"
|
||||||
@ -11,7 +12,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Inventory struct {
|
type Inventory struct {
|
||||||
@ -19,13 +19,9 @@ type Inventory struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Inventory) Work(request engine.Request, response *engine.Response) error {
|
func (i *Inventory) Work(request engine.Request, response *engine.Response) error {
|
||||||
value := uuid.New()
|
|
||||||
|
|
||||||
//log.Printf("uuid: %s, lock key: %s\n", value.String(), request.Dlock)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
lock := redisLock.CreateRedisLock(i.Client, ctx, request.Dlock, value.String(), 100)
|
lock := redisLock.CreateRedisLock(i.Client, ctx, request.Dlock, 100)
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
|
|
||||||
time.Sleep(time.Duration(rand.Int31n(100)) * time.Millisecond)
|
time.Sleep(time.Duration(rand.Int31n(100)) * time.Millisecond)
|
||||||
@ -41,16 +37,22 @@ func (i *Inventory) Work(request engine.Request, response *engine.Response) erro
|
|||||||
if inventory >= 0 {
|
if inventory >= 0 {
|
||||||
//这里应该使用lua脚本,再检测一下当前是否获取到锁,获取到之后再进行扣减。类似双检加锁的思想,因为此时可能会续期失败。
|
//这里应该使用lua脚本,再检测一下当前是否获取到锁,获取到之后再进行扣减。类似双检加锁的思想,因为此时可能会续期失败。
|
||||||
//i.Client.Set(ctx, "inventory", fmt.Sprintf("%d", inventory), redis.KeepTTL)
|
//i.Client.Set(ctx, "inventory", fmt.Sprintf("%d", inventory), redis.KeepTTL)
|
||||||
script := `if redis.call('hexists',KEYS[1],ARGV[1]) == 1 then return redis.call('set',KEYS[2],ARGV[2])
|
//script := `if redis.call('hexists',KEYS[1],ARGV[1]) == 1 then return redis.call('set',KEYS[2],ARGV[2])
|
||||||
else return 0 end`
|
// else return 0 end`
|
||||||
|
//
|
||||||
val := i.Client.Eval(ctx, script, []string{request.Dlock, "inventory"}, value.String(), inventory).Val()
|
//val := i.Client.Eval(ctx, script, []string{request.Dlock, "inventory"}, value.String(), inventory).Val()
|
||||||
if res, ok := val.(string); ok && res == "OK" {
|
|
||||||
|
|
||||||
|
if lock.IsHeld() {
|
||||||
|
setString := fmt.Sprintf("%d", inventory)
|
||||||
|
if i.Client.Set(ctx, "inventory", setString, redis.KeepTTL).Val() != "OK" {
|
||||||
|
log.Println("error set inventory")
|
||||||
|
err = errors.New("inventory err")
|
||||||
|
goto Error
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
//任务执行失败需要通知调用者,让调用者自己决策是否需要重新调度还是放弃,这样worker和主线程实现了解偶
|
//任务执行失败需要通知调用者,让调用者自己决策是否需要重新调度还是放弃,这样worker和主线程实现了解偶
|
||||||
log.Println("error set inventory")
|
log.Println("error lock is not held")
|
||||||
err = errors.New("inventory err")
|
err = errors.New("error lock is not held")
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user