distributed-locks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Distributed Locks

分布式锁

Coordinate exclusive access to resources across multiple service instances.
实现跨多个服务实例的资源独占访问协调。

Overview

概述

  • Preventing duplicate processing of jobs/events
  • Coordinating singleton processes (cron, leaders)
  • Protecting critical sections across instances
  • Implementing leader election
  • Rate limiting at distributed level
  • 防止作业/事件重复处理
  • 协调单例进程(定时任务、领导者)
  • 跨实例保护临界区
  • 实现领导者选举
  • 分布式级别限流

Lock Types Comparison

锁类型对比

Lock TypeDurabilityLatencyUse Case
Redis (single)Low~1msFast, non-critical
Redlock (multi)High~5msCritical, HA required
PostgreSQL advisoryHigh~2msAlready using PG, ACID
锁类型持久性延迟适用场景
Redis(单节点)~1ms快速、非关键场景
Redlock(多节点)~5ms关键场景、需高可用
PostgreSQL advisory锁~2ms已使用PG、需ACID特性

Quick Reference

快速参考

Redis Lock (Single Node)

Redis锁(单节点)

python
from uuid_utils import uuid7
import redis.asyncio as redis

class RedisLock:
    """Redis lock with Lua scripts for atomicity."""

    ACQUIRE = "if redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2]) then return 1 end return 0"
    RELEASE = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) end return 0"

    def __init__(self, client: redis.Redis, name: str, ttl_ms: int = 30000):
        self._client = client
        self._name = f"lock:{name}"
        self._owner = str(uuid7())
        self._ttl = ttl_ms

    async def acquire(self) -> bool:
        return await self._client.eval(self.ACQUIRE, 1, self._name, self._owner, self._ttl) == 1

    async def release(self) -> bool:
        return await self._client.eval(self.RELEASE, 1, self._name, self._owner) == 1

    async def __aenter__(self):
        if not await self.acquire():
            raise LockError(f"Failed to acquire {self._name}")
        return self

    async def __aexit__(self, *_):
        await self.release()
See redis-locks.md for complete implementation with retry/extend.
python
from uuid_utils import uuid7
import redis.asyncio as redis

class RedisLock:
    """Redis lock with Lua scripts for atomicity."""

    ACQUIRE = "if redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2]) then return 1 end return 0"
    RELEASE = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) end return 0"

    def __init__(self, client: redis.Redis, name: str, ttl_ms: int = 30000):
        self._client = client
        self._name = f"lock:{name}"
        self._owner = str(uuid7())
        self._ttl = ttl_ms

    async def acquire(self) -> bool:
        return await self._client.eval(self.ACQUIRE, 1, self._name, self._owner, self._ttl) == 1

    async def release(self) -> bool:
        return await self._client.eval(self.RELEASE, 1, self._name, self._owner) == 1

    async def __aenter__(self):
        if not await self.acquire():
            raise LockError(f"Failed to acquire {self._name}")
        return self

    async def __aexit__(self, *_):
        await self.release()
查看redis-locks.md获取包含重试/续期的完整实现。

PostgreSQL Advisory Lock

PostgreSQL Advisory锁

python
from sqlalchemy import text

async def with_advisory_lock(session, lock_id: int):
    """PostgreSQL advisory lock (session-level)."""
    await session.execute(text("SELECT pg_advisory_lock(:id)"), {"id": lock_id})
    try:
        yield
    finally:
        await session.execute(text("SELECT pg_advisory_unlock(:id)"), {"id": lock_id})
See postgres-advisory-locks.md for transaction-level and monitoring.
python
from sqlalchemy import text

async def with_advisory_lock(session, lock_id: int):
    """PostgreSQL advisory lock (session-level)."""
    await session.execute(text("SELECT pg_advisory_lock(:id)"), {"id": lock_id})
    try:
        yield
    finally:
        await session.execute(text("SELECT pg_advisory_unlock(:id)"), {"id": lock_id})
查看postgres-advisory-locks.md获取事务级锁和监控相关内容。

Key Decisions

关键决策

DecisionRecommendation
BackendRedis for speed, PG if already using it
TTL2-3x expected operation time
RetryExponential backoff with jitter
FencingInclude owner ID for safety
决策项建议方案
后端存储追求速度选Redis,已使用PG则选PG
TTL设置为预期操作时间的2-3倍
重试策略带抖动的指数退避
防护机制包含所有者ID以保证安全

Anti-Patterns (FORBIDDEN)

反模式(禁止)

python
undefined
python
undefined

NEVER forget TTL (causes deadlocks)

NEVER forget TTL (causes deadlocks)

await redis.set(f"lock:{name}", "1") # WRONG - no expiry!
await redis.set(f"lock:{name}", "1") # WRONG - no expiry!

NEVER release without owner check

NEVER release without owner check

await redis.delete(f"lock:{name}") # WRONG - might release others' lock
await redis.delete(f"lock:{name}") # WRONG - might release others' lock

NEVER use single Redis for critical operations

NEVER use single Redis for critical operations

lock = RedisLock(single_redis, "payment") # Use Redlock for HA
lock = RedisLock(single_redis, "payment") # Use Redlock for HA

NEVER hold locks across await points without heartbeat

NEVER hold locks across await points without heartbeat

async with lock: await slow_external_api() # Lock may expire!
undefined
async with lock: await slow_external_api() # Lock may expire!
undefined

Related Skills

相关技能

  • idempotency-patterns
    - Complement locks with idempotency
  • caching-strategies
    - Redis patterns
  • background-jobs
    - Job deduplication
  • idempotency-patterns
    - 用幂等性补充锁的能力
  • caching-strategies
    - Redis相关模式
  • background-jobs
    - 作业去重

References

参考资料

  • Redis Locks - Lua scripts, retry, extend
  • Redlock Algorithm - Multi-node HA
  • PostgreSQL Advisory - Session/transaction
  • Redis Locks - Lua脚本、重试、续期
  • Redlock Algorithm - 多节点高可用
  • PostgreSQL Advisory - 会话/事务级锁

Capability Details

能力详情

redis-locks

redis-locks

Keywords: Redis, Lua, SET NX, atomic, TTL Solves: Fast distributed locks, atomic acquire/release, auto-expiry
关键词: Redis、Lua、SET NX、原子性、TTL 解决问题: 快速分布式锁、原子性获取/释放、自动过期

redlock

redlock

Keywords: Redlock, multi-node, quorum, HA, fault-tolerant Solves: High-availability locking, survive node failures
关键词: Redlock、多节点、法定人数、高可用、容错 解决问题: 高可用锁、节点故障时仍可正常工作

advisory-locks

advisory-locks

Keywords: PostgreSQL, advisory, pg_advisory_lock, session, transaction Solves: Lock with existing PG, ACID integration, no extra infra
关键词: PostgreSQL、advisory、pg_advisory_lock、会话、事务 解决问题: 基于现有PG实现锁、ACID集成、无需额外基础设施

leader-election

leader-election

Keywords: leader, election, singleton, coordinator Solves: Single active instance, coordinator pattern
关键词: leader、选举、单例、协调器 解决问题: 单活跃实例、协调器模式