go_redislock

package module
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2025 License: MIT Imports: 7 Imported by: 12

README

go-redislock

Go Release Action Report Coverage Doc License

English | 简体中文

介绍

go-redislock 是一个用于 Go 的库,用于使用 Redis 作为后端存储提供分布式锁功能。确保在分布式环境中的并发访问下实现数据共享和资源互斥。我们的分布式锁具备可靠性、高性能、超时机制、可重入性和灵活的锁释放方式等特性,简化了分布式锁的使用,让您专注于业务逻辑的实现。

我们实现了以下关键能力:

  • 🔒 普通分布式锁(可重入)
  • 🔁 自旋锁
  • ⚖️ 公平锁(FIFO 顺序)
  • 🧵读锁(多个读者并发访问,互斥写者)
  • ✍️写锁(独占访问资源)
  • 【即将发布】🔗联锁(MultiLock)(多个锁一起获取,全成功才算加锁)
  • 🔄 手动续期与自动续期
  • ✅ 多 Redis 客户端适配(v7/v8/v9、go-zero、goframe)

快速开始

安装
go get -u github.com/jefferyjob/go-redislock
使用Demo
package main

import (
	"context"
	"fmt"

	redislock "github.com/jefferyjob/go-redislock"
	adapter "github.com/jefferyjob/go-redislock/adapter/go-redis/v9"
	"github.com/redis/go-redis/v9"
)

func main() {
	// Create a Redis client adapter
	rdbAdapter := adapter.New(redis.NewClient(&redis.Options{
		Addr: "localhost:6379",
	}))

	// Create a context for canceling lock operations
	ctx := context.Background()

	// Create a RedisLock object
	lock := redislock.New(rdbAdapter, "test_key")

	// acquire lock
	err := lock.Lock(ctx)
	if err != nil {
		fmt.Println("lock acquisition failed:", err)
		return
	}
	defer lock.UnLock(ctx) // unlock

	// Perform tasks during lockdown
	// ...
	fmt.Println("task execution completed")
}

配置选项
选项函数 说明 默认值
WithTimeout(d time.Duration) 锁超时时间(TTL) 5s
WithAutoRenew() 是否自动续期 false
WithToken(token string) 可重入锁 Token(唯一标识) 随机 UUID
WithRequestTimeout(d time.Duration) 公平锁队列最大等待时间 同 TTL

核心功能一览

普通锁
方法名 说明
Lock(ctx) 获取普通锁(支持可重入)
SpinLock(ctx, timeout) 自旋方式获取普通锁
UnLock(ctx) 解锁操作
Renew(ctx) 手动续期
公平锁(FIFO)
方法名 说明
FairLock(ctx, requestId) 获取公平锁(FIFO)
SpinFairLock(ctx, requestId, timeout) 自旋方式获取公平锁
FairUnLock(ctx, requestId) 公平锁解锁
FairRenew(ctx, requestId) 公平锁续期
读锁
方法名 说明
RLock(ctx) 获取读锁(支持可重入)
SpinRLock(ctx, timeout) 自旋方式获取读锁
UnLRock(ctx) 解锁操作
RRenew(ctx) 手动续期
写锁
方法名 说明
WLock(ctx) 获取写锁(支持可重入)
SpinWLock(ctx, timeout) 自旋方式获取写锁
UnWLock(ctx) 解锁操作
WRenew(ctx) 手动续期
接口定义如下
type RedisLockInter interface {
	// Lock 加锁
	Lock(ctx context.Context) error
	// SpinLock 自旋锁
	SpinLock(ctx context.Context, timeout time.Duration) error
	// UnLock 解锁
	UnLock(ctx context.Context) error
	// Renew 手动续期
	Renew(ctx context.Context) error

	// FairLock 公平锁加锁
	FairLock(ctx context.Context, requestId string) error
	// SpinFairLock 自旋公平锁
	SpinFairLock(ctx context.Context, requestId string, timeout time.Duration) error
	// FairUnLock 公平锁解锁
	FairUnLock(ctx context.Context, requestId string) error
	// FairRenew 公平锁续期
	FairRenew(ctx context.Context, requestId string) error

    // RLock 读锁加锁
    RLock(ctx context.Context) error
    // RUnLock 读锁解锁
    RUnLock(ctx context.Context) error
    // SpinRLock 自旋读锁
    SpinRLock(ctx context.Context, timeout time.Duration) error
    // RRenew 读锁续期
    RRenew(ctx context.Context) error
    
    // WLock 写锁加锁
    WLock(ctx context.Context) error
    // WUnLock 写锁解锁
    WUnLock(ctx context.Context) error
    // SpinWLock 自旋写锁
    SpinWLock(ctx context.Context, timeout time.Duration) error
    // WRenew 写锁续期
    WRenew(ctx context.Context) error
}

