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: // 执行业务逻辑 } // ...
Output:
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: // 执行业务逻辑 }
Output:
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.