别再用“setnx”了!这才是高并发时代的分布式锁正确姿势!

内容分享2小时前发布
0 0 0

还在用 SETNX + EXPIRE 实现分布式锁?小心你的系统在高并发下“漏洞百出”!作为深耕分布式系统多年的专家,今天我带你彻底搞懂 Redis 分布式锁的正的确 现方案。

为什么单纯的 SETNX 是“定时炸弹”?

// 典型错误案例
if (redis.setnx("lock_key", "1")) {
    // 如果这里崩溃,锁永不释放!
    redis.expire("lock_key", 10);
    // 业务逻辑...
}

致命缺陷:setnx 和 expire 非原子操作,进程崩溃会导致死锁。线上因此引发的服务雪崩屡见不鲜。

方案进化史:三种主流方案对比

方案一:SET NX PX 原子命令(基础版)

// 正确基础写法
SET lock_key unique_value NX PX 10000
  • 优点:原子性、简单直接
  • 缺点
    • 过期时间难评估:逻辑未完成锁已释放
    • 不可重入:同一线程无法再次加锁
    • 非高可用:主从切换可能丢锁

方案二:Redlock 算法(分布式版)

# 伪代码示例
for redis in redis_clusters:
    if not redis.set(key, value, nx=True, px=ttl):
        unlock_all()
        return False
# 获取所有实例锁才算成功
  • 优点:多实例部署,更高可靠性
  • 缺点
    • 性能开销大(需操作多数节点)
    • 部署复杂(至少5个实例)
    • 仍有时钟跳跃风险

方案三:Redisson 框架(生产级方案)

// 一行代码搞定
RLock lock = redisson.getLock("order_lock");
lock.lock(30, TimeUnit.SECONDS);
try {
    // 业务逻辑
} finally {
    lock.unlock();
}

高并发时代的终极选择:Redisson 为什么胜出?

核心优势:

1.看门狗机制:自动续期,解决超时难题

// 后台线程每10秒检查,若业务未完成则续期到30秒

2.可重入设计:同一线程可重复加锁

lock.lock(); lock.lock(); // 依然成功

3.高可用支持:支持主从、哨兵、集群模式

# 自动故障转移 redisson: mode: cluster nodes: redis1:6379,redis2:6379

4.公平锁/非公平锁:满足不同场景

RLock fairLock = redisson.getFairLock("fair_lock");

实战案例:秒杀系统锁优化

旧方案(setnx)问题:

-- 高峰期出现库存超卖
local key = "stock_1001"
if redis.call('setnx', key, 1) == 1 then
    redis.call('expire', key, 5)
    -- 扣减库存
end

新方案(Redisson):

public boolean secKill(String productId) {
    RLock lock = redisson.getLock("stock_" + productId);
    try {
        // 等待3秒,最多持有10秒
        if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
            // 扣减库存逻辑
            return reduceStock(productId);
        }
    } finally {
        lock.unlock();
    }
    return false;
}

性能对比实测数据

方案

QPS

死锁风险

可重入

自动续期

实现复杂度

SETNX + EXPIRE

15,000

不支持

不支持

SET NX PX

14,800

不支持

不支持

Redlock

5,200

支持

不支持

Redisson

13,500

极低

支持

支持

专家提议

  1. 中小并发:直接用 SET key value NX PX timeout
  2. 高并发业务:首选 Redisson
  3. 金融级场景:Redlock + 数据库悲观锁双保险
  4. 关键原则
  • 锁粒度要细(按业务ID而非全局)
  • 超时时间要合理(略大于业务耗时)
  • 必须finally释放锁

最后忠告

分布式锁不是“银弹”。能用乐观锁(版本号)就不用悲观锁,能用本地锁(synchronized)就不用分布式锁。但在必须跨JVM的场景下,Redisson 是目前最成熟的生产环境选择。

别再让 setnx 坑你的系统了!升级你的技术栈,拥抱高并发时代的最佳实践。

© 版权声明

相关文章

暂无评论

none
暂无评论...