杰瑞科技汇

Java用Redis缓存的具体步骤是什么?

总览:使用 Redis 缓存的核心步骤

  1. 环境准备:安装并启动 Redis 服务器。
  2. 项目依赖:在 Java 项目中引入 Redis 客户端库(最常用的是 Lettuce 或 Jedis)。
  3. 建立连接:在 Java 代码中配置并创建与 Redis 服务器的连接。
  4. 基本操作:执行缓存的核心操作:增、删、改、查
  5. 高级特性:使用过期时间、数据结构等高级功能。
  6. 最佳实践:遵循规范,如缓存穿透、缓存击穿、雪崩的解决方案。

第一步:环境准备

  1. 安装 Redis

    Java用Redis缓存的具体步骤是什么?-图1
    (图片来源网络,侵删)
    • 如果你使用的是 Linux 或 macOS,可以通过包管理器安装(如 apt-get install redis-serverbrew install redis)。
    • 如果你使用的是 Windows,可以下载 WSL (Windows Subsystem for Linux) 并在 WSL 中安装 Redis,或者直接下载 Windows 版本的 Redis。
    • 最简单的方式是使用 Docker:
      docker run -d -p 6379:6379 redis

      这条命令会在后台启动一个 Redis 容器,并将主机的 6379 端口映射到容器的 6379 端口。

  2. 验证 Redis 是否运行

    • 连接到 Redis 客户端:
      redis-cli
    • 执行一个简单命令:
      ping

      如果返回 PONG,说明 Redis 服务已成功启动。


第二步:项目依赖

在 Java 项目中,你需要一个 Redis 客户端,目前主流的选择是 LettuceJedis

Java用Redis缓存的具体步骤是什么?-图2
(图片来源网络,侵删)
  • Lettuce:基于 Netty,是异步和非阻塞的,性能更高,是 Spring Boot 2.x 的默认选择。
  • Jedis:是较老的、同步阻塞的客户端,非常稳定。

这里我们以 Spring Boot + Lettuce 为例,这是目前最流行和最高效的组合。

如果你使用 Maven,在 pom.xml 中添加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

如果你使用 Gradle,在 build.gradle 中添加依赖:

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

这个 starter 会自动为你配置好 Lettuce 连接池和序列化方式。


第三步:建立连接

在 Spring Boot 项目中,配置非常简单。

  1. application.propertiesapplication.yml 中配置 Redis 连接信息

    • application.properties (传统格式)

      # Redis 服务器地址
      spring.redis.host=localhost
      # Redis 服务器端口
      spring.redis.port=6379
      # Redis 服务器密码 (如果没有密码,可以不配置)
      # spring.redis.password=
      # 连接池配置
      spring.redis.lettuce.pool.max-active=8
      spring.redis.lettuce.pool.max-idle=8
      spring.redis.lettuce.pool.min-idle=0
      spring.redis.lettuce.pool.max-wait=-1ms
    • application.yml (推荐,YAML 格式)

      spring:
        redis:
          host: localhost
          port: 6379
          # password: yourpassword
          lettuce:
            pool:
              max-active: 8  # 连接池最大连接数
              max-idle: 8    # 连接池最大空闲连接数
              min-idle: 0    # 连接池最小空闲连接数
              max-wait: -1ms # 连接池获取连接的最大等待时间,-1表示无限等待
  2. 注入 RedisTemplate

    Spring Data Redis 为我们提供了一个强大的模板类 RedisTemplate,它封装了所有 Redis 操作,你只需要在你的 Service 或 Component 中注入它即可。

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    @Service
    public class UserService {
        // Spring Boot 自动配置好的 RedisTemplate
        // 它的 key 和 value 默认是序列化的,所以可以直接存对象
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        // ... 后续操作
    }

第四步:基本操作(增删改查)

RedisTemplate 提供了 opsForValue(), opsForHash(), opsForList() 等方法来操作不同的数据结构,最常用的是 opsForValue(),用于操作最简单的键值对。

添加/修改数据 (Set)

// 向 Redis 中存入一个键值对
// key: "user:1001", value: 一个 User 对象
User user = new User(1001L, "张三", "zhangsan@example.com");
redisTemplate.opsForValue().set("user:1001", user);

查询数据 (Get)

// 从 Redis 中根据 key 获取 value
// 返回的是 Object 类型,需要强制转换
Object obj = redisTemplate.opsForValue().get("user:1001");
if (obj != null) {
    User user = (User) obj;
    System.out.println("从缓存获取用户: " + user.getName());
}

删除数据 (Delete)

// 根据 key 删除数据
Boolean result = redisTemplate.delete("user:1001");
System.out.println("删除结果: " + result); // true 表示删除成功,false 表示 key 不存在

判断 Key 是否存在 (Exists)

// 判断 key 是否存在
Boolean exists = redisTemplate.hasKey("user:1001");
System.out.println("Key是否存在: " + exists);

第五步:高级特性

设置过期时间

这是缓存中最重要的功能之一,可以防止数据永久占用内存。

