Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← Web 开发 / Web Development

中间件 / Middleware

1. Web 中间件全景 / The Web Middleware Landscape

2. 中间件——流量洪峰下的系统保护 / Middleware for Protecting Systems Under Traffic Spikes

cache layer

1. 缓存架构全景 / Cache Architecture Overview

2. Redis 深入——为什么你的缓存总是出问题 / Redis Internals and Cache Failure Modes

3. Redis 数据结构场景应用——什么时候用什么 / Choosing Redis Data Structures for Real Applications

4. 缓存策略——库存变了,缓存怎么处理 / Cache Strategies and Inventory Consistency

5. Redis 缓存三剑客——穿透/击穿/雪崩 + 一致性策略 / Redis Cache Penetration, Breakdown, Avalanche, and Consistency

6. Redis 分布式锁——从 SETNX 到 Redisson / Redis Distributed Locks from SETNX to Redisson

7. Redis Cluster 与 Sentinel 高可用架构 / Redis Cluster and Sentinel High-Availability Architecture

8. Redis 高级特性——Stream / PubSub / Module / LLM 应用

9. Redis 架构深度分析——为什么 Redis 能这么快 / Redis Architecture and the Sources of Its Performance

10. Redis 全景——为什么你的系统需要一个缓存层 / The Redis Landscape and Why Systems Need a Cache Layer

message queue

1. 消息队列全景——为什么你的系统需要一个中间人 / Message Queue Overview and Why Your System Needs a Middleman

2. Kafka 核心——为什么你的消息总是"丢"了 / Kafka Fundamentals and Message Delivery Semantics

3. 消息队列高级——死信队列、延迟消息、消息积压 / Advanced Messaging with Dead Letters, Delays, and Backlogs

4. Kafka Streams 与 Connect —— 让数据自己流动起来 / Kafka Streams and Connect for Streaming Data Pipelines

5. RabbitMQ 深度解析 —— 灵活路由与消息可靠性 / RabbitMQ Deep Dive into Flexible Routing and Reliability

6. 消息队列对比——为什么最终选了 Kafka / Comparing Message Queues and Choosing Kafka

search engine

1. 搜索引擎知识体系 / Search Engine Knowledge System

2. Elasticsearch——为什么 Like 查询总是那么慢 / Elasticsearch for Full-Text Search at Scale

3. Elasticsearch 查询 DSL 深入——为什么你的搜索总是不准 / Elasticsearch Query DSL Deep Dive

4. Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations

5. Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives

infrastructure

1. 基础设施组件全景 / Infrastructure Components Landscape

2. Nginx 与反向代理 / Nginx and Reverse Proxy

3. 服务发现 / Service Discovery

4. 配置中心 / Configuration Center

本页目录

Redis 分布式锁——从 SETNX 到 Redisson / Redis Distributed Locks from SETNX to Redisson ​

📅 创建时间:2026-06-02 🏷️ 标签:#Redis #分布式锁 #SETNX #Redisson #RedLock #Watchdog #Lua脚本 📚 前置知识:[[00-redis-overview]](Redis 全景) [[01-redis-architecture]](架构分析) [[03-redis-cache-patterns]](缓存三剑客) 📚 相关知识:[[/03-web/05-backend-engineering/04-distributed-system]](分布式锁原理) [[/03-web/07-middleware/01-redis-deep]](已有分布式锁内容) [[/03-web/05-backend-engineering/08-concurrency]](并发编程)


场景:10 万人同时抢 100 部手机,怎么保证不超卖 ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  秒杀场景:10 万人同时抢 100 部手机。                     │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐ │
│  │  方案 A:数据库乐观锁(行锁)                      │ │
│  │  UPDATE products SET stock = stock - 1              │ │
│  │  WHERE id = 1 AND stock > 0;                       │ │
│  │                                                      │ │
│  │  问题:10 万 QPS 同时打 MySQL                      │ │
│  │  → 事务排队 → 数据库连接耗尽 → 系统崩溃           │ │
│  └─────────────────────────────────────────────────────┘ │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐ │
│  │  方案 B:Redis 分布式锁                           │ │
│  │  SET lock:product:1 unique_id NX EX 30           │ │
│  │                                                      │ │
│  │  → 抢到锁的人去买手机 → 买完释放锁               │ │
│  │  → 没抢到锁的人直接返回"已售罄"               │ │
│  │  → 只有极少数人进数据库,扛住 10 万 QPS          │ │
│  └─────────────────────────────────────────────────────┘ │
│                                                             │
│  分布式锁是 Redis 最强大的武器之一。                       │
│  但用错了,比不用还危险。                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

