Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:update ttl to ms #35

Merged
merged 3 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lock_redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var (

// Lock 加锁
func (lock *RedisLock) Lock() error {
result, err := lock.redis.Eval(lock.Context, reentrantLockScript, []string{lock.key}, lock.token, lock.lockTimeout.Seconds()).Result()
result, err := lock.redis.Eval(lock.Context, reentrantLockScript, []string{lock.key}, lock.token, lock.lockTimeout.Milliseconds()).Result()

if err != nil {
return ErrException
Expand Down Expand Up @@ -79,7 +79,7 @@ func (lock *RedisLock) SpinLock(timeout time.Duration) error {

// Renew 锁手动续期
func (lock *RedisLock) Renew() error {
res, err := lock.redis.Eval(lock.Context, reentrantRenewScript, []string{lock.key}, lock.token, lock.lockTimeout.Seconds()).Result()
res, err := lock.redis.Eval(lock.Context, reentrantRenewScript, []string{lock.key}, lock.token, lock.lockTimeout.Milliseconds()).Result()

if err != nil {
return ErrException
Expand Down
32 changes: 16 additions & 16 deletions lock_redis_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestLockSuccess(t *testing.T) {
lock := New(ctx, db, key, WithToken(token))

// 设置模拟锁获取成功的行为
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

err := lock.Lock()
if err != nil {
Expand All @@ -53,7 +53,7 @@ func TestLockFail(t *testing.T) {

ctx := context.Background()
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestUnlockFail(t *testing.T) {
lock := New(ctx, db, key, WithToken(token))

// 加锁逻辑
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

err := lock.Lock()
if err != nil {
Expand Down Expand Up @@ -142,8 +142,8 @@ func TestSpinLockSuccess(t *testing.T) {
token2 := "some_token2"
spinTimeout := time.Duration(5) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -192,8 +192,8 @@ func TestSpinLockTimeout(t *testing.T) {
spinTimeout := time.Duration(5) * time.Second
spinTimeout2 := time.Duration(3) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Seconds()).SetVal("nil")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token2, lockTime.Milliseconds()).SetVal("nil")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -238,8 +238,8 @@ func TestRenewSuccess(t *testing.T) {
key := "test_key_TestRenewSuccess"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")

// 设置模拟锁续期成功的行为
mock.ExpectExpire(key, lockTime).SetVal(true)
Expand Down Expand Up @@ -283,7 +283,7 @@ func TestRenewFail(t *testing.T) {
key := "test_key_TestRenewFail"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// 设置模拟锁续期成功的行为
mock.ExpectExpire(key, lockTime).SetVal(false)

Expand Down Expand Up @@ -328,7 +328,7 @@ func TestWithTimeout(t *testing.T) {
token := "some_token"
timeout := time.Duration(10) * time.Second

mock.ExpectEval(reentrantLockScript, []string{key}, token, timeout.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, timeout.Milliseconds()).SetVal("OK")

var wg sync.WaitGroup
wg.Add(2)
Expand Down Expand Up @@ -375,8 +375,8 @@ func TestAutoRenew(t *testing.T) {
key := "test_key_TestAutoRenew"
token := "some_token"

mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
mock.ExpectEval(reentrantLockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
mock.ExpectExpire(key, lockTime).SetVal(true)

lock := New(ctx, db, key, WithToken(token), WithAutoRenew())
Expand All @@ -400,7 +400,7 @@ func TestAutoRenew(t *testing.T) {
// token := "some_token"
//
// // 设置模拟锁获取成功的行为
// mock.ExpectEval(lockScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
// mock.ExpectEval(lockScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// // 设置模拟锁续期成功的行为
// mock.ExpectExpire(key, lockTime).SetVal(true)
//
Expand All @@ -414,7 +414,7 @@ func TestAutoRenew(t *testing.T) {
// go func() {
// defer wg.Done()
// // 模拟锁续期成功
// mock.ExpectEval(renewScript, []string{key}, token, lockTime.Seconds()).SetVal("OK")
// mock.ExpectEval(renewScript, []string{key}, token, lockTime.Milliseconds()).SetVal("OK")
// // 等待一段时间,模拟自动续期的过程
// time.Sleep(time.Second * 3)
// // 取消上下文,模拟上下文的取消
Expand Down Expand Up @@ -515,7 +515,7 @@ func TestSevLockSuccess(t *testing.T) {
lock := New(ctx, redisClient, key)

times, _ := redisClient.TTL(ctx, key).Result()
log.Println("线程二:ttl 时间:", times.Seconds())
log.Println("线程二:ttl 时间:", times.Milliseconds())

err := lock.Lock()
if err == nil {
Expand Down
46 changes: 23 additions & 23 deletions lock_redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -34,7 +34,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁内部异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetErr(ErrException)
return db
},
Expand All @@ -46,7 +46,7 @@ func TestRedisLock_Lock(t *testing.T) {
name: "加锁失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("nil")
return db
},
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetVal("OK")
Expand All @@ -99,7 +99,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁内部异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetErr(ErrException)
Expand All @@ -119,7 +119,7 @@ func TestRedisLock_UnLock(t *testing.T) {
name: "解锁失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantUnLockScript, []string{"key"}, "token").
SetVal("nil")
Expand Down Expand Up @@ -166,7 +166,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-加锁成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -185,7 +185,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-加锁超时",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -210,7 +210,7 @@ func TestRedisLock_SpinLock(t *testing.T) {
name: "自旋锁-Ctx取消",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand Down Expand Up @@ -267,9 +267,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -287,9 +287,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期异常",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetErr(ErrException)
return db
},
Expand All @@ -307,9 +307,9 @@ func TestRedisLock_LockRenew(t *testing.T) {
name: "锁手动续期失败",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("nil")
return db
},
Expand Down Expand Up @@ -362,9 +362,9 @@ func TestRedisLock_LockAutoRenew(t *testing.T) {
name: "锁自动续期成功",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand All @@ -382,9 +382,9 @@ func TestRedisLock_LockAutoRenew(t *testing.T) {
name: "锁自动续期-Ctx取消",
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Seconds()).
mock.ExpectEval(reentrantRenewScript, []string{"key"}, "token", lockTime.Milliseconds()).
SetVal("OK")
return db
},
Expand Down Expand Up @@ -440,10 +440,10 @@ func TestRedisLock_LockTimeout(t *testing.T) {
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
// 第一次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Milliseconds()).
SetVal("OK")
// 第二次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 2).Milliseconds()).
SetVal("OK")

// 第一次解锁
Expand Down Expand Up @@ -476,10 +476,10 @@ func TestRedisLock_LockTimeout(t *testing.T) {
mock: func(t *testing.T) *redis.Client {
db, mock := redismock.NewClientMock()
// 第一次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Milliseconds()).
SetVal("OK")
// 第二次加锁
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Seconds()).
mock.ExpectEval(reentrantLockScript, []string{"key"}, "token", (time.Second * 5).Milliseconds()).
SetVal("nil")

// 第一次解锁
Expand Down
8 changes: 4 additions & 4 deletions lua/reentrantLock.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ local reentrant_count = tonumber(redis.call('GET', reentrant_key) or '0')
-- 可重入锁计数器
if reentrant_count > 0 then
redis.call('INCR', reentrant_key)
redis.call('EXPIRE', lock_key, lock_ttl)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', lock_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

-- 创建锁
if redis.call('SET', lock_key, lock_value, 'NX', 'EX', lock_ttl) then
if redis.call('SET', lock_key, lock_value, 'NX', 'PX', lock_ttl) then
redis.call('SET', reentrant_key, 1)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

Expand Down
4 changes: 2 additions & 2 deletions lua/reentrantRenew.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ local reentrant_count = tonumber(redis.call('GET', reentrant_key) or '0')
-- 重入锁的场景(reentrant_count > 0)
-- 普通锁的场景(redis.call('GET', lock_key) == lock_value)
if reentrant_count > 0 or redis.call('GET', lock_key) == lock_value then
redis.call('EXPIRE', lock_key, lock_ttl)
redis.call('EXPIRE', reentrant_key, lock_ttl)
redis.call('PEXPIRE', lock_key, lock_ttl)
redis.call('PEXPIRE', reentrant_key, lock_ttl)
return "OK"
end

Expand Down
Loading