7、Redis 缓存实现-定时任务

主要内容(后端):
1.缓存和分布式缓存讲解
2.Redis介绍(5种数据结构等)
3.Java操作Redis的方法(4种方法+对比分析)
4.Java Redis Template序列化(包含源码追踪)
5.首页缓存开发与注意事项
6.缓存预热设计与实现
7.定时任务介绍和实现

数据查询慢怎么办?

  • 用缓存:提前把数据取出来保存好(通过保存到读写更快的介质,比如内存)

  • 用定时任务:预加载缓存,定时更新缓存

思考:多个机器要执行同一个任务吗?

可以用用分布式锁解决:控制同一时间只有一台机器去执行定时任务,其他机器不用重复执行了

缓存分类

分布式缓存:

  • Redis(分布式缓存)
  • mencached(分布式)
  • Etcd (云原生架构的一个分布式存储,存储配置,扩容能力)

单机缓存:

  • ehcache
  • Java 内存集合,如 HashMap
  • Caffeine (Java 内存缓存性能之王,高性能)
  • Google Guava

Redis 缓存实现

NoSQL 数据库

key-value 存储系统(区别于 MYSQL 它存储的是键值对)

Redis 数据结构

基本数据结构:

  • String 字符串类型:name:”mofeng”
  • List 列表:names:[“mofeng”,”dogmofeng”,”lu”]
  • Set 集合:names:[“mofeng”,”lu”] (值不能重复)
  • Hash 哈希:nameAge:{“mofeng”:1,”dogLu”:2}
  • Zset 集合:names[mofeng -9, doglu -12] (适合排行榜)

高级:

  • bloomfilter(布隆过滤器,主要从大量的数据中快速过滤值,比如邮件黑名单拦截)
  • geo(计算地理位置)
  • hyperloglog(pv/uv)
  • pub/sub(发布订阅,类以消息队列)
  • BitMap(1001010101010101010101010101)

自定义序列化

为了防止写入 Redis 的数据乱码、浪费空间等,可以自定义序列化器,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.yupi.yupao.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisTemplateConfig {

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(RedisSerializer.string());
return redisTemplate;
}
}

Java 操作 Redis

Spring Data Redis (推荐)

地址:https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis

Spring Data:通用的数据访问框架,定义了一组 增删改查的接口

还可以操作:mysql、Redis、jpa

使用方式如下:

1)引入 Spring Data Redis 依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.4</version>
</dependency>

2)配置 Redis 地址

1
2
3
4
5
6
spring:
# redis 配置
redis:
port: 6379
host: localhost
database: 1

Jedis

独立与 Spring 操作 Redis 的 Java 客户端

要配合 Jedis Pool 使用

Lettuce

高阶的操作 Redis 的 Java 客户端

异步、连接池

Redisson

分布式操作 Redis 的 Java 客户端,像使用本地集合一样操作 Redis (分布式 Redis 数据网络)

几种库对比

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

设计缓存 key

关键点:不同用户看到的数据不同

建议格式:

systemId:moduleld:fuc:options (防止其他系统的冲突)

比如:yupao:user:recommend:userId

注意:Redis 内存不能无限增加,一定要设置过期时间!!!

缓存预热

问题:即使使用了缓存,第一个用户访问还是很慢

缓存预热的优点:

  1. 解决第一个用户访问很慢,让用户始终快速访问
  2. 在一定程度上保护数据库

缺点:

  1. 增加开发成本(额外的开发、设计等)
  2. 预热的时机和时间错了,缓存的数据不对或者是未更新的数据
  3. 需要占用额外空间

怎么缓存预热

  1. 定时任务
  2. 手动触发

实现缓存预热

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

注意点:

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