distributed_lock

package module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 13, 2024 License: Apache-2.0 Imports: 8 Imported by: 1

README

dis_lock

基于redis的分布式锁

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrPreemptLock    = errors.New("抢锁失败")
	ErrLockNotExist   = errors.New("锁不存在")
	ErrRefreshFailed  = errors.New("续约失败")
	ErrMaxRetryFailed = errors.New("超过最大重试次数")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(client redis.Cmdable) *Client

func (*Client) Lock

func (c *Client) Lock(ctx context.Context, key, val string, expiration, timeout time.Duration, retry RetryStrategy) (*Lock, error)

Lock 申请分布式锁,内部会重试抢锁

func (*Client) TryLock

func (c *Client) TryLock(ctx context.Context, key, val string, expiration time.Duration) (*Lock, error)

TryLock 尝试加锁 @param ctx context.Context 上下文 @param key string 锁在redis中的key名称 @param val string 锁的唯一标识,标识是哪一个进程/程序申请的 @param expiration time.Duration 分布式锁的过期时间

func (*Client) UUID

func (c *Client) UUID() string

UUID 生成唯一的ID,用户区分进程/程序,可选

type FixedIntervalStrategy

type FixedIntervalStrategy struct {
	// contains filtered or unexported fields
}

FixedIntervalStrategy 固定时间间隔策略

func NewFixedIntervalStrategy

func NewFixedIntervalStrategy(interval time.Duration,
	maxRetry int) *FixedIntervalStrategy

func (*FixedIntervalStrategy) Next

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

func (l *Lock) Refresh(ctx context.Context) error

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:

func (*Lock) UnLock

func (l *Lock) UnLock(ctx context.Context) error

UnLock 并发安全的释放锁 释放锁之前需要先判断锁是否存在,锁是否是申请的锁,然后才可以删除 防止删除了别人申请的锁

type NonFixedIntervalStrategy

type NonFixedIntervalStrategy struct {
	// contains filtered or unexported fields
}

func NewNonFixedIntervalStrategy

func NewNonFixedIntervalStrategy(interval time.Duration, maxRetry int) *NonFixedIntervalStrategy

func (*NonFixedIntervalStrategy) Next

type RetryStrategy

type RetryStrategy interface {
	// Next
	// 第一个返回值为重试的时间间隔
	// 第二个返回值为错误信息
	Next() (time.Duration, error)
}

Directories

Path Synopsis
Package mock_v9 is a generated GoMock package.
Package mock_v9 is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL