English | 简体中文
go-redislock 是一个用于 Go 的库,用于使用 Redis 作为后端存储提供分布式锁功能。确保在分布式环境中的并发访问下实现数据共享和资源互斥。我们的分布式锁具备可靠性、高性能、超时机制、可重入性和灵活的锁释放方式等特性,简化了分布式锁的使用,让您专注于业务逻辑的实现。
我们实现了以下关键能力:
- 🔒 普通分布式锁(可重入)
- 🔁 自旋锁
- ⚖️ 公平锁(FIFO 顺序)
- 🧵读锁(多个读者并发访问,互斥写者)
- ✍️写锁(独占访问资源)
- 🔄 手动续期与自动续期
- ✅ 多 Redis 客户端适配(v7/v8/v9、go-zero)
go get -u github.com/jefferyjob/go-redislock
# 根据所使用的 Redis 客户端选择匹配的适配器。
go get -u github.com/jefferyjob/go-redislock/adapter/go-redis/V9package 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) |
手动续期 |
| 方法名 | 说明 |
|---|---|
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
}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 |
✅ |
如您使用的 Redis 客户端不在上述列表中,也可以实现接口 RedisInter 来接入任意 Redis 客户端。
- 每次加锁建议使用新的锁实例。
- 加锁和解锁必须使用同一个 key 和 token。
- 默认 TTL 是 5 秒,建议根据任务耗时自行设置。
- 自动续期适合无阻塞任务,避免长时间阻塞。
- 建议关键逻辑中使用
defer unlock,防止泄露。 - 建议对锁获取失败、重试等行为做日志或监控。
- 公平锁需传入唯一的 requestId(建议使用 UUID)。
- 读锁可并发,写锁互斥,避免读写冲突。
- 联锁中任一子锁失败,会释放已加成功的锁。
- Redis 不可用时可能造成死锁风险。
本库采用 MIT 进行授权。有关详细信息,请参阅 LICENSE 文件。