lockmgr

package
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Jan 26, 2026 License: BSD-2-Clause Imports: 15 Imported by: 0

README

LockMgr - 锁管理器

LockMgr 提供统一的锁管理功能,支持 Redis 分布式锁和 Memory 本地内存锁,内置完整的可观测性支持。

特性

  • 多驱动支持:支持 Redis(分布式锁)和 Memory(本地内存锁)两种驱动
  • 统一接口:提供统一的 ILockManager 接口,便于切换实现
  • 可观测性:内置日志、指标和链路追踪支持
  • 自动过期:支持锁的 TTL 自动过期,防止死锁
  • 非阻塞模式:TryLock 支持非阻塞获取锁
  • 依赖注入:支持通过 inject:"" 标签注入 Manager
  • 健康检查:内置健康检查接口,便于监控

快速开始

package main

import (
	"context"
	"time"

	"github.com/lite-lake/litecore-go/manager/lockmgr"
)

func main() {
	ctx := context.Background()

	// 创建内存锁管理器
	mgr := lockmgr.NewLockManagerMemoryImpl(nil, nil, &lockmgr.MemoryLockConfig{
		MaxBackups: 1000,
	})
	defer mgr.Close()

	// 获取锁
	err := mgr.Lock(ctx, "resource:123", 10*time.Second)
	if err != nil {
		panic(err)
	}
	defer mgr.Unlock(ctx, "resource:123")

	// 执行需要加锁的操作
}

支持的锁驱动

Memory 驱动

基于 sync.Mutex 实现的本地内存锁,适用于单机环境。

特点

  • 高性能,无网络开销
  • 仅适用于单机进程
  • 锁在内存中维护,进程重启后丢失

适用场景

  • 单机应用
  • 单元测试
  • 不需要分布式协调的场景
Redis 驱动

基于 Redis SET NX EX 命令实现的分布式锁,适用于分布式环境。

特点

  • 支持分布式环境
  • 依赖 cachemgr.ICacheManager
  • 锁键格式:lock:{key}
  • Lock 方法内部自动重试(50ms 间隔)

适用场景

  • 微服务架构
  • 多实例部署
  • 需要跨进程锁的场景

API 说明

ILockManager 接口
type ILockManager interface {
	common.IBaseManager

	// Lock 获取锁(阻塞直到成功或上下文取消)
	// ctx: 上下文
	// key: 锁的键
	// ttl: 锁的过期时间,0表示不过期
	Lock(ctx context.Context, key string, ttl time.Duration) error

	// Unlock 释放锁
	// ctx: 上下文
	// key: 锁的键
	Unlock(ctx context.Context, key string) error

	// TryLock 尝试获取锁(非阻塞)
	// ctx: 上下文
	// key: 锁的键
	// ttl: 锁的过期时间,0表示不过期
	// 返回: 成功返回 true,失败返回 false
	TryLock(ctx context.Context, key string, ttl time.Duration) (bool, error)
}
Lock - 阻塞获取锁

Lock 方法会阻塞直到成功获取锁或上下文取消。

ctx := context.Background()

// 获取锁,自动重试直到成功或上下文取消
err := lockMgr.Lock(ctx, "resource:123", 10*time.Second)
if err != nil {
	return err
}
defer lockMgr.Unlock(ctx, "resource:123")

// 执行需要加锁的操作

注意事项

  • Memory 驱动使用 sync.Mutex,会阻塞当前 goroutine
  • Redis 驱动每 50ms 重试一次
  • 建议使用 defer 确保锁一定会被释放
Unlock - 释放锁

Unlock 方法释放已持有的锁。

err := lockMgr.Unlock(ctx, "resource:123")
if err != nil {
	return err
}

建议使用 defer 确保锁一定会被释放:

lockMgr.Lock(ctx, "resource:123", 10*time.Second)
defer lockMgr.Unlock(ctx, "resource:123")
TryLock - 非阻塞获取锁

TryLock 方法尝试获取锁,立即返回结果,不阻塞。

ctx := context.Background()

locked, err := lockMgr.TryLock(ctx, "resource:123", 10*time.Second)
if err != nil {
	return err
}