第1节:分布式锁的四大核心问题 ​

问题全景图 ​

┌─────────────────────────────────────────────────────────────┐
│                 分布式锁的四大灵魂拷问                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题 1:怎么获取锁?                                       │
│  → 多进程同时抢,谁先抢到算谁的                         │
│                                                             │
│  问题 2:怎么释放锁?                                       │
│  → 别人持有锁时不能删,删了别人的锁怎么办               │
│                                                             │
│  问题 3:锁过期了但业务还没跑完?                          │
│  → 自动续期(Watchdog)                                   │
│                                                             │
│  问题 4:同一进程需要多次获取锁?                          │
│  → 可重入锁                                              │
│                                                             │
│  任何一个问题没处理好,都会导致锁失效。                     │
│  这就是分布式锁"看起来简单,用起来处处是坑"的原因。       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

灵魂拷问一:怎么获取锁 ​

┌─────────────────────────────────────────────────────────────┐
│                 获取锁的正确姿势                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ❌ 错误做法:先 SET 再 EXPIRE(两步骤,有竞态)         │
│                                                             │
│  r.set("lock", "123")    # 步骤1:设值                  │
│  r.expire("lock", 30)    # 步骤2:设过期                 │
│                                                             │
│  问题:如果步骤1和2之间进程崩溃了                        │
│  → 锁没有过期时间 → 永远不过期 → 死锁!                 │
│                                                             │
│  ✅ 正确做法:SET NX EX(单指令,原子性)                │
│                                                             │
│  r.set("lock:product:1", lock_id, nx=True, ex=30)       │
│                                                             │
│  nx=True:key 不存在才设置(原子性保证)                  │
│  ex=30:30 秒后自动过期(防止死锁)                      │
│                                                             │
│  为什么 value 要用唯一 ID(UUID)?                        │
│  → 用于释放锁时验证"只有持有者才能释放"                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

灵魂拷问二:怎么释放锁 ​

┌─────────────────────────────────────────────────────────────┐
│                 释放锁的正确姿势                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ❌ 错误做法:直接 DEL 删除锁                             │
│                                                             │
│  r.delete("lock:product:1")                               │
│                                                             │
│  问题场景:                                               │
│  T1: 进程 A 获取锁(lock_id="A-uuid")                  │
│  T2: 进程 A 开始执行任务...                               │
│  T3: 任务太慢,锁自动过期了                              │
│  T4: 进程 B 获取了同一把锁(lock_id="B-uuid")          │
│  T5: 进程 A 任务执行完毕,执行 DEL(删掉了 B 的锁!)   │
│  T6: 进程 C 获取了同一把锁(lock_id="C-uuid")          │
│  T7: 进程 B 和 C 同时在执行同一个任务 → 并发问题!       │
│                                                             │
│  ✅ 正确做法:Lua 脚本,只删除自己的锁                    │
│                                                             │
│  lua = """                                                │
│  if redis.call('get', KEYS[1]) == ARGV[1] then            │
│      return redis.call('del', KEYS[1])                    │
│  else                                                     │
│      return 0                                             │
│  end                                                      │
│  """                                                       │
│  r.eval(lua, 1, "lock:product:1", "A-uuid")              │
│                                                             │
│  T5: 进程 A 执行 Lua → GET 发现不是自己的 uuid → 不删    │
│  → 进程 B 的锁安全 ✅                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

灵魂拷问三:锁过期了但业务没跑完 ​

┌─────────────────────────────────────────────────────────────┐
│                 锁续期(Watchdog)问题                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  问题场景:                                               │
│  T1: 进程 A 获取锁(30 秒过期)                          │
│  T2: 进程 A 开始执行任务(预计 60 秒)                  │
│  T3: T1+30s,锁自动过期了                                │
│  T4: 进程 B 获取了同一把锁                                │
│  T5: 进程 A 和 B 同时在执行 → 并发问题!                  │
│                                                             │
│  解法:锁续期(看门狗机制)                               │
│                                                             │
│  Redisson 的 Watchdog:                                   │
│  • 锁持有后,后台线程每 10 秒检查一次                    │
│  • 如果持有者还在运行,自动续期 30 秒                   │
│  • 只有主动释放锁或进程崩溃时才真正释放                   │
│                                                             │
│  lua = """                                                │
│  if redis.call('get', KEYS[1]) == ARGV[1] then           │
│      return redis.call('expire', KEYS[1], ARGV[2])       │
│  else                                                     │
│      return 0                                             │
│  end                                                      │
│  """                                                       │
│  # 续期:将过期时间重置为 30 秒                          │
│  r.eval(lua, 1, lock_key, lock_id, 30)                   │
│                                                             │
│  ⚠️ 注意:如果你不用 Redisson,手动续期需要额外线程。     │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

