Locker 组件

Locker 组件实现了分布式锁。

locker 组件采用 driver 的机制,目前支持的 driver 有 redis, etcd。

每个 driver 都需要实现下面 ILocker 接口的两个方法:

// yago-coms/locker/locker.go
type ILocker interface {
    Lock(key string, opts ...SessionOption) error
    Unlock()
}

下面介绍具体的使用方式。

1. 配置 locker 组件

1.1. 使用 redis 做 locker 驱动的组件

[redis]
addr = "127.0.0.1:6379"
auth = "yourpass"
db = 0
max_idle = 5
idle_timeout = 30

[locker]
driver = "redis"
driver_instance_id = "redis"

locker 配置中只需要配置 driver 名称和 driver 实例 ID, 上例中 driver_instance_id 为 redis 表示使用配置文件中 section 为 redis 的组件实例作为 locker 的 driver 驱动对象

1.2. 使用 etcd 做 locker 驱动的组件

[etcd]
endpoints = ["127.0.0.1:2379"]

[locker]
driver = "etcd"
driver_instance_id = "etcd"

上例中 driver_instance_id 为 etcd 表示使用配置文件中 section 为 etcd 的组件实例作为 locker 的 driver 驱动对象

2. 使用 Locker 组件

2.1. 构建永久锁

key := "locker_name"
// 锁的默认租期是 60s,如果拿锁进程异常,会续约失败,释放锁

// 创建锁对象
lo := locker.New()

// Lock() will block until get the locker
// Get locker
err := lo.Lock(key)
if err != nil {
    // err handler
}
// Release locker
defer lo.Unlock()
// your code here

2.2. 构建一个带有效期的锁

key := "locker_name"
// 锁的默认租期是 60s,也可以自行指定
timeout := 10

// 创建锁对象
lo := locker.New()

// Lock() will block until get the locker
// 带有效期的锁,需要关闭 keepAlive 自动续约参数
err := lo.Lock(key,lock.WithTTL(timeout),lock.WithDisableKeepAlive())
if err != nil {
    // err handler
}
// Release locker
defer lo.Unlock()
// your code here

2.3. 构建一个设置等待时间的锁

key := "locker_name"

// 创建锁对象
lo := locker.New()

// Lock() will block until get the locker
// 客户端会等待 3s,如果 3s 还是没能拿到锁则自动退出争抢
err := lo.Lock(key,lock.WithWaitTime(time.Second*3))
if err != nil {
    // 用来判断是否为超时错误,超时错误算是预期内错误,业务可能需要特殊处理
    if errors.Is(err, context.DeadlineExceeded) {
        return
    }
    // err handler
}
// Release locker
defer lo.Unlock()
// your code here

说明一下,locker 组件默认只注册了 redis,etcd-locker 需要业务方在使用时加载注册一下

import _ "github.com/hulklab/yago-coms/locker/etcd"

2.4. 在 task 中使用永久锁

为了方便多节点部署的情况下,始终保障 task 任务只在一个节点运行,我们在 basetask 里面封装了一个 RunLoopWithLock 的方法。

// 直接使用
func (t *YourTask) DoAction() {
    t.RunLoopWithLock(func(){
        // put your code here
    })

}

// 自定义 lock-key
func (t *YourTask) DoAction() {
    t.RunLoopWithLock(func(){
        // put your code here
    },basetask.WithLockKey("mylock"))

}

// 默认使用配置文件中的 locker 配置段,如果需要自定义
func (t *YourTask) DoAction() {
    t.RunLoopWithLock(func(){
        // put your code here
    },basetask.WithLockConf("lock_conf_name"))

}

// 默认循环体之间是没有时间间隔的,如果需要添加
func (t *YourTask) DoAction() {
    t.RunLoopWithLock(func(){
        // put your code here
    },basetask.WithInterval(1*time.Second))

}

results matching ""

    No results matching ""