# 1. 基于 Redis 的分布式锁

优点:

  • 性能高,延迟低
  • 实现相对简单
  • 支持过期时间自动释放

核心特性:

  • 使用 SET NX PX 原子操作获取锁
  • 使用 Lua 脚本确保释放锁的原子性
  • 防止误删其他客户端的锁
  • 支持锁续约
import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"time"
	
	"github.com/redis/go-redis/v9"
)
type DistributedLock interface {
	Lock(ctx context.Context) error
	Unlock(ctx context.Context) error
	TryLock(ctx context.Context) (bool, error)
	Refresh(ctx context.Context, ttl time.Duration) error
}
// 基于 Redis 的分布式锁
type RedisDistriburedLock struct {
	client     *redis.Client
	key        string
	value      string
	ttl        time.Duration
	retryDelay time.Duration
}
// 生成随机值,防止误解锁
func generateRandomValue() string {
	bytes := make([]byte, 16)
	rand.Read(bytes)
	return hex.EncodeToString(bytes)
}
func (r *RedisDistriburedLock) Lock(ctx context.Context) error {
	ticker := time.NewTicker(r.retryDelay)
	defer ticker.Stop()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-ticker.C:
			result := r.client.SetNX(ctx, r.key, r.value, r.ttl)
			if result.Err() != nil {
				return result.Err()
			}
			if result.Val() {
				return nil // 获取锁成功
			}
		}
	}
}
// 尝试获取锁,不阻塞
func (r *RedisDistriburedLock) TryLock(ctx context.Context) (bool, error) {
	result := r.client.SetNX(ctx, r.key, r.value, r.ttl)
	if result.Err() != nil {
		return false, result.Err()
	}
	return result.Val(), nil
}
func (r *RedisDistriburedLock) Unlock(ctx context.Context) error {
	//lua 脚本,确保只有锁的持有者才能释放锁
	luaScript := `
		if redis.call("GET",KEY[1]) == ARGV[1] then
			return redis.call("DEL",KEYS[1])
		else
			return 0
		end
	`
	result := r.client.Eval(ctx, luaScript, []string{r.key}, r.value)
	if result.Err() != nil {
		return result.Err()
	}
	if result.Val().(int64) == 0 {
		return errors.New("lock not owned by current client")
	}
	return nil
}
func (r *RedisDistriburedLock)Refresh(ctx context.Context,ttl time.Duration) error{
	luaScript := `
	if redis.call("GET",KEYS[1]) = ARGV[1] then 
		return redis.call("PEXPIRE",KEYS[1],ARGV[2])
	else
		return 0
	end
	`
	result := r.client.Eval(ctx, luaScript, []string{r.key}, r.value, int64(ttl/time.Millisecond))
	if result.Err() != nil {
		return result.Err()
	}
	if result.Val().(int64) == 0 {
		return errors.New("lock not owned by current client")
	}
	return nil
}

# 2. 基于 etcd 的分布式锁

优点:

  • 强一致性保证
  • 自动续约机制
  • 支持锁的监听和等待

核心特性:

  • 基于 etcd 的 lease 机制
  • 使用 concurrency 包简化实现
  • 会话自动续约
    

# 3. 基于数据库的分布式锁

优点:

  • 实现简单,易于理解
  • 可以利用现有数据库
  • 强一致性

缺点:

  • 性能相对较低
  • 需要定期清理过期锁
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ZJM 微信支付

微信支付

ZJM 支付宝

支付宝