Redis客户端支持

go-redislock 提供高度可扩展的客户端适配机制,已内置支持以下主流 Redis 客户端,详细示例请参考 examples

Redis客户端版本 包路径 是否支持
go-redis v7 github.com/jefferyjob/go-redislock/adapter/go-redis/V7
go-redis v8 github.com/jefferyjob/go-redislock/adapter/go-redis/V8
go-redis v9 github.com/jefferyjob/go-redislock/adapter/go-redis/V9
go-zero redis github.com/jefferyjob/go-redislock/adapter/go-zero/V1
goframe v1 redis github.com/jefferyjob/go-redislock/adapter/gf/V1
goframe v2 redis github.com/jefferyjob/go-redislock/adapter/gf/V2

如您使用的 Redis 客户端不在上述列表中,也可以实现接口 RedisInter 来接入任意 Redis 客户端。

注意事项

  • 每次加锁建议使用新的锁实例。
  • 加锁和解锁必须使用同一个 key 和 token。
  • 默认 TTL 是 5 秒,建议根据任务耗时自行设置。
  • 自动续期适合无阻塞任务,避免长时间阻塞。
  • 建议关键逻辑中使用 defer unlock,防止泄露。
  • 建议对锁获取失败、重试等行为做日志或监控。
  • 公平锁需传入唯一的 requestId(建议使用 UUID)。
  • 读锁可并发,写锁互斥,避免读写冲突。
  • 联锁中任一子锁失败,会释放已加成功的锁。
  • Redis 不可用时可能造成死锁风险。

许可证

本库采用 MIT 进行授权。有关详细信息,请参阅 LICENSE 文件。

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrLockFailed 加锁失败
	ErrLockFailed = errors.New("lock failed")
	// ErrUnLockFailed 解锁失败
	ErrUnLockFailed = errors.New("unLock failed")
	// ErrSpinLockTimeout 自旋锁加锁超时
	ErrSpinLockTimeout = errors.New("spin lock timeout")
	// ErrSpinLockDone 自旋锁加锁超时
	ErrSpinLockDone = errors.New("spin lock context done")
	// ErrLockRenewFailed 锁续期失败
	ErrLockRenewFailed = errors.New("lock renew failed")
	// ErrException 内部异常
	ErrException = errors.New("go redis lock internal exception")
)

Functions

This section is empty.

Types

type Option

type Option func(lock *RedisLock)

func WithAutoRenew

func WithAutoRenew() Option

WithAutoRenew enables automatic lock renewal WithAutoRenew 是否开启自动续期

func WithRequestTimeout added in v1.3.0

func WithRequestTimeout(timeout time.Duration) Option

WithRequestTimeout sets the maximum wait time in the fair lock queue WithRequestTimeout 设置公平锁在队列中的最大等待时间

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the expiration time of the lock WithTimeout 设置锁的过期时间

func WithToken

func WithToken(token string) Option

WithToken sets a custom token for the lock instance WithToken 设置锁的 Token,用于标识当前持有者

type RedisCmd added in v1.3.0

type RedisCmd interface {
	Result() (interface{}, error)
	Int64() (int64, error)
}

RedisCmd Eval 返回结果的接口

type RedisInter added in v1.1.0

type RedisInter interface {
	Eval(ctx context.Context, script string, keys []string, args ...interface{}) RedisCmd
}

RedisInter Redis 客户端接口

type RedisLock

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

func (*RedisLock) FairLock added in v1.3.0

func (l *RedisLock) FairLock(ctx context.Context, requestId string) error

FairLock 公平锁尝试加锁(使用指定的 requestId 获取公平锁) FairLock tries to acquire a fair lock using the given requestId. 公平锁确保请求按照顺序获取锁,避免饥饿现象 如果是队首且成功获取锁则返回 nil,否则返回 ErrLockFailed

func (*RedisLock) FairRenew added in v1.3.0

func (l *RedisLock) FairRenew(ctx context.Context, requestId string) error

FairRenew manually extends the expiration of a fair lock. FairRenew 手动延长指定 requestId 的公平锁有效期。

func (*RedisLock) FairUnLock added in v1.3.0

func (l *RedisLock) FairUnLock(ctx context.Context, requestId string) error

FairUnLock releases the fair lock held by the given requestId. FairUnLock 根据 requestId 释放公平锁。

func (*RedisLock) Lock

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

Lock tries to acquire a standard lock. This implementation supports "reentrant locks". If the lock is currently held by the same key+token, reentry is allowed and the count is increased. Unlock() needs to be called a corresponding number of times to release the lock.

