Skip to main content

分布式锁

支持

  • go_cache: 基于内存的本地缓存, 单体服务时使用
  • redis: redis分布式锁, 分布式时使用

配置组件

[lock]
# 默认使用 go_cache
# 如果想使用redis分布式锁, 需要配置redis, 具体见redis相关配置
provider = "go_cache"

基本使用

package main

import (
"context"
"time"

"github.com/infraboard/mcube/v2/ioc/config/lock"
)

func main() {
// 创建一个key为test, 超时时间为10秒的锁
locker := lock.L().New("test", 10*time.Second)

ctx := context.Background()

// 获取锁
if err := locker.Lock(ctx); err != nil {
panic(err)
}

// 释放锁
defer locker.UnLock(ctx)
}

Lock

func TestRedisLock(t *testing.T) {
os.Setenv("LOCK_PROVIDER", lock.PROVIDER_REDIS)
ioc.DevelopmentSetup()
g := &sync.WaitGroup{}
for i := range 9 {
go LockTest(i, g)
}
g.Wait()
time.Sleep(10 * time.Second)
}

func LockTest(number int, g *sync.WaitGroup) {
fmt.Println(number, "start")
g.Add(1)
defer g.Done()
m := lock.L().New("test", 1*time.Second)
if err := m.Lock(ctx); err != nil {
fmt.Println(err)
}
fmt.Println(number, "down")
}
=== RUN   TestRedisLock
8 start
3 start
0 start
5 start
4 start
1 start
6 start
7 start
2 start
6 down
5 down
4 down
3 down
1 down
7 down
0 down
8 down
2 down
--- PASS: TestRedisLock (10.00s)

Try Lock

func TestRedisTryLock(t *testing.T) {
os.Setenv("LOCK_PROVIDER", lock.PROVIDER_REDIS)
ioc.DevelopmentSetup()
g := &sync.WaitGroup{}
for i := range 9 {
go TryLockTest(i, g)
}
g.Wait()
time.Sleep(10 * time.Second)
}

func TryLockTest(number int, g *sync.WaitGroup) {
fmt.Println(number, "start")
g.Add(1)
defer g.Done()
m := lock.L().New("test", 1*time.Second)
if err := m.TryLock(ctx); err != nil {
fmt.Println(number, err)
return
}
fmt.Println(number, "obtained lock")
}
=== RUN   TestRedisTryLock
8 start
3 start
1 start
4 start
0 start
7 start
2 start
5 start
6 start
8 obtained lock
3 lock: not obtained
6 lock: not obtained
2 lock: not obtained
4 lock: not obtained
7 lock: not obtained
0 lock: not obtained
1 lock: not obtained
5 lock: not obtained