Java-分布式锁

1. 分布式锁概述

1.1 什么是分布式锁?

分布式锁是一种在分布式系统中实现资源互斥访问的机制,确保多个进程或线程在访问共享资源时不会发生冲突。其核心特性包括:

  • 互斥性:同一时刻只有一个客户端能持有锁。

  • 无死锁:即使持有锁的客户端崩溃,锁最终也会被释放。

  • 容错性:部分节点故障不影响锁的正常使用。

1.2 为什么需要分布式锁?

在分布式系统中,传统的单机锁(如Java的synchronizedReentrantLock)无法跨JVM生效。例如:

  • 电商库存扣减:防止超卖。

  • 订单处理:避免重复下单。

  • 定时任务调度:确保任务仅执行一次。

2. 分布式锁的实现方案

2.1 基于数据库的实现

2.1.1 乐观锁(CAS)
UPDATE inventory SET stock = stock - 1 
WHERE product_id = 100 AND stock >= 1;

缺点:高并发下大量失败重试。

2.1.2 悲观锁(SELECT FOR UPDATE)
@Transactional
public void deductStock(Long productId) {
    Inventory inventory = em.createQuery(
        "SELECT i FROM Inventory i WHERE i.productId = :pid FOR UPDATE", 
        Inventory.class)
        .setParameter("pid", productId)
        .getSingleResult();
    inventory.setStock(inventory.getStock() - 1);
}

缺点:数据库性能瓶颈。

2.2 基于Redis的实现

2.2.1 基础版(SETNX + EXPIRE)
public boolean tryLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
    String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
    return "OK".equals(result);
}

问题:非原子性操作可能导致死锁。

2.2.2 增强版(Lua脚本)
if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then
    return redis.call('pexpire', KEYS[1], ARGV[2])
else
    return 0
end

优点:保证原子性。

2.3 基于ZooKeeper的实现

public class ZkDistributedLock {
    private final InterProcessMutex mutex;
    
    public boolean tryLock(long time, TimeUnit unit) {
        return mutex.acquire(time, unit);
    }
}

特点:基于临时顺序节点,强一致但性能较低。


3. Redisson高级特性解析

3.1 看门狗机制

// 自动续期(默认30秒,每10秒续一次)
RLock lock = redisson.getLock("myLock");
lock.lock(); // 无需指定超时时间

源码逻辑

  1. 启动守护线程定期检查锁状态。

  2. 若客户端仍活跃,重置锁过期时间。

3.2 红锁(RedLock)算法

RLock lock1 = redisson.getLock("lock1");
RLock lock2 = redisson.getLock("lock2");
RLock lock3 = redisson.getLock("lock3");
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
redLock.lock();

流程

  1. 向N个独立Redis节点申请锁。

  2. 当多数节点(N/2+1)获取成功时,认为加锁成功。

4. 性能优化方案

4.1 锁分段技术

// 将库存ID哈希到16个分段
public RLock getSegmentLock(Long productId) {
    int segment = productId.hashCode() & 0xF;
    return redisson.getLock("stock_lock_" + segment);
}

效果:并发能力提升16倍。

4.2 热点数据优化

4.2.1 本地缓存+版本号
@Cacheable(value = "inventory", key = "#productId")
public Inventory getInventory(Long productId) {
    return inventoryRepo.findById(productId);
}
4.2.2 熔断降级
@HystrixCommand(fallbackMethod = "fallbackDeduct")
public void deductStock(Long productId) {
    // 尝试获取分布式锁
}

5. 生产环境监控

5.1 关键指标

指标名称计算方式报警阈值
锁等待时间获取锁结束时间-开始时间P99 > 500ms
锁持有时间释放锁时间-获取锁时间平均值 > 1s
锁竞争失败率失败次数/总尝试次数> 20%

5.2 Prometheus配置

- job_name: 'distributed_lock'
  metrics_path: '/actuator/prometheus'
  static_configs:
    - targets: ['lock-service:8080']

6. 选型建议

6.1 方案对比

方案一致性性能实现复杂度适用场景
Redis SETNX最终允许短暂不一致
Redisson中高金融交易
ZooKeeper配置管理
数据库行锁最低低并发事务

6.2 决策树

 

7. 未来演进

7.1 协程支持

suspend fun acquireLock() {
    while (!tryLock()) {
        delay(10) // 非阻塞挂起
    }
}

7.2 自动弹性扩缩

# 根据QPS动态调整锁分段数
def adjust_segments(current_qps):
    return max(16, math.ceil(current_qps / 1000))

附录:扩展阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值