前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缓存预热?你没用过?

缓存预热?你没用过?

作者头像
疯狂的KK
修改2023-02-06 17:46:58
4740
修改2023-02-06 17:46:58
举报
文章被收录于专栏:Java项目实战Java项目实战

根据场景来用合适的技术,那真是再合适不过了,学了就得用么,不会咱再学,没场景实在难有用武之地,在实战中摸索异常是比demo更有效果的,与其坐学厚厚的.....怎么t里t气的(手动狗头)。

我们从哪入手呢?不直接从场景入手,我们从理论入手,如何解决缓存穿透问题?

什么是缓存穿透?

去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

如何解决缓存穿透问题?

1.利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。

2.采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。

3.提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

缓存预热 vs 缓存热备

缓存热备即当一台服务器不可用时能实时切换到备用缓存服务器,不影响缓存使用。集群模式下,每个主节点都会有一个或多个从节点来当备用,一旦主节点挂掉,从节点立即充当主节点使用。

应用场景

对于一些固定不变模板类,基础类等信息,但在流程中需要时刻查询的,比如机票起始地点,北京飞上海你永远是固定的航线内的公里数,比如地点是不会变的,期间的公里数完全可以预先缓存。但缓存期限和数据量需要考虑效率问题。缓存数据如果因为集群宕掉,应不影响数据。

对了到了这里不得不提一句redis find hot key还有没有印象,京东开源的热点数据缓存接口,这个大家有兴趣可以了解一下。

代码

@DependsOn+@Component

@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中,因为缓存预热这是必须的。

代码语言:javascript
复制
//可以作用在方法和类上。
//当作用在类上时,通常会与@Component及其衍生注解等注解配合使用。
//当作用在方法上时,通常会与@Bean注解配合使用。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
  //要依赖的bean id,是个数组,也就是说可以依赖多个bean。
  //效果是该注解作用的bean会比value设置的依赖bean晚实例化到容器中。
  String[] value() default {};
}

demo

代码语言:javascript
复制
@Component
public class CacheEventSource {

    public CacheEventSource(){
        System.out.println("缓存事件驱动...");
    }

}

@Component
public class EventListenerSource {

    public EventListenerSource(){
        System.out.println("监听事件驱动...");
    }
}

使用DependsOn注解

代码语言:javascript
复制
@Component
@DependsOn(value = {"eventListenerSource"})
public class CacheEventSource {

    public CacheEventSource(){
        System.out.println("缓存事件驱动...");
    }

}
代码语言:javascript
复制
@Slf4j
@DependsOn(value = {"RedisService", "routeService","orderService"})
@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基础上再次开发。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档