SpringDataRedis快速入门

一、前言:为什么用 Spring Data Redis?

在 Spring Boot 项目中,直接使用 Jedis 或 Lettuce 操作 Redis 虽然灵活,但存在以下问题:

  • ❌ 需手动管理连接、异常处理
  • ❌ 序列化/反序列化逻辑重复
  • ❌ 无法享受 Spring 的依赖注入、AOP、事务等特性

Spring Data Redis 作为 Spring 官方提供的 Redis 集成模块,提供了:

自动配置 (开箱即用)

统一 APIRedisTemplate / StringRedisTemplate

对象序列化支持

Repository 模式 (类似 JPA,操作 Hash)

与 Spring 生态无缝集成

本文将带你从零搭建 Spring Data Redis 环境,并实现常用操作


二、环境准备

2.1 前提条件

  • JDK 8+
  • Spring Boot 2.7+(默认使用 Lettuce)
  • Redis 服务(本地或远程)
bash 复制代码
# 启动本地 Redis(Docker)
docker run -d --name redis -p 6379:6379 redis:7.2

2.2 Maven 依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- 若需连接池(Lettuce 默认不依赖连接池,但推荐添加) -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

💡 注意 :Spring Boot 2.x+ 默认客户端是 Lettuce(非阻塞、线程安全),而非 Jedis。


三、基础配置:application.yml

复制代码
spring:
  redis:
    host: localhost
    port: 6379
    password: ""          # 无密码留空
    database: 0
    timeout: 2000ms       # 连接超时
    lettuce:
      pool:
        max-active: 8     # 最大连接数
        max-idle: 8       # 最大空闲连接
        min-idle: 0       # 最小空闲连接
        max-wait: -1ms    # 获取连接最大等待时间(-1 表示无限)

✅ 启动时,Spring Boot 会自动创建 RedisConnectionFactoryRedisTemplate 等 Bean。


四、核心组件:RedisTemplate vs StringRedisTemplate

组件 Key/Value 类型 适用场景
RedisTemplate<K, V> 泛型(Object) 存储 Java 对象(需配置序列化)
StringRedisTemplate String / String 存储字符串、JSON、简单 KV

4.1 使用 StringRedisTemplate(推荐用于简单场景)

java 复制代码
@Service
public class CacheService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    public void setEx(String key, String value, long timeout, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    // List 操作
    public void lpush(String key, String... values) {
        stringRedisTemplate.opsForList().leftPushAll(key, values);
    }

    // Set 操作
    public void sadd(String key, String... values) {
        stringRedisTemplate.opsForSet().add(key, values);
    }

    // ZSet 操作
    public void zadd(String key, double score, String member) {
        stringRedisTemplate.opsForZSet().add(key, member, score);
    }
}

4.2 使用 RedisTemplate(存储 Java 对象)

步骤 1:配置序列化方式(避免乱码)
java 复制代码
@Configuration
@EnableRedisRepositories // 启用 Redis Repository
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 使用 Jackson 序列化
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        // 设置 key 和 value 的序列化
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();

        return template;
    }
}
步骤 2:操作对象
java 复制代码
@Service
public class UserService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void saveUser(User user) {
        redisTemplate.opsForValue().set("user:" + user.getId(), user, 1, TimeUnit.HOURS);
    }

    public User getUser(Long id) {
        return (User) redisTemplate.opsForValue().get("user:" + id);
    }
}

优势 :自动完成对象 ↔ JSON 转换,无需手动 JSON.toJSONString()


五、高级特性:Redis Repository(操作 Hash)

Spring Data Redis 支持类似 JPA 的 Repository 模式 ,专用于操作 Hash 类型

5.1 定义实体类

java 复制代码
@RedisHash("user") // Hash key 前缀
public class User {
    @Id
    private Long id;
    private String name;
    private Integer age;

    // 构造函数、getter/setter 略
}

5.2 定义 Repository 接口

java 复制代码
public interface UserRepository extends CrudRepository<User, Long> {
    // 自动继承 save(), findById(), delete() 等方法
}

5.3 使用 Repository

java 复制代码
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void save(User user) {
        userRepository.save(user); 
        // 实际执行:HSET user:id name "Alice" age 25
    }

    public Optional<User> findById(Long id) {
        return userRepository.findById(id);
    }
}

🔍 底层原理

  • Hash key = user:id
  • 字段 = 对象属性
  • 自动序列化为字符串
    ⚠️ 注意 :Repository 仅适用于 Hash ,且实体必须有 @Id

六、常见操作封装示例

6.1 分布式锁(基于 RedisTemplate)

java 复制代码
public boolean tryLock(String lockKey, String requestId, int expireSeconds) {
    Boolean result = stringRedisTemplate.execute(
        (RedisCallback<Boolean>) connection ->
            connection.set(lockKey.getBytes(), 
                          requestId.getBytes(),
                          Expiration.seconds(expireSeconds),
                          RedisStringCommands.SetOption.SET_IF_ABSENT)
    );
    return Boolean.TRUE.equals(result);
}

public void unlock(String lockKey, String requestId) {
    // 安全解锁需 Lua 脚本(略)
    stringRedisTemplate.delete(lockKey);
}

6.2 缓存工具类

java 复制代码
@Component
public class RedisCache {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public <T> void set(String key, T value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, JSON.toJSONString(value), timeout, unit);
    }

    public <T> T get(String key, Class<T> clazz) {
        String json = redisTemplate.opsForValue().get(key);
        return json == null ? null : JSON.parseObject(json, clazz);
    }
}

七、序列化方案对比

方案 优点 缺点 适用场景
JDK 序列化(默认) 无需配置 体积大、跨语言不兼容 内部系统
String(JSON) 可读、通用 需手动转换 Web API、前后端交互
Jackson2Json 自动对象映射 需配置 存储 POJO
Protobuf 体积小、高效 需定义 schema 高性能微服务

推荐 :Web 项目优先使用 Jackson2JsonRedisSerializer


八、最佳实践与避坑指南

✅ 最佳实践

  1. 优先使用 StringRedisTemplate 处理字符串、JSON
  2. 对象缓存务必配置序列化,避免 `` 乱码
  3. key 命名规范 :如 user:{id}:profile
  4. 设置 TTL,防止内存泄漏
  5. 监控 Redis 内存与连接数

❌ 常见错误

  • 未配置序列化 → Redis 中看到 aced0005...(JDK 序列化结果)
  • 直接存储大对象 → 网络传输慢、内存爆炸
  • 忘记加 @EnableRedisRepositories → Repository 无法注入

九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
我是大猴子2 小时前
解决并发的两种方法(没用到redis)(对上一期的补充)以及开启多个定时任务
数据库·redis·缓存
難釋懷2 小时前
Redis分片集群散列插槽
数据库·redis·缓存
咖啡の猫3 小时前
Redis命令-Set命令
数据库·chrome·redis
要开心吖ZSH3 小时前
关于Redis的持久化方式(RDB、AOF)
数据库·redis·缓存
南山love4 小时前
Redis持久化深度解析:RDB与AOF的原理、区别及生产选型
数据库·redis·缓存
筱顾大牛4 小时前
Redission快速入门---分布式锁
java·redis·分布式·缓存
陈皮糖..5 小时前
docker-compose实验案例之基于docker容器化部署下 Flask+Redis 访问计数功能的实现与调优
linux·运维·redis·docker·微服务·flask·云计算
哈里谢顿17 小时前
Redis在jwt中的作用
redis
阿梦Anmory18 小时前
Redis配置远程访问(绑定0.0.0.0):从配置到安全实战
redis·安全·bootstrap