面试题答案
一键面试性能瓶颈方面
- 网络延迟:微服务分布在不同节点,获取和释放锁时的网络通信延迟,可能导致锁操作响应缓慢。例如,服务A在上海,服务B在深圳,跨地域获取锁可能因网络距离产生延迟。
- 锁竞争:高并发下大量请求同时竞争全局锁,会使等待队列变长,增加锁获取等待时间。比如电商秒杀场景,众多用户同时请求购买商品,竞争库存锁。
- 存储瓶颈:若全局锁基于数据库、Redis等存储,高并发时存储的读写性能可能成为瓶颈。例如数据库频繁进行锁的读写操作,可能出现I/O瓶颈。
- 序列化与反序列化:在微服务间传递锁相关信息(如使用JSON序列化锁对象),高并发下序列化和反序列化操作也会消耗性能。
设计与优化保证高可用性与高性能
- 选择合适的锁存储:
- Redis:利用其单线程、高性能的特点,通过SETNX命令实现简单分布式锁。例如:
Jedis jedis = new Jedis("localhost");
String lockKey = "product:1:lock";
String requestId = UUID.randomUUID().toString();
boolean success = jedis.set(lockKey, requestId, "NX", "EX", 10);
if (success) {
// 获取锁成功,执行业务逻辑
try {
// 业务代码
} finally {
// 释放锁
if (requestId.equals(jedis.get(lockKey))) {
jedis.del(lockKey);
}
}
}
- **Zookeeper**:利用其树形结构和Watcher机制实现分布式锁。Zookeeper的节点具有顺序性,每个请求创建临时顺序节点,通过比较节点顺序获取锁。例如,服务启动时在`/locks/product`节点下创建临时顺序节点,最小序号的节点获取锁,当锁释放时,Watcher通知下一个节点获取锁。
2. 锁优化策略: - 减少锁粒度:将大锁拆分为多个小锁。比如电商库存系统,对不同商品分类分别设置锁,而不是对整个库存设置一把大锁,减少锁竞争范围。 - 锁续约:对于执行时间较长的任务,避免锁过期导致业务异常,可以在持有锁期间进行锁续约。例如在Redis中,通过定时任务延长锁的过期时间。 3. 高可用设计: - 多实例部署:对存储锁的中间件(如Redis集群、Zookeeper集群)进行多实例部署,避免单点故障。 - 故障转移:当主节点出现故障时,从节点能快速接管。例如Redis Sentinel模式,当主节点挂掉,Sentinel能选举出新的主节点,保证锁服务的可用性。