灵魂拷问四:可重入锁 ​

┌─────────────────────────────────────────────────────────────┐
│                 可重入锁——同一进程多次获取                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  场景:方法 A 获取锁 → 调用方法 B,方法 B 也要获取同一把锁 │
│                                                             │
│  普通锁:同一进程两次 acquire → 死锁(自己等自己释放)   │
│  可重入锁:同一进程可以多次获取,只有计数归零才真正释放   │
│                                                             │
│  实现思路:用 Hash 存 {lock_id: 重入计数}                 │
│                                                             │
│  lua_acquire = """                                        │
│  local key = KEYS[1]                                      │
│  local id = ARGV[1]                                       │
│  local ttl = ARGV[2]                                      │
│                                                             │
│  -- 如果锁不存在,初始化                                   │
│  if redis.call('exists', key) == 0 then                  │
│      redis.call('hset', key, id, 1)                       │
│      redis.call('expire', key, ttl)                       │
│      return 1                                             │
│  end                                                      │
│                                                             │
│  -- 如果是自己持有的锁,重入计数 +1                       │
│  if redis.call('hget', key, id) then                     │
│      redis.call('hincrby', key, id, 1)                    │
│      redis.call('expire', key, ttl)                       │
│      return 1                                             │
│  end                                                      │
│                                                             │
│  return 0                                                 │
│  """                                                       │
│                                                             │
│  lua_release = """                                        │
│  local key = KEYS[1]                                       │
│  local id = ARGV[1]                                       │
│                                                             │
│  if redis.call('hget', key, id) then                      │
│      local cnt = redis.call('hincrby', key, id, -1)       │
│      if cnt <= 0 then                                     │
│          redis.call('del', key)                           │
│      end                                                  │
│      return 1                                             │
│  end                                                      │
│  return 0                                                 │
│  """                                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

第2节:分布式锁完整实现 ​

从零实现一个分布式锁 ​

python
import redis
import uuid
import time
import threading
import json

class RedisLock:
    def __init__(self, redis_client, key, timeout=30, blocking=True, blocking_timeout=10):
        self.redis = redis_client
        self.key = f"lock:{key}"
        self.timeout = timeout
        self.blocking = blocking
        self.blocking_timeout = blocking_timeout
        self.lock_id = str(uuid.uuid4())
        self.acquired = False
        self._renew_timer = None

    def acquire(self):
        """尝试获取锁"""
        end = time.time() + self.blocking_timeout
        while time.time() < end:
            # SET NX EX:原子获取锁
            if self.redis.set(self.key, self.lock_id, nx=True, ex=self.timeout):
                self.acquired = True
                # 开启 watchdog 续期
                self._start_watchdog()
                return True

            if not self.blocking:
                return False
            time.sleep(0.01)  # 10ms 重试

        return False

    def release(self):
        """释放锁(只释放自己持有的)"""
        if not self.acquired:
            return
        self._stop_watchdog()
        lua = """
        if redis.call('get', KEYS[1]) == ARGV[1] then
            return redis.call('del', KEYS[1])
        else
            return 0
        end
        """
        self.redis.eval(lua, 1, self.key, self.lock_id)
        self.acquired = False

    def _start_watchdog(self):
        """后台线程每 timeout/3 秒自动续期"""
        def renew():
            while self.acquired:
                time.sleep(self.timeout / 3)
                if self.acquired:
                    lua = """
                    if redis.call('get', KEYS[1]) == ARGV[1] then
                        return redis.call('expire', KEYS[1], ARGV[2])
                    else
                        return 0
                    end
                    """
                    self.redis.eval(lua, 1, self.key, self.lock_id, self.timeout)

        self._renew_timer = threading.Thread(target=renew, daemon=True)
        self._renew_timer.start()

    def _stop_watchdog(self):
        self.acquired = False

    def __enter__(self):
        self.acquire()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.release()
        return False


# 使用方式
def seckill(product_id):
    lock = RedisLock(r, f"product:{product_id}", timeout=30, blocking_timeout=5)
    if lock.acquire():
        try:
            stock = r.get(f"stock:{product_id}")
            if stock and int(stock) > 0:
                r.decr(f"stock:{product_id}")
                create_order(product_id)
        finally:
            lock.release()
    else:
        return "已售罄"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

Redisson 的封装——开箱即用 ​

java
import org.redisson.Redisson;
import org.redisson.api.RLock;

