ling-baseling-base

分布式锁

进程内与 Redis/etcd 分布式锁

在线 Playground

在浏览器中直接体验本页相关 API,无需本地安装 Go 环境。

分布式锁

统一 Lock 接口,支持 mutex、Redis、etcd、PostgreSQL 等后端。

go get github.com/LingByte/ling-base/common/lock
go get github.com/LingByte/ling-base/common/lock/redis

以下为 common/lock 包 README 全文。

Unified distributed locking for Go services. All backends implement the same lock.Locker interface:

  • Lock(ctx) — block until acquired or context cancelled
  • TryLock(ctx) — single attempt
  • Unlock(ctx) — release
  • Refresh(ctx) — extend lease where supported

Shared configuration uses functional options: WithTTL, WithRetryDelay, and WithValue (auto-generated token when empty).

On-demand modules

Module pathThird-party deps
github.com/LingByte/ling-base/common/locknone (+ lock/memory)
.../lock/redisgo-redis
.../lock/redlocklock/redis
.../lock/etcdetcd clientv3
.../lock/zookeepergo-zookeeper/zk
.../lock/consulhashicorp/consul/api
.../lock/mysqldatabase/sql only
.../lock/postgresdatabase/sql only
go get github.com/LingByte/ling-base/common/lock/redis

Backends

PackageUse caseTTL / leaseRefresh
memoryProcess-local (tests, single instance)In-memory expiryYes
redisSingle Redis node (SET NX + Lua unlock/refresh)RequiredYes
redlockMultiple Redis nodes (quorum)RequiredYes (quorum)
etcdetcd v3 lease + transactional create≥ 1sKeepAlive
zookeeperEphemeral sequential nodesSessionNo-op (session)
consulSession + KV lock≥ 1sSession renew
mysqlGET_LOCK / RELEASE_LOCKN/A (connection)No-op
postgresAdvisory locks (pg_try_advisory_lock)N/A (session)No-op

Quick start

import (
    "context"
    "time"

    "github.com/LingByte/ling-base/common/lock"
    lockredis "github.com/LingByte/ling-base/common/lock/redis"
    goredis "github.com/redis/go-redis/v9"
)

func run(client *goredis.Client) error {
    mu, err := lockredis.NewMutex(client, "orders:42",
        lock.WithTTL(30*time.Second),
        lock.WithRetryDelay(100*time.Millisecond),
    )
    if err != nil {
        return err
    }
    ctx := context.Background()
    if err := mu.Lock(ctx); err != nil {
        return err
    }
    defer mu.Unlock(ctx)
    return mu.Refresh(ctx)
}

On this page