if locked {
	defer lockMgr.Unlock(ctx, "resource:123")
	// 执行需要加锁的操作
} else {
	// 锁已被占用
}

工厂函数

Build - 手动创建
import "github.com/lite-lake/litecore-go/manager/lockmgr"

// 创建内存锁
mgr, err := lockmgr.Build("memory", map[string]any{
	"max_backups": 1000,
}, loggerMgr, telemetryMgr, nil)

// 创建 Redis 锁
mgr, err := lockmgr.Build("redis", map[string]any{
	"host":              "localhost",
	"port":              6379,
	"password":          "",
	"db":                0,
	"max_idle_conns":    10,
	"max_open_conns":    100,
	"conn_max_lifetime": "30s",
}, loggerMgr, telemetryMgr, cacheMgr)
BuildWithConfigProvider - 从配置创建
mgr, err := lockmgr.BuildWithConfigProvider(
	configProvider,
	loggerMgr,
	telemetryMgr,
	cacheMgr,
)

配置

Redis 驱动配置
lock:
  driver: redis
  redis_config:
    host: localhost
    port: 6379
    password: ""
    db: 0
    max_idle_conns: 10
    max_open_conns: 100
    conn_max_lifetime: 30s

配置参数

参数 类型 默认值 说明
host string localhost Redis 主机地址
port int 6379 Redis 端口
password string "" Redis 密码
db int 0 Redis 数据库编号
max_idle_conns int 10 最大空闲连接数
max_open_conns int 100 最大打开连接数
conn_max_lifetime duration 30s 连接最大存活时间
Memory 驱动配置
lock:
  driver: memory
  memory_config:
    max_backups: 1000

配置参数

参数 类型 默认值 说明
max_backups int 1000 最大备份项数

依赖注入

type MyService struct {
	LockMgr lockmgr.ILockManager `inject:""`
	logger   loggermgr.ILogger
}

func (s *MyService) ProcessResource(ctx context.Context, resourceID string) error {
	if s.logger == nil && s.LockMgr != nil {
		s.logger = s.LockMgr.Ins()
	}

	// 获取锁
	key := fmt.Sprintf("resource:%s", resourceID)
	err := s.LockMgr.Lock(ctx, key, 10*time.Second)
	if err != nil {
		s.logger.Error("获取锁失败", "resource_id", resourceID, "error", err)
		return err
	}
	defer s.LockMgr.Unlock(ctx, key)

	// 执行业务逻辑
	return nil
}

可观测性

LockMgr 内置完整的可观测性支持:

指标
指标名称 类型 说明
lock.acquire Counter 锁获取次数
lock.release Counter 锁释放次数
lock.acquire_failed Counter 锁获取失败次数
lock.operation.duration Histogram 锁操作耗时(秒)

指标标签

  • lock.driver: 驱动类型(redis/memory)
  • operation: 操作类型(lock/unlock/trylock)
  • status: 状态(success/error)
日志

记录锁操作的成功和失败事件,包含操作类型、锁键(已脱敏)、耗时等信息。

链路追踪

支持 OpenTelemetry 链路追踪,每个锁操作都会创建一个 span。

错误处理

所有锁操作都可能返回错误,常见错误包括:

错误类型 说明 处理建议
context canceled 上下文被取消 检查上下文超时设置
context deadline exceeded 操作超时 增加 TTL 或优化业务逻辑
cache manager not injected Redis 驱动未注入缓存管理器 注入 cachemgr.ICacheManager
lock key cannot be empty 锁键为空 检查 key 参数
context cannot be nil 上下文为 nil 传递有效的 context.Context

使用场景

  1. 分布式环境下的资源互斥访问:防止多个进程同时修改同一资源
  2. 并发控制:防止重复操作,如防止重复提交表单
  3. 任务队列:确保任务只能被一个消费者处理
  4. 限流控制:配合令牌桶等算法实现限流
  5. 数据库更新防并发:防止并发更新导致数据不一致

