MST

星途 面试题库

面试题:如何根据业务场景动态调整分布式系统中分布式锁的过期时间?

假设你负责一个电商抢购的分布式系统,在抢购开始前和抢购过程中,业务对锁的持有时间需求不同。请阐述如何设计一套机制,能够根据业务场景(比如抢购开始前预热阶段、抢购进行中不同阶段等)来动态地调整分布式锁的过期时间,同时保证系统的高并发性能和数据一致性。
48.9万 热度难度
后端开发分布式系统

知识考点

AI 面试

面试题答案

一键面试
  1. 设计思路
    • 基于配置中心:利用配置中心(如 Apollo、Nacos 等)来管理不同业务场景下分布式锁的过期时间配置。这样可以在不重启系统的情况下,动态修改过期时间。
    • 锁服务分层:将锁服务分为两层,外层为通用的分布式锁获取与释放逻辑,内层根据不同业务场景处理过期时间。
    • 事件驱动:通过事件机制来感知业务场景的切换,例如使用消息队列(如 Kafka)来传递场景切换事件。
  2. 具体实现
    • 配置管理
      • 在配置中心定义不同业务场景的锁过期时间配置项,例如:
        pre_sale_lock_expire_time = 60 # 抢购预热阶段锁过期时间(秒)
        sale_start_lock_expire_time = 10 # 抢购开始时锁过期时间(秒)
        sale_mid_lock_expire_time = 5 # 抢购进行中锁过期时间(秒)
        
    • 锁服务实现
      • 通用锁获取方法
public boolean acquireLock(String lockKey, long acquireTimeout, TimeUnit unit) {
    // 通用的分布式锁获取逻辑,如使用 Redis 实现
    Jedis jedis = jedisPool.getResource();
    String lockValue = UUID.randomUUID().toString();
    try {
        long result = jedis.setnx(lockKey, lockValue);
        if (result == 1) {
            return true;
        } else {
            long endTime = System.nanoTime() + unit.toNanos(acquireTimeout);
            while (System.nanoTime() < endTime) {
                result = jedis.setnx(lockKey, lockValue);
                if (result == 1) {
                    return true;
                }
                Thread.sleep(100);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        jedis.close();
    }
    return false;
}
  - **根据场景设置过期时间**:
public void setLockExpireTime(String lockKey, long expireTime, TimeUnit unit) {
    Jedis jedis = jedisPool.getResource();
    try {
        jedis.expire(lockKey, (int) unit.toSeconds(expireTime));
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        jedis.close();
    }
}
- **场景切换处理**:
  - **事件监听**:通过消息队列监听业务场景切换事件,例如:
@KafkaListener(topics = "scene_switch_topic", groupId = "lock_group")
public void handleSceneSwitch(String scene) {
    String lockKey = "product_sale_lock";
    if ("pre_sale".equals(scene)) {
        long expireTime = Long.parseLong(config.getProperty("pre_sale_lock_expire_time"));
        setLockExpireTime(lockKey, expireTime, TimeUnit.SECONDS);
    } else if ("sale_start".equals(scene)) {
        long expireTime = Long.parseLong(config.getProperty("sale_start_lock_expire_time"));
        setLockExpireTime(lockKey, expireTime, TimeUnit.SECONDS);
    } else if ("sale_mid".equals(scene)) {
        long expireTime = Long.parseLong(config.getProperty("sale_mid_lock_expire_time"));
        setLockExpireTime(lockKey, expireTime, TimeUnit.SECONDS);
    }
}
  1. 保证高并发性能和数据一致性
    • 高并发性能
      • 锁优化:使用乐观锁、分段锁等技术减少锁竞争。例如,在商品库存扣减时,可根据商品 ID 进行分段加锁,不同段商品可并行处理。
      • 缓存:在抢购前将商品库存等数据加载到缓存(如 Redis)中,减少数据库压力,提高响应速度。在锁获取成功后,先在缓存中进行库存扣减,再异步更新数据库。
    • 数据一致性
      • 分布式事务:使用分布式事务框架(如 Seata)来保证在锁操作、库存扣减、订单生成等一系列操作的原子性。
      • 日志记录:记录所有锁操作和业务操作日志,以便在出现问题时进行数据恢复和一致性校验。