// 设置 key 的过期时间为 10 秒
redisTemplate.opsForValue().set("user:1001", user, 10, TimeUnit.SECONDS);
// 也可以先设置值,再单独设置过期时间
redisTemplate.opsForValue().set("temp:data", "some data");
redisTemplate.expire("temp:data", 5, TimeUnit.MINUTES);

使用不同的数据结构

除了 String,Redis 还有 Hash, List, Set, ZSet 等。

操作 Hash:

// 存储 Hash
redisTemplate.opsForHash().put("user:info:1001", "name", "李四");
redisTemplate.opsForHash().put("user:info:1001", "age", "30");
// 获取 Hash 中的某个字段
String name = (String) redisTemplate.opsForHash().get("user:info:1001", "name");
// 获取整个 Hash
Map<Object, Object> userInfo = redisTemplate.opsForHash().entries("user:info:1001");

操作 List:

// 从左边推入一个元素
redisTemplate.opsForList().leftPush("messages:1001", "你好,世界!");
// 从右边推入一个元素
redisTemplate.opsForList().rightPush("messages:1001", "这是第二条消息");
// 获取列表中的元素(索引从0开始)
String firstMsg = (String) redisTemplate.opsForList().index("messages:1001", 0);
// 获取列表长度
Long size = redisTemplate.opsForList().size("messages:1001");

第六步:最佳实践与注意事项

序列化问题

RedisTemplate 默认使用的是 JdkSerializationRedisSerializer,它有几个缺点:

  • 可读性差:序列化后的数据是二进制,无法直接在 redis-cli 中查看。
  • 体积大:序列化后的数据体积较大。

推荐自定义序列化方式:通常使用 JSON 格式,因为它可读性好、体积小。

创建一个配置类:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 1. 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 2. 创建 Jackson2JsonRedisSerializer 序列化器
        Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSerializer.setObjectMapper(om);
        // 3. 创建 StringRedisSerializer 序列化器(用于 key)
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        // 4. 设置 key 和 hash 的 key 采用 String 序列化方式
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        // 5. 设置 value 和 hash 的 value 采用 Jackson 序列化方式
        template.setValueSerializer(jacksonSerializer);
        template.setHashValueSerializer(jacksonSerializer);
        // 6. 初始化 RedisTemplate
        template.afterPropertiesSet();
        return template;
    }
}

配置后,存入 Redis 的数据就是 JSON 格式,方便阅读和调试。

缓存问题解决方案

  • 缓存穿透:查询一个根本不存在的数据。

    • 解决方案:如果查询数据库结果为空,依然将这个空结果缓存起来,并设置一个较短的过期时间。
  • 缓存击穿:一个 key 非常热点,在某一刻大量请求同时失效,导致所有请求直接打到数据库上。

    • 解决方案:使用互斥锁(如 SETNX 实现),当缓存失效时,只允许一个线程去查询数据库并回写缓存,其他线程等待。
  • 缓存雪崩:大量的 key 在同一时间集体失效,导致所有请求直接打到数据库上。

    • 解决方案
      1. 在设置缓存时,给 key 的过期时间加上一个随机值,避免集体失效。
      2. 高可用架构,保证 Redis 集群不会宕机。
      3. 做好数据库的降级和限流策略。

Spring Cache 注解

Spring Boot 提供了 @Cacheable, @CachePut, @CacheEvict 等注解,可以让你以声明式的方式使用缓存,而无需手动调用 RedisTemplate

示例:

@Service
public class UserService {
    @Cacheable(value = "users", key = "#id") // value 是缓存名称,key 是 SpEL 表达式
    public User getUserById(Long id) {
        System.out.println("正在从数据库查询用户 ID: " + id);
        // 模拟从数据库查询
        return new User(id, "用户" + id, "user" + id + "@example.com");
    }
    @CachePut(value = "users", key = "#user.id") // 每次都会执行方法,并更新缓存
    public User updateUser(User user) {
        System.out.println("正在更新用户: " + user.getId());
        // 模拟更新数据库
        return user;
    }
    @CacheEvict(value = "users", key = "#id") // 方法执行后,删除缓存
    public void deleteUser(Long id) {
        System.out.println("正在删除用户: " + id);
        // 模拟从数据库删除
    }
}

要使用 @Cacheable,你需要在主启动类上添加 @EnableCaching 注解。


在 Java 中使用 Redis 缓存的步骤可以总结为:

  1. 环境就绪:确保 Redis 服务正在运行。
  2. 引入依赖:在 Spring Boot 项目中加入 spring-boot-starter-data-redis
  3. 配置连接:在配置文件中指定 Redis 的地址和端口。
  4. 注入模板:在需要使用的类中注入 RedisTemplate
  5. 执行操作:通过 opsForValue() 等方法进行增删改查。
  6. 优化与规范:自定义序列化方式,并注意处理缓存穿透、击穿、雪崩等常见问题。

遵循以上步骤,你就可以在 Java 项目中顺利地集成和使用 Redis 缓存了。

分享:
扫描分享到社交APP
上一篇
下一篇