最佳实践

  1. 使用 defer 确保锁释放:在获取锁后立即使用 defer 释放锁
  2. 设置合理的 TTL:根据业务场景设置合适的 TTL,防止死锁
  3. 选择合适的驱动:分布式环境使用 Redis 驱动,单机环境使用 Memory 驱动
  4. 锁粒度控制:锁的粒度应尽可能小,减少锁的持有时间
  5. 错误处理:所有锁操作都应进行错误处理
  6. 上下文使用:始终传递有效的 context.Context,支持超时和取消
  7. 锁命名规范:使用清晰的锁键命名,如 resource:{id}task:{name}
  8. 避免长时间持有锁:锁的持有时间应尽可能短,避免阻塞其他操作

Documentation

Overview

Package lockmgr 提供统一的锁管理功能,支持 Redis 和 Memory 两种驱动。

核心特性:

  • 多驱动支持:支持 Redis(分布式锁)、Memory(本地内存锁)两种锁驱动
  • 统一接口:提供统一的 ILockManager 接口,便于切换锁实现
  • 可观测性:内置日志、指标和链路追踪支持
  • 自动过期:支持锁的自动过期机制,防止死锁
  • 非阻塞模式:TryLock 支持非阻塞获取锁

基本用法:

// 使用内存锁
mgr := lockmgr.NewLockManagerMemoryImpl(&lockmgr.MemoryLockConfig{})
defer mgr.Close()

ctx := context.Background()

// 获取锁(阻塞)
err := mgr.Lock(ctx, "resource:123", 10*time.Second)
if err != nil {
    log.Fatal(err)
}

// 执行需要加锁的操作
// ...

// 释放锁
mgr.Unlock(ctx, "resource:123")

使用 Redis 分布式锁:

cfg := &lockmgr.RedisLockConfig{
    Host:     "localhost",
    Port:     6379,
    Password: "",
    DB:       0,
}
mgr := lockmgr.NewLockManagerRedisImpl(cfg)
defer mgr.Close()

非阻塞获取锁:

// 尝试获取锁(非阻塞)
locked, err := mgr.TryLock(ctx, "resource:123", 10*time.Second)
if err != nil {
    log.Fatal(err)
}
if locked {
    // 成功获取锁
    // 执行需要加锁的操作
    // ...

    // 释放锁
    mgr.Unlock(ctx, "resource:123")
} else {
    // 锁已被占用
    log.Println("锁已被占用")
}

配置驱动类型:

// 通过 Build 函数创建
mgr, err := lockmgr.Build("memory", map[string]any{
    "max_backups": 1000,
})

// 通过配置提供者创建
mgr, err := lockmgr.BuildWithConfigProvider(configProvider)

使用场景:

  • 分布式环境下的资源互斥访问
  • 并发控制,防止重复操作
  • 任务队列的任务消费
  • 限流控制

Index

Constants

View Source
const (
	// 默认值
	DefaultRedisHost            = "localhost"
	DefaultRedisPort            = 6379
	DefaultRedisDB              = 0
	DefaultRedisMaxIdleConns    = 10
	DefaultRedisMaxOpenConns    = 100
	DefaultRedisConnMaxLifetime = 30 * time.Second

	DefaultMemoryMaxBackups = 1000
)

Variables

This section is empty.

Functions

func ValidateContext

func ValidateContext(ctx context.Context) error

ValidateContext 验证上下文是否有效

func ValidateKey

func ValidateKey(key string) error

ValidateKey 验证锁键是否有效

Types

type ILockManager

type ILockManager interface {
	common.IBaseManager

	// Lock 获取锁(阻塞直到成功或超时)
	// ctx: 上下文
	// key: 锁的键
	// ttl: 锁的过期时间
	// 返回: 成功获取锁返回 nil,否则返回错误
	Lock(ctx context.Context, key string, ttl time.Duration) error

	// Unlock 释放锁
	// ctx: 上下文
	// key: 锁的键
	Unlock(ctx context.Context, key string) error

	// TryLock 尝试获取锁(非阻塞)
	// ctx: 上下文
	// key: 锁的键
	// ttl: 锁的过期时间
	// 返回: 成功返回 true,失败返回 false
	TryLock(ctx context.Context, key string, ttl time.Duration) (bool, error)
}

ILockManager 锁管理器接口

func Build

