设计缓存 key
不同用户看到的数据不同
systemId:moduleId:func:options(不要和别人冲突)
yupao:user:recommed:userId
redis 内存不能无限增加,一定要设置过期时间!!!
缓存预热
问题:第一个用户访问还是很慢(加入第一个老板),也能一定程度上保护数据库
缓存预热的优点:
-
解决上面的问题,可以让用户始终访问很快
缓存预热的缺点:
-
增加开发成本(你要额外的开发、设计)
-
预热的时机和时间如果错了,有可能你缓存的数据不对或者太老
-
需要占用额外空间
怎么缓存预热?
-
定时
-
模拟触发(手动触发)
缓存预热的实现思路
用定时任务,每天刷新所有用户的推荐列表
注意点:
-
缓存预热的意义(新增少、总用户多)
-
缓存的空间不能太大,要预留给其他缓存空间
-
缓存数据的周期(此处每天一次)
定时任务实现缓存预热
几种方法:
-
Spring Scheduler(spring boot 默认整合了)
-
Quartz(独立于 Spring 存在的定时任务框架)
-
XXL-Job 之类的分布式任务调度平台(界面 + sdk)
SpringScheduler实现缓存预热:
1)启动类开启 @EnableScheduling
@SpringBootApplication
@MapperScan("com.zj.mapper")
@EnableSwagger2WebMvc
@EnableScheduling//开启支持定时任务
public class UserCenterApplication {
public static void main(String[] args) {
SpringApplication.run(UserCenterApplication.class, args);
}
}
2)给要定时执行的方法添加 @Scheduling 注解,指定 cron 表达式或者执行频率
/**
* 缓存预热任务
*/
@Component
@Slf4j
public class PreCacheJob {
@Resource
private UserService userService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
//设置重点用户
private List<Long> mainUserList = Arrays.asList(1L, 2L);
//每天执行,预热缓存
@Scheduled(cron = "0 00 22 * * *")//cron表达式
public void doCacheRecommend(){
for(Long userId : mainUserList){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
Page<User> userPage = new Page<>(1, 10);
userService.page(userPage, queryWrapper);
List<User> userList = userPage.getRecords();
userList = userList.stream().map((user) -> {return userService.getSafetyUser(user);}).collect(Collectors.toList());
userPage.setRecords(userList);
String redisKey = String.format("zj:user:recommend:%s", userId);
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
//写缓存
try {
valueOperations.set(redisKey, userPage, 30000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
log.info("redis set key error", e);
}
}
}
}