面试问题

自由港 / 2024-10-23 / 原文

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 做分布式锁。

image

接口优化

后台代码

  • 缓存机制
  • 并发调用
    比如有两个耗时操作,可以同时使用两个线程调用。
  • 同步接口异步化
  • 避免大事务
  • 优化日志

数据库

  • 数据库查询优化
    索引,查询必要的字段,避免深分页,表数据冗余数据,使用连接池管理链接,使用数据压缩技术

网络缓慢 防止用户重复下单

使用 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;