Lock 尝试获取普通锁。 该实现支持“可重入锁”,如果当前已由相同 key+token 持有,允许重入并增加计数。需调用相应次数 Unlock() 释放

func (*RedisLock) MultiLock added in v1.4.0

func (l *RedisLock) MultiLock(ctx context.Context, locks []RedisLockInter) error

func (*RedisLock) MultiRenew added in v1.4.0

func (l *RedisLock) MultiRenew(ctx context.Context, locks []RedisLockInter) error

func (*RedisLock) MultiUnLock added in v1.4.0

func (l *RedisLock) MultiUnLock(ctx context.Context, locks []RedisLockInter) error

func (*RedisLock) RLock added in v1.4.0

func (l *RedisLock) RLock(ctx context.Context) error

func (*RedisLock) RRenew added in v1.4.0

func (l *RedisLock) RRenew(ctx context.Context) error

func (*RedisLock) RUnLock added in v1.4.0

func (l *RedisLock) RUnLock(ctx context.Context) error

func (*RedisLock) Renew

func (l *RedisLock) Renew(ctx context.Context) error

Renew manually extends the lock expiration. Renew 手动延长锁的有效期。

func (*RedisLock) SpinFairLock added in v1.3.0

func (l *RedisLock) SpinFairLock(ctx context.Context, requestId string, timeout time.Duration) error

SpinFairLock keeps trying to acquire a fair lock until timeout. SpinFairLock 在指定超时时间内不断尝试获取公平锁。

func (*RedisLock) SpinLock

func (l *RedisLock) SpinLock(ctx context.Context, timeout time.Duration) error

SpinLock keeps trying to acquire the lock until timeout. SpinLock 在指定超时时间内不断尝试加锁。

func (*RedisLock) SpinMultiLock added in v1.4.0

func (l *RedisLock) SpinMultiLock(ctx context.Context, locks []RedisLockInter, timeout time.Duration) error

func (*RedisLock) SpinRLock added in v1.4.0

func (l *RedisLock) SpinRLock(ctx context.Context, timeout time.Duration) error

func (*RedisLock) SpinWLock added in v1.4.0

func (l *RedisLock) SpinWLock(ctx context.Context, timeout time.Duration) error

func (*RedisLock) UnLock

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

UnLock releases the standard lock. If it is a reentrant lock, each call will reduce the holding count until the count reaches 0 and the lock will be released.

UnLock 释放普通锁。 如果为重入锁,每调用一次减少一次持有计数,直到计数为 0 锁会被释放

func (*RedisLock) WLock added in v1.4.0

func (l *RedisLock) WLock(ctx context.Context) error

func (*RedisLock) WRenew added in v1.4.0

func (l *RedisLock) WRenew(ctx context.Context) error

func (*RedisLock) WUnLock added in v1.4.0

func (l *RedisLock) WUnLock(ctx context.Context) error

type RedisLockInter

type RedisLockInter interface {
	// Lock 加锁
	Lock(ctx context.Context) error
	// SpinLock 自旋锁。
	SpinLock(ctx context.Context, timeout time.Duration) error
	// UnLock 解锁
	UnLock(ctx context.Context) error
	// Renew 锁续期
	Renew(ctx context.Context) error

	// FairLock 公平锁加锁
	FairLock(ctx context.Context, requestId string) error
	// SpinFairLock 自旋公平锁
	SpinFairLock(ctx context.Context, requestId string, timeout time.Duration) error
	// FairUnLock 公平锁解锁
	FairUnLock(ctx context.Context, requestId string) error
	// FairRenew 公平锁续期
	FairRenew(ctx context.Context, requestId string) error

	// RLock 读锁加锁
	RLock(ctx context.Context) error
	// RUnLock 读锁解锁
	RUnLock(ctx context.Context) error
	// SpinRLock 自旋读锁
	SpinRLock(ctx context.Context, timeout time.Duration) error
	// RRenew 读锁续期
	RRenew(ctx context.Context) error

	// WLock 写锁加锁
	WLock(ctx context.Context) error
	// WUnLock 写锁解锁
	WUnLock(ctx context.Context) error
	// SpinWLock 自旋写锁
	SpinWLock(ctx context.Context, timeout time.Duration) error
	// WRenew 写锁续期
	WRenew(ctx context.Context) error
}

RedisLockInter defines the interface for distributed Redis locks

func New

func New(redisClient RedisInter, lockKey string, options ...Option) RedisLockInter

New creates a RedisLock instance

Directories

Path Synopsis
adapter
gf module
gf/V1 module
gf/V2 module
go-redis module
go-redis/V8 module
go-redis/V9 module
go-zero module
go-zero/V1 module
examples
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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