RedissonClient redisson = Redisson.create();

// 获取锁
RLock lock = redisson.getLock("order:123");

try {
    // 尝试获取(等 10 秒,锁自动 30 秒过期)
    boolean acquired = lock.tryLock(10, 30, TimeUnit.SECONDS);
    if (acquired) {
        // 执行业务逻辑
        processOrder(123);
    }
} finally {
    // 释放锁(自动处理 watchdog 续期)
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}

// Redisson 的优势:
// 1. Watchdog 自动续期(后台线程每 10 秒检查一次)
// 2. 可重入锁(同一线程多次获取)
// 3. 公平锁(按请求顺序排队)
// 4. 读写锁(读读不互斥,读写/写写互斥)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

第3节:RedLock——多节点多数派共识 ​

为什么需要 RedLock ​

┌─────────────────────────────────────────────────────────────┐
│                 普通分布式锁的致命弱点                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  单机 Redis + 主从复制:                                   │
│                                                             │
│  T1: 进程 A 从 Master 获取锁(lock_id="A")              │
│  T2: Master 把命令同步给 Slave(异步,有延迟)            │
│  T3: Master 宕机,Slave 升主(锁数据还没同步过来!)      │
│  T4: 进程 B 从新 Master 获取同一把锁(成功了!)          │
│  T5: 进程 A 和 B 同时在执行 → 并发问题!                  │
│                                                             │
│  核心问题:                                              │
│  主从异步复制 → 主挂了可能丢锁                           │
│                                                             │
│  解法:RedLock——多台 Redis 独立获取锁,多数派胜出        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

RedLock 算法 ​

┌─────────────────────────────────────────────────────────────┐
│                 RedLock 算法流程                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  假设有 5 台 Redis 节点(N=5):                          │
│                                                             │
│  1. 获取当前时间 T1(毫秒级)                             │
│                                                             │
│  2. 依次向 5 台 Redis 请求获取锁:                       │
│     for i in [1, 2, 3, 4, 5]:                          │
│         r.set(lock_key, lock_id, nx=True, ex=30)          │
│     记录每台响应时间                                       │
│                                                             │
│  3. 计算锁的有效时间:                                    │
│     valid_time = 30 - (T2 - T1) - 时钟偏移               │
│     → 如果获取了 ≥3 台,且 valid_time > 0 → 锁有效    │
│                                                             │
│  4. 如果锁有效:                                          │
│     → 实际有效时间 = valid_time                         │
│     → 执行任务                                             │
│                                                             │
│  5. 任务完成后,向所有节点释放锁:                        │
│     for i in [1, 2, 3, 4, 5]:                          │
│         r.eval(release_lua)                              │
│                                                             │
│  6. 如果获取的节点 < 3:                                  │
│     → 释放所有已获取的锁                                   │
│     → 锁获取失败                                          │
│                                                             │
│  为什么至少 3 台?                                         │
│  → 允许 2 台宕机,剩下 3 台 多数派胜出                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

RedLock 的争议和局限性 ​

┌─────────────────────────────────────────────────────────────┐
│                 RedLock 的争议和适用边界                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  争议点(Martin Kleppmann 等人 vs Antirez):             │
│                                                             │
│  1. 时钟偏移问题:                                        │
│  5 台机器时钟不同步,可能导致有效时间计算错误             │
│  → RedLock 认为时钟偏移可忽略,争议方认为这是隐患        │
│                                                             │
│  2. 持锁期间逻辑复杂:                                   │
│  如果 GC(垃圾回收)导致进程暂停,锁可能已过期           │
│  → GC 安全点/STW 可能超过锁的有效时间                    │
│                                                             │
│  适用边界:                                               │
│  • 不需要强一致性的场景 → 单机 Redis + 主从足够          │
│  • 需要高可用且容忍短暂不一致 → RedLock                  │
│  • 强一致性(金融场景)→ Zookeeper / etcd                │
│                                                             │
│  一句话:RedLock 不是银弹,它的正确性有争议。             │
│  对于大多数业务场景,单机 Redis + 主从 + watchdog 就够了。 │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第4节:常见踩坑指南 ​

┌─────────────────────────────────────────────────────────────┐
│                 分布式锁十大踩坑清单                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  坑 1:锁的粒度设错了                                     │
│  ❌ SET lock order:* NX EX 30                            │
│     → 所有订单共用一把锁 → 并发全变串行                   │
│  ✅ SET lock order:123 NX EX 30                          │
│     → 按具体资源加锁,只锁冲突的部分                      │
│                                                             │
│  坑 2:锁的 TTL 设太短                                    │
│  ❌ 任务要 60 秒,但锁只设了 30 秒                      │
│  ✅ 评估任务耗时 + 留 buffer;或用 watchdog 自动续期      │
│                                                             │
│  坑 3:业务代码写在 finally 外面                          │
│  ❌ if lock.acquire(): process(); lock.release()         │
│  ✅ try: lock.acquire(); process(); finally: lock.release()│
│                                                             │
│  坑 4:用 SETNX 做锁,但没验证返回值                      │
│  ❌ r.setnx("lock", "id") → 没判断是否成功就执行业务   │
│  ✅ if r.set("lock", "id", nx=True, ex=30): process()  │
│                                                             │
│  坑 5:释放锁时没检查是否是自己的                         │
│  ❌ r.delete("lock")                                      │
│  ✅ 用 Lua 脚本验证 lock_id 后再删除                      │
│                                                             │
│  坑 6:主从切换丢锁                                       │
│  ❌ 单机 Redis + 主从 → Master 挂了可能丢锁              │
│  ✅ 对一致性要求高 → RedLock 或换 etcd/Zookeeper         │
│                                                             │
│  坑 7:用 redis-py 的 lock() 对象,但忘了加 timeout      │
│  ❌ lock = redis.lock("lock") → 没设 blocking_timeout   │
│  ✅ lock = redis.lock("lock", timeout=30, blocking_timeout=10)│
│                                                             │
│  坑 8:锁等待时用了 sleep 而不是事件驱动                   │
│  ❌ while not lock: time.sleep(0.1)                      │
│  ✅ 使用 redis-py 的 blocking=True 参数,不占用 CPU        │
│                                                             │
│  坑 9:分布式锁 + 数据库事务混用                          │
│  ❌ 获取锁 → 开启 DB 事务 → 提交事务 → 释放锁           │
│  → 如果 DB 事务卡住,锁也卡住,最后过期 → 并发问题       │
│  ✅ 获取锁 → 执行 DB 操作 → 释放锁 → 事务在锁内完成      │
│                                                             │
│  坑 10:集群 slot 迁移时抢锁                              │
│  ❌ Cluster 迁移期间,同一 key 可能同时在两个节点存在    │
│  ✅ 使用 Redisson 的 RClusteredRedissonClient             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

升华:分布式锁不是万能的 ​

┌─────────────────────────────────────────────────────────────┐
│              什么时候用分布式锁,什么时候不用                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用分布式锁的场景:                                       │
│  ✅ 秒杀扣库存(减少数据库压力)                        │
│  ✅ 防止重复下单(幂等性保证)                         │
│  ✅ 任务调度(同一时刻只有一个节点执行)                │
│  ✅ 分布式事务的前置锁(准备阶段)                     │
│                                                             │
│  不用分布式锁的场景:                                      │
│  ❌ 数据一致性要求极高 → 换数据库行锁或 Zookeeper       │
│  ❌ 只需要限制并发数 → 用信号量(Semaphore)            │
│  ❌ 高频短任务 → 锁竞争激烈 → 考虑消息队列削峰        │
│                                                             │
│  一句话:                                               │
│  分布式锁是"让多进程串行执行某一小段代码"的工具。       │
│  锁的粒度要尽量小,持有时间要尽量短。                   │
│  如果你的业务需要长时间持有锁,可能设计本身有问题。       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

"AI 可查 vs 必须理解"清单 ​

AI 可查:
✅ Redisson 各语言的 API 用法
✅ RedLock 算法的具体实现代码
✅ 各语言的 Redis 锁封装库(redisson-py / jedis-lock / redlock-py)
✅ Lua 脚本的语法和调试方法

必须理解:
🔴 SET NX EX 为什么比 SET + EXPIRE 更安全(原子性)
🔴 释放锁时为什么不能用 DEL 而要用 Lua 脚本验证
🔴 Watchdog 自动续期的原理和必要性
🔴 可重入锁的实现思路(Hash + 重入计数)
🔴 RedLock 的适用场景和局限性(不是银弹)
🔴 分布式锁的常见十大踩坑(特别是锁粒度和 TTL 设计)
1
2
3
4
5
6
7
8
9
10
11
12
13

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇5. Redis 缓存三剑客——穿透/击穿/雪崩 + 一致性策略 / Redis Cache Penetration, Breakdown, Avalanche, and Consistency
下一篇7. Redis Cluster 与 Sentinel 高可用架构 / Redis Cluster and Sentinel High-Availability Architecture

持续记录,持续成长

Copyright © Tidenflow