当前位置: 首页 > news >正文

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 thenreturn redis.call('pexpire', KEYS[1], ARGV[2])
elsereturn 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))

附录:扩展阅读

  • Redis分布式锁官方建议

  • Redisson源码分析

  • CAP理论实践指南

http://www.dtcms.com/a/303161.html

相关文章:

  • Lakehouse: Unifying DW Advanced Analytics in Open Platforms
  • 【C语言网络编程基础】TCP并发网络编程:io多路复用
  • 开源赋能产业,生态共筑未来 | 开源科学计算与系统建模(openSCS)分论坛圆满举行
  • 笔试——Day21
  • JS面试题
  • Linux 远程连接与文件传输:从基础到高级配置
  • QT之QThread 与 QtConcurrent
  • 【自动化运维神器Ansible】Ansible常用模块之cron模块详解
  • GaussDB as的用法
  • 【GaussDB】内存资源告急:深度诊断一起“memory temporarily unavailable“故障
  • DMETL安装流程及简单使用
  • OpenLayers 入门指南【四】:项目初始化
  • Qt小组件 - 8 图片浏览器
  • MySQL高级配置与优化实战指南
  • 利用 SQL Server 实现字符替换的高效函数
  • 第二十一天(shell练习)
  • IT运维的365天--033 跨交换机部署没有单独供电口的爱快AP到另一个地方去
  • 如何选择适合高并发环境的服务器:性能与稳定性的平衡
  • 短剧小程序系统开发:连接创作者与用户的桥梁
  • Node.js + TypeScript 开发健壮的淘宝商品 API SDK
  • 2025年07月23日秋瑶传媒一面
  • 【学习路线】AI开发工程师成长指南:从机器学习基础到大模型应用
  • 调色总监的“色彩炼金术”:在PS中创建LUT,并应用于Premiere Pro视频
  • TCP/IP 网际层详解
  • RCLAMP2574N.TCT Semtech:超低钳位TVS二极管 0.5pF超低电容+±30kV超强防护
  • 【Blender小技巧】Blender使用多边形建形工具创建多边形模型,挤出面,模型创建修改编辑UV贴图
  • PostgreSQL 与 MySQL 时间类型避坑指南
  • 《Ai智能眼镜的市场定义及用户分析》- 深圳市天趣星空科技有限公司 CEO 王洁
  • Java字符串详解
  • Entity Framework Core (EF Core) 使用ado.net