Skip to content

Commit b33a6b6

Browse files
authored
Fix/redis reacquire (#2)
* fix: redis locker reAcquire * fix: locker * fix: redis del lua script
1 parent 34f5362 commit b33a6b6

File tree

3 files changed

+79
-50
lines changed

3 files changed

+79
-50
lines changed

core/stores/redis/lockscript.lua

-6
This file was deleted.

core/stores/redis/redislock.go

+15-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
_ "embed"
66
"errors"
77
"math/rand"
8-
"strconv"
98
"sync/atomic"
109
"time"
1110

@@ -15,16 +14,10 @@ import (
1514
)
1615

1716
const (
18-
randomLen = 16
19-
tolerance = 500 // milliseconds
20-
millisPerSecond = 1000
17+
randomLen = 16
2118
)
2219

2320
var (
24-
//go:embed lockscript.lua
25-
lockLuaScript string
26-
lockScript = NewScript(lockLuaScript)
27-
2821
//go:embed delscript.lua
2922
delLuaScript string
3023
delScript = NewScript(delLuaScript)
@@ -58,26 +51,27 @@ func (rl *RedisLock) Acquire() (bool, error) {
5851

5952
// AcquireCtx acquires the lock with the given ctx.
6053
func (rl *RedisLock) AcquireCtx(ctx context.Context) (bool, error) {
61-
seconds := atomic.LoadUint32(&rl.seconds)
62-
resp, err := rl.store.ScriptRunCtx(ctx, lockScript, []string{rl.key}, []string{
63-
rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance),
64-
})
54+
55+
var (
56+
seconds = atomic.LoadUint32(&rl.seconds)
57+
res bool
58+
err error
59+
)
60+
61+
if seconds == 0 {
62+
res, err = rl.store.SetnxCtx(ctx, rl.key, rl.id)
63+
} else {
64+
res, err = rl.store.SetnxExCtx(ctx, rl.key, rl.id, int(seconds))
65+
}
66+
6567
if errors.Is(err, red.Nil) {
6668
return false, nil
6769
} else if err != nil {
6870
logx.Errorf("Error on acquiring lock for %s, %s", rl.key, err.Error())
6971
return false, err
70-
} else if resp == nil {
71-
return false, nil
72-
}
73-
74-
reply, ok := resp.(string)
75-
if ok && reply == "OK" {
76-
return true, nil
7772
}
7873

79-
logx.Errorf("Unknown reply when acquiring lock for %s: %v", rl.key, resp)
80-
return false, nil
74+
return res, nil
8175
}
8276

8377
// Release releases the lock.

core/stores/redis/redislock_test.go

+64-23
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,45 @@ package redis
33
import (
44
"context"
55
"testing"
6+
"time"
67

8+
"github.com/alicebob/miniredis/v2"
79
"github.com/stretchr/testify/assert"
810

911
"github.com/zeromicro/go-zero/core/stringx"
1012
)
1113

14+
func TestRedisLock_SameAcquire(t *testing.T) {
15+
16+
var (
17+
s = miniredis.RunT(t)
18+
seconds = 5
19+
)
20+
client := MustNewRedis(
21+
RedisConf{
22+
Host: s.Addr(),
23+
Type: NodeType,
24+
},
25+
)
26+
27+
key := stringx.Rand()
28+
firstLock := NewRedisLock(client, key)
29+
firstLock.SetExpire(seconds)
30+
firstAcquire, err := firstLock.Acquire()
31+
assert.Nil(t, err)
32+
assert.True(t, firstAcquire)
33+
34+
secondAcquire, err := firstLock.Acquire()
35+
assert.Nil(t, err)
36+
assert.False(t, secondAcquire)
37+
38+
s.FastForward(time.Second * time.Duration(seconds+1))
39+
40+
thirdAcquire, err := firstLock.Acquire()
41+
assert.Nil(t, err)
42+
assert.True(t, thirdAcquire)
43+
}
44+
1245
func TestRedisLock(t *testing.T) {
1346
testFn := func(ctx context.Context) func(client *Redis) {
1447
return func(client *Redis) {
@@ -35,31 +68,39 @@ func TestRedisLock(t *testing.T) {
3568
}
3669
}
3770

38-
t.Run("normal", func(t *testing.T) {
39-
runOnRedis(t, testFn(nil))
40-
})
71+
t.Run(
72+
"normal", func(t *testing.T) {
73+
runOnRedis(t, testFn(nil))
74+
},
75+
)
4176

42-
t.Run("withContext", func(t *testing.T) {
43-
runOnRedis(t, testFn(context.Background()))
44-
})
77+
t.Run(
78+
"withContext", func(t *testing.T) {
79+
runOnRedis(t, testFn(context.Background()))
80+
},
81+
)
4582
}
4683

4784
func TestRedisLock_Expired(t *testing.T) {
48-
runOnRedis(t, func(client *Redis) {
49-
key := stringx.Rand()
50-
redisLock := NewRedisLock(client, key)
51-
ctx, cancel := context.WithCancel(context.Background())
52-
cancel()
53-
_, err := redisLock.AcquireCtx(ctx)
54-
assert.NotNil(t, err)
55-
})
56-
57-
runOnRedis(t, func(client *Redis) {
58-
key := stringx.Rand()
59-
redisLock := NewRedisLock(client, key)
60-
ctx, cancel := context.WithCancel(context.Background())
61-
cancel()
62-
_, err := redisLock.ReleaseCtx(ctx)
63-
assert.NotNil(t, err)
64-
})
85+
runOnRedis(
86+
t, func(client *Redis) {
87+
key := stringx.Rand()
88+
redisLock := NewRedisLock(client, key)
89+
ctx, cancel := context.WithCancel(context.Background())
90+
cancel()
91+
_, err := redisLock.AcquireCtx(ctx)
92+
assert.NotNil(t, err)
93+
},
94+
)
95+
96+
runOnRedis(
97+
t, func(client *Redis) {
98+
key := stringx.Rand()
99+
redisLock := NewRedisLock(client, key)
100+
ctx, cancel := context.WithCancel(context.Background())
101+
cancel()
102+
_, err := redisLock.ReleaseCtx(ctx)
103+
assert.NotNil(t, err)
104+
},
105+
)
65106
}

0 commit comments

Comments
 (0)