func Build(
	driverType string,
	driverConfig map[string]any,
	loggerMgr loggermgr.ILoggerManager,
	telemetryMgr telemetrymgr.ITelemetryManager,
	cacheMgr cachemgr.ICacheManager,
) (ILockManager, error)

Build 创建锁管理器实例 参数:

  • driverType: 驱动类型 ("redis", "memory")
  • driverConfig: 驱动配置 (根据驱动类型不同而不同)
  • loggerMgr: 日志管理器
  • telemetryMgr: 遥测管理器
  • cacheMgr: 缓存管理器(Redis 模式必需,Memory 模式可以为 nil)

返回 ILockManager 接口实例和可能的错误

func BuildWithConfigProvider

func BuildWithConfigProvider(
	configProvider configmgr.IConfigManager,
	loggerMgr loggermgr.ILoggerManager,
	telemetryMgr telemetrymgr.ITelemetryManager,
	cacheMgr cachemgr.ICacheManager,
) (ILockManager, error)

BuildWithConfigProvider 从配置提供者创建锁管理器实例 自动从配置提供者读取 lock.driver 和对应驱动配置 参数:

  • configProvider: 配置提供者
  • loggerMgr: 日志管理器
  • telemetryMgr: 遥测管理器
  • cacheMgr: 缓存管理器(Redis 模式必需,Memory 模式可以为 nil)

返回 ILockManager 接口实例和可能的错误

func NewLockManagerMemoryImpl

func NewLockManagerMemoryImpl(
	loggerMgr loggermgr.ILoggerManager,
	telemetryMgr telemetrymgr.ITelemetryManager,
	config *MemoryLockConfig,
) ILockManager

NewLockManagerMemoryImpl 创建内存锁管理器实例 参数:

  • loggerMgr: 日志管理器
  • telemetryMgr: 遥测管理器
  • config: 内存锁配置

@return ILockManager 锁管理器接口

func NewLockManagerRedisImpl

func NewLockManagerRedisImpl(
	loggerMgr loggermgr.ILoggerManager,
	telemetryMgr telemetrymgr.ITelemetryManager,
	cacheMgr cachemgr.ICacheManager,
	config *RedisLockConfig,
) ILockManager

NewLockManagerRedisImpl 创建Redis锁管理器实例 参数:

  • loggerMgr: 日志管理器
  • telemetryMgr: 遥测管理器
  • cacheMgr: 缓存管理器
  • config: Redis锁配置

@return ILockManager 锁管理器接口

type LockConfig

type LockConfig struct {
	Driver       string            `yaml:"driver"`        // 驱动类型: redis, memory
	RedisConfig  *RedisLockConfig  `yaml:"redis_config"`  // Redis 配置
	MemoryConfig *MemoryLockConfig `yaml:"memory_config"` // Memory 配置
}

LockConfig 锁配置

func DefaultConfig

func DefaultConfig() *LockConfig

DefaultConfig 返回默认配置(使用内存锁驱动)

func ParseLockConfigFromMap

func ParseLockConfigFromMap(cfg map[string]any) (*LockConfig, error)

ParseLockConfigFromMap 从 ConfigMap 解析锁配置

func (*LockConfig) Validate

func (c *LockConfig) Validate() error

Validate 验证配置

type MemoryLockConfig

type MemoryLockConfig struct {
	MaxBackups int `yaml:"max_backups"` // 最大备份项数(清理策略相关)
}

MemoryLockConfig 内存锁配置

type RedisLockConfig

type RedisLockConfig struct {
	Host            string        `yaml:"host"`              // Redis 主机地址
	Port            int           `yaml:"port"`              // Redis 端口
	Password        string        `yaml:"password"`          // Redis 密码
	DB              int           `yaml:"db"`                // Redis 数据库编号
	MaxIdleConns    int           `yaml:"max_idle_conns"`    // 最大空闲连接数
	MaxOpenConns    int           `yaml:"max_open_conns"`    // 最大打开连接数
	ConnMaxLifetime time.Duration `yaml:"conn_max_lifetime"` // 连接最大存活时间
}

RedisLockConfig Redis 锁配置

Jump to

Keyboard shortcuts

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