Documentation
¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func (*Client) Lock ¶
func (c *Client) Lock(ctx context.Context, key, val string, expiration, timeout time.Duration, retry RetryStrategy) (*Lock, error)
Lock 申请分布式锁,内部会重试抢锁
type FixedIntervalStrategy ¶
type FixedIntervalStrategy struct {
// contains filtered or unexported fields
}
FixedIntervalStrategy 固定时间间隔策略
func NewFixedIntervalStrategy ¶
func NewFixedIntervalStrategy(interval time.Duration, maxRetry int) *FixedIntervalStrategy
type Lock ¶
type Lock struct {
// contains filtered or unexported fields
}
func (*Lock) AutoRefresh ¶
func (l *Lock) AutoRefresh(ctx context.Context, interval, expiration, timeout time.Duration, maxRetry ...int) error
AutoRefresh 自动续约,简化业务手动续约处理的难度 ctx context.Context 上下文 interval time.Duration 轮询的时间间隔 expiration time.Duration 分布式锁的单次续约时间
Example ¶
l := &Lock{
key: "key1",
id: "123456",
expiration: time.Second * 10,
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
errCh := make(chan error)
go func() {
err := l.AutoRefresh(ctx, time.Second, time.Second*10, 10)
if err != nil {
_ = l.UnLock(ctx)
errCh <- err
return
}
}()
// 第一段
select {
case <-errCh:
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
// 第二段
select {
case <-errCh:
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
// 第三段
select {
case <-errCh:
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
// ...
func (*Lock) Refresh ¶
Refresh 续约分布式锁 @ctx context.Context 上下文 续约多个命令需要考虑原子性,使用lua脚本实现 过期时间沿用创建时设置的
Example ¶
l := &Lock{
key: "key1",
id: "123456",
expiration: time.Second * 10,
}
errCh := make(chan error)
closeCh := make(chan struct{})
go func() {
maxCounter := 5
counter := 0
retryCh := make(chan struct{}, 1)
defer close(retryCh)
// 手动定期续约
ticker := time.NewTicker(time.Second * 8)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// 开始续约
if counter >= maxCounter {
errCh <- ErrMaxRetryFailed
return
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
err := l.Refresh(ctx)
cancel()
if errors.Is(err, context.DeadlineExceeded) {
retryCh <- struct{}{}
continue
}
if err != nil {
errCh <- err
return
}
// 续约成功,重置计数器
counter = 0
case <-retryCh:
if counter >= maxCounter {
errCh <- ErrMaxRetryFailed
return
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
err := l.Refresh(ctx)
cancel()
if errors.Is(err, context.DeadlineExceeded) {
retryCh <- struct{}{}
continue
}
if err != nil {
errCh <- err
return
}
// 续约成功,重置计数器
counter = 0
case <-closeCh:
// 释放锁
return
}
}
}()
// 第一段
select {
case <-errCh:
close(closeCh)
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
// 第二段
select {
case <-errCh:
close(closeCh)
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
// 第三段
select {
case <-errCh:
close(closeCh)
// 自动续约失败,记录日志
default:
// 执行业务逻辑
}
type NonFixedIntervalStrategy ¶
type NonFixedIntervalStrategy struct {
// contains filtered or unexported fields
}
func NewNonFixedIntervalStrategy ¶
func NewNonFixedIntervalStrategy(interval time.Duration, maxRetry int) *NonFixedIntervalStrategy
type RetryStrategy ¶
Click to show internal directories.
Click to hide internal directories.