每日Java面试场景题知识点之-分布式锁

一、分布式锁的应用场景

在高并发的企业级项目中,分布式锁是解决多个服务节点访问共享资源的重要技术手段。主要应用场景包括:

  1. 秒杀系统:防止超卖问题,确保库存扣减的原子性
  2. 订单处理:避免重复下单,保证订单号唯一性
  3. 缓存更新:防止缓存击穿,实现缓存的更新同步
  4. 定时任务:在分布式环境下防止任务重复执行
  5. 金融交易:确保转账等操作的原子性和一致性

二、常见的分布式锁实现方式

1. Redis分布式锁

实现原理: 利用Redis的SETNX命令实现,只有当key不存在时才能设置成功。

基础实现代码:

public boolean tryLock(String key, String value, long expireTime) {
    Boolean result = redisTemplate.opsForValue()
        .setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
    return Boolean.TRUE.equals(result);
}

进阶实现:使用Lua脚本保证原子性,避免锁释放时的竞态条件。

2. Zookeeper分布式锁

实现原理: 利用Zookeeper的临时顺序节点和Watch机制实现。

优势:

  • 可靠性高,基于Zookeeper的强一致性
  • 支持锁的可重入和公平锁
  • 自动释放,避免死锁

3. 数据库分布式锁

实现方式:

  • 乐观锁:基于版本号机制
  • 悲观锁:SELECT...FOR UPDATE

三、面试中常见的问题和解决方案

问题1:Redis分布式锁如何避免误删?

场景描述:线程A获取了锁,但由于业务执行时间过长,锁过期自动释放,此时线程B获取了锁,线程A执行完成后错误地释放了线程B的锁。

解决方案:

public void unlock(String key, String value) {
    String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
                   "then return redis.call('del', KEYS[1]) " +
                   "else return 0 end";
    redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), 
                         Collections.singletonList(key), value);
}

问题2:如何实现锁的可重入?

解决方案: 使用Hash结构存储锁信息,key为锁名,field为线程标识,value为重入次数。

public boolean reentrantLock(String key, String value, long expireTime) {
    String script = "if redis.call('exists', KEYS[1]) == 0 " +
                   "then redis.call('hset', KEYS[1], ARGV[1], 1); " +
                   "redis.call('expire', KEYS[1], ARGV[2]); " +
                   "return 1; " +
                   "end; " +
                   "if redis.call('hexists', KEYS[1], ARGV[1]) == 1 " +
                   "then redis.call('hincrby', KEYS[1], ARGV[1], 1); " +
                   "return 1; " +
                   "end; " +
                   "return 0;";
}

问题3:如何解决主从复制导致的锁丢失问题?

问题描述:Redis主从异步复制时,主节点故障可能导致锁丢失。

解决方案:

  • 使用Redis RedLock算法,在多个Redis实例上同时加锁
  • 使用Zookeeper替代Redis,利用其强一致性特性

问题4:如何优化分布式锁的性能?

优化策略:

  1. 减少锁的持有时间:将锁范围缩小到最小必要代码块
  2. 使用分段锁:对大量数据进行分片,不同数据使用不同锁
  3. 锁降级:在特定场景下使用本地锁替代分布式锁
  4. 连接池优化:合理配置Redis连接池参数

四、实战最佳实践

  1. 合理设置过期时间:根据业务执行时间动态调整
  2. 完善异常处理:确保锁在任何情况下都能正确释放
  3. 监控和报警:对锁的获取和释放进行监控
  4. 性能测试:在上线前进行充分的压力测试
  5. 降级方案:准备锁服务不可用时的备选方案

感谢读者观看,希望本文对您理解分布式锁有所帮助!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