欢迎点击头像进入主页查看更多内容....
根据场景来用合适的技术,那真是再合适不过了,学了就得用么,不会咱再学,没场景实在难有用武之地,在实战中摸索异常是比demo更有效果的,与其坐学厚厚的.....怎么t里t气的图片。
我们从哪入手呢?不直接从场景入手,我们从理论入手,如何解决缓存穿透问题?
什么是缓存穿透?
去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
如何解决缓存穿透问题?
1.利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
2.采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
3.提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。
缓存预热 vs 缓存热备
缓存热备即当一台服务器不可用时能实时切换到备用缓存服务器,不影响缓存使用。集群模式下,每个主节点都会有一个或多个从节点来当备用,一旦主节点挂掉,从节点立即充当主节点使用。
应用场景
对于一些固定不变模板类,基础类等信息,但在流程中需要时刻查询的,比如机票起始地点,北京飞上海你永远是固定的航线内的公里数,比如地点是不会变的,期间的公里数完全可以预先缓存。但缓存期限和数据量需要考虑效率问题。缓存数据如果因为集群宕掉,应不影响数据。
对了到了这里不得不提一句redis find hot key还有没有印象,京东开源的热点数据缓存接口,这个大家有兴趣可以了解一下。
代码
@DependsOn+@Component
@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中,因为缓存预热这是必须的。
//可以作用在方法和类上。
//当作用在类上时,通常会与@Component及其衍生注解等注解配合使用。
//当作用在方法上时,通常会与@Bean注解配合使用。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
//要依赖的bean id,是个数组,也就是说可以依赖多个bean。
//效果是该注解作用的bean会比value设置的依赖bean晚实例化到容器中。
String[] value() default {};
}
@Component
public class CacheEventSource {
public CacheEventSource(){
System.out.println("缓存事件驱动...");
}
}
@Component
public class EventListenerSource {
public EventListenerSource(){
System.out.println("监听事件驱动...");
}
}
使用DependsOn注解
@Component
@DependsOn(value = {"eventListenerSource"})
public class CacheEventSource {
public CacheEventSource(){
System.out.println("缓存事件驱动...");
}
}
@Slf4j
@DependsOn(value = {"RedisService"})
@Component
public class RedisDataInitializeRunner implements ApplicationRunner {
RedisLock lock = RedisLock.getLolck(Enum.OrderNoPlanDate);
boolean isLock = lock.tryLock(RedisKeyConstants.ROUTE_CUSTOMER_FEE);
if(isLock){
try {
String key = RedisKeyConstants.ROUTE_CUSTOMER_FEE;
if (redisProvider.exists(key)){
lock.unlock();
}
} catch (Exception e) {
} finally {
// 释放锁
lock.unlock();
}
else{
//dosomthing
}
}
另外针对一些活动、大促场景需要对缓存数据进行预热。所以需要设计一套通用的预热系统。所谓预热,其实就是提前请求数据,使缓存生效。缓存和预热有关联,但是可以设计成独立的两套系统,此时就可以考虑集成SpringCache或者再起一个项目了。至于多级缓存的问题目前还没有场景用到,可以参考SpringCache基础上再次开发。