面试问题
1.防止订单重复提交
使用 redis 分布式锁来实现,可以使用用户ID,加购物车的商品ID,使用 MD5算法,得出一个key 作为分布式锁的key。解决问题的关键是 保持分布式锁的 key 的唯一性。
2. 缓存击穿
如果用户查的ID数据库没有值,那么缓存就击穿了,解决办法,如果数据库没有值,也给他缓存一个空值,第二次 在访问的时候,就直接给他返回null
private String Empty="-1";
public Product getProduct(String productId){
Object obj= cache.get(productId);
if(obj!=null){
if(obj instantOf(Product.class)){
return (Product)obj;
}
if(Empty.equals(obj)){
return null
}
}
Product p=dao.get(productId);
if(p!=null){
cache.put(productId,p);
}
else{
cache.put(productId,Empty);
}
return p;
}
这个方法有个问题,如果大量的 空存在会 损耗 内存,那么空缓存可以设置一个缓存过期时间,过一段时间缓存就会被清理掉。
还可以使用布隆过滤器。
- 热点数据访问。
//双重检测锁
Product getProduct(String productId){
Object obj= cache.get(productId);
if(obj!=null){
if(obj instantOf(Product.class)){
return (Product)obj;
}
if(Empty.equals(obj)){
return null
}
}
synchronized(this){
Object obj= cache.get(productId);
if(obj!=null){
if(obj instantOf(Product.class)){
return (Product)obj;
}
if(Empty.equals(obj)){
return null
}
}
Product p=dao.get(productId);
if(p!=null){
cache.put(productId,p);
}
else{
cache.put(productId,Empty,60000);
}
}
return p;
}
synchronized 性能提升
synchronized 锁定时,需要注意锁的对象。
如果在 spring 使用
// 这个代码会锁定当前控制器的实例对象,因为控制器实例是单例对象,因此效率不高。
synchronized(this){
}
性能提升
CurrentHashMap map=new CurrentHashMap();
public void save(String userId){
//产生锁对象
Object o=map.computeIfAbsent(userId,o->new Object());
//这样就每个用户ID就持有有一把锁。
synchronized(o){
}
}
分布式锁
使用redisson 做分布式锁。

接口优化
后台代码
- 缓存机制
- 并发调用
比如有两个耗时操作,可以同时使用两个线程调用。 - 同步接口异步化
- 避免大事务
- 优化日志
数据库
- 数据库查询优化
索引,查询必要的字段,避免深分页,表数据冗余数据,使用连接池管理链接,使用数据压缩技术
网络缓慢 防止用户重复下单
使用 redis 的 setnx,关键是在于key 的选择,比如用户TOKEN和商品的KEY,可以使用MD5将KEY变短。
如何查看线程死锁
- 使用jstack 命名
- 数据库死锁
1.查询是否锁表
show open tables where in_use>0
2. 查询进程
show processlist
3.查询在锁的事务
select * from INFORMATION_SCHEMA.INNODB_LOCKS;
4.查询等待锁的事务
select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;