Day3学习笔记

定时任务/数据预热时间

问题:第一个用户访问还是很慢(加入第一个老板),也能一定程度上保护数据库

缓存预热的优点:

  1. 解决上面的问题,可以让用户始终访问很快

缺点:

  1. 增加开发成本(你要额外的开发、设计)
  2. 预热的时机和时间如果错了,有可能你缓存的数据不对或者太老
  3. 需要占用额外空间

怎么缓存预热?

  1. 定时
  2. 模拟触发(手动触发)
实现

用定时任务,每天刷新所有用户的推荐列表

注意点:

  1. 缓存预热的意义(新增少、总用户多)
  2. 缓存的空间不能太大,要预留给其他缓存空间
  3. 缓存数据的周期(此处每天一次)

定时任务实现

  1. Spring Scheduler(spring boot 默认整合了)
  2. Quartz(独立于 Spring 存在的定时任务框架)
  3. XXL-Job 之类的分布式任务调度平台(界面 + sdk)

第一种方式:

  1. 主类开启 @EnableScheduling
  2. 给要定时执行的方法添加 @Scheduling 注解,指定 cron 表达式或者执行频率

不要去背 cron 表达式!!!!!

并发问题

  • 用户插入单元测试,注意打包时要删掉或忽略,不然打一次包就插入一次
  • for 循环插入数据的问题:
    1. 建立和释放数据库链接(批量查询解决)
    2. for 循环是绝对线性的(并发)
private ExecutorService executorService = new ThreadPoolExecutor(
    16,                // 核心线程数 (corePoolSize)
    1000,              // 最大线程数 (maximumPoolSize)
    10000,             // 线程空闲时间 (keepAliveTime)
    TimeUnit.MINUTES,  // 时间单位 (unit)
    new ArrayBlockingQueue<>(10000) // 任务队列 (workQueue)
);

任务队列 (workQueue)

  • new ArrayBlockingQueue<>(10000)
  • 作用:这是一个有界队列,用来存储等待执行的任务。ArrayBlockingQueue 是一个基于数组的阻塞队列,具有固定的容量(这里是10000)。当线程池中的线程都在忙碌时,新提交的任务会被放入这个队列中等待处理。
  1. 超出队列容量:如果任务队列满了,而此时仍有新任务提交,线程池会创建新的线程来处理这些任务,但不会超过最大线程数(1000个)。
  2. 线程回收:一旦某个线程完成其工作并且空闲了超过指定的 keepAliveTime(10000分钟),它将被终止,前提是当前线程数大于核心线程数。

Completable使用详解

二者配合使用完成并发操作

查询效率问题

  • 数据库慢?预先把数据查出来,放到一个更快读取的地方,不用再查数据库了。(缓存)

  • 预加载缓存,定时更新缓存。(定时任务)

  • 多个机器都要执行任务么?(分布式锁:控制同一时间只有一台机器去执行定时任务,其他机器不用重复执行)

分布式

  1. 如果你用的是 Spring,并且没有过多的定制化要求,可以用 Spring Data Redis,最方便
  2. 如果你用的不是 SPring,并且追求简单,并且没有过高的性能要求,可以用 Jedis + Jedis Pool
  3. 如果你的项目不是 Spring,并且追求高性能、高定制化,可以用 Lettuce,支持异步、连接池
  • 如果你的项目是分布式的,需要用到一些分布式的特性(比如分布式锁、分布式集合),推荐用 redisson

Redis

NoSQL 数据库

key - value 存储系统(区别于 MySQL,他存储的是键值对)

Redis 数据结构

  • String 字符串类型: name: "yupi"

  • List 列表:names: ["yupi", "dogyupi", "yupi"]

  • Set 集合:names: ["yupi", "dogyupi"](值不能重复)

  • Hash 哈希:nameAge:

  • Zset 集合:names: { yupi - 9, dogyupi - 12 }(适合做排行榜)

而redis一般要写个配置类才能用

/**
 *
 *  自定义序列化
 *
 */
@Configuration
public class RedisTemplateConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        //创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
       //设置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置Key的序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());

        //创建Json序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置Value的序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);

        return redisTemplate;
    }
}

redis 内存不能无限增加,一定要设置过期时间!!!

 //无缓存,查数据库
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        userPage = userService.page(new Page<>(pageNum,pageSize),queryWrapper);
        //写缓存,10s过期
        try {
            valueOperations.set(redisKey,userPage,30000, TimeUnit.MILLISECONDS);//存储到redis中并规定30000ms过期
        } catch (Exception e){
            log.error("redis set key error",e);
        }
posted @   Sha11ow  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示