Redis与Spring Boot集成指南:从基础到高级应用

环境准备与依赖配置

1. Redis 服务安装

在开始集成前,需确保本地或远程已运行 Redis 服务。以下是不同操作系统的安装方式:

Ubuntu/Debian

sudo apt update
sudo apt install redis-server
sudo systemctl start redis

CentOS

sudo yum install epel-release
sudo yum install redis
sudo systemctl start redis

macOS (Homebrew)

brew install redis
brew services start redis

Windows
推荐通过 Docker 或 WSL2 运行 Redis 容器:

docker run --name redis -p 6379:6379 -d redis

验证 Redis 运行状态:

redis-cli ping
# 返回 PONG 表示成功

2. 创建 Spring Boot 项目

通过 Spring Initializr(https://start.spring.io)生成项目骨架,添加以下依赖:

  • Spring Data Redis
  • Lombok(可选,用于简化代码)

Maven 依赖示例

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Gradle 依赖示例

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

Redis 连接配置

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

application.properties

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password= # 若无密码则留空
spring.redis.database=0

application.yml

spring:
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0

高级连接池配置(Lettuce)

Spring Boot 默认使用 Lettuce 客户端,可通过以下参数优化连接池:

spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.pool.max-wait=100ms

基础操作:RedisTemplate 使用

1. 注入 RedisTemplate

@Autowired
private RedisTemplate<String, Object> redisTemplate;

2. 序列化配置(解决 key/value 乱码)

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // Key 序列化为 String
        template.setKeySerializer(new StringRedisSerializer());
        
        // Value 序列化为 JSON
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        return template;
    }
}

3. 数据操作示例

存储字符串

redisTemplate.opsForValue().set("greeting", "Hello, Redis!");
String value = (String) redisTemplate.opsForValue().get("greeting");

存储对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Long id;
    private String name;
    private String email;
}

// 操作示例
User user = new User(1L, "Alice", "alice@example.com");
redisTemplate.opsForValue().set("user:1", user);
User cachedUser = (User) redisTemplate.opsForValue().get("user:1");

设置过期时间

redisTemplate.opsForValue().set("temporary_key", "data", 30, TimeUnit.SECONDS);

缓存集成:Spring Cache 抽象

1. 启用缓存支持

在启动类添加 @EnableCaching 注解:

@SpringBootApplication
@EnableCaching
public class RedisDemoApplication { ... }

2. 配置 Redis 缓存管理器

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
        .entryTtl(Duration.ofMinutes(30));

    return RedisCacheManager.builder(factory)
        .cacheDefaults(config)
        .build();
}

3. 注解使用示例

@Cacheable

@Service
public class UserService {

    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 模拟数据库查询
        return userRepository.findById(id).orElse(null);
    }
}

@CacheEvict

@CacheEvict(value = "users", key = "#user.id")
public void updateUser(User user) {
    userRepository.save(user);
}

@CachePut

@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
    return userRepository.save(user);
}

高级功能实现

1. 发布/订阅模式

消息监听器

@Component
public class RedisMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(message.getChannel());
        String body = new String(message.getBody());
        System.out.println("Received message: " + body + " from channel: " + channel);
    }
}

配置监听容器

@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                              RedisMessageListener listener) {
    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(factory);
    container.addMessageListener(listener, new ChannelTopic("news"));
    return container;
}

发布消息

@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void publishMessage(String channel, String message) {
    redisTemplate.convertAndSend(channel, message);
}

2. 事务支持

// 启用事务支持
redisTemplate.setEnableTransactionSupport(true);

// 事务操作示例
List<Object> results = redisTemplate.execute(new SessionCallback<>() {
    @Override
    public List<Object> execute(RedisOperations operations) {
        operations.multi();
        operations.opsForValue().set("key1", "value1");
        operations.opsForValue().set("key2", "value2");
        return operations.exec();
    }
});

3. 分布式锁实现

Redisson 客户端集成

  1. 添加依赖:
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.2</version>
</dependency>
  1. 配置 Redisson:
@Bean
public RedissonClient redissonClient() {
    Config config = new Config();
    config.useSingleServer()
          .setAddress("redis://localhost:6379");
    return Redisson.create(config);
}
  1. 使用分布式锁:
@Autowired
private RedissonClient redissonClient;

public void performTaskWithLock() {
    RLock lock = redissonClient.getLock("myLock");
    try {
        boolean isLocked = lock.tryLock(10, 60, TimeUnit.SECONDS);
        if (isLocked) {
            // 执行受保护的操作
        }
    } finally {
        lock.unlock();
    }
}

性能优化实践

1. 连接池调优

根据实际负载调整 Lettuce 参数:

spring.redis.lettuce.pool.max-active=50
spring.redis.lettuce.pool.max-idle=20
spring.redis.lettuce.pool.min-idle=5
spring.redis.lettuce.pool.max-wait=2000ms

2. 序列化优化

针对不同数据类型选择最佳序列化方案:

  • String 类型StringRedisSerializer
  • JSON 对象GenericJackson2JsonRedisSerializer
  • 二进制数据ByteArrayRedisSerializer

3. 管道技术(Pipeline)

批量操作减少网络往返次数:

List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
    @Override
    public Object doInRedis(RedisConnection connection) {
        for (int i = 0; i < 1000; i++) {
            connection.stringCommands().set(("key:" + i).getBytes(), ("value:" + i).getBytes());
        }
        return null;
    }
});

异常处理策略

1. 连接失败处理

try {
    redisTemplate.opsForValue().set("key", "value");
} catch (RedisConnectionFailureException ex) {
    log.error("Redis connection failed: {}", ex.getMessage());
    // 执行降级逻辑
}

2. 缓存穿透防护

使用空值缓存和布隆过滤器:

@Cacheable(value = "users", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
    User user = userRepository.findById(id).orElse(null);
    if (user == null) {
        redisTemplate.opsForValue().set("user:null:" + id, "", 5, TimeUnit.MINUTES);
    }
    return user;
}

3. 缓存雪崩预防

设置随机过期时间:

private int getRandomTTL() {
    return 1800 + new Random().nextInt(300); // 1800-2100 秒
}

redisTemplate.opsForValue().set("key", "value", getRandomTTL(), TimeUnit.SECONDS);

集群与哨兵模式配置

1. Redis 集群配置

spring.redis.cluster.nodes=192.168.1.101:6379,192.168.1.102:6379,192.168.1.103:6379
spring.redis.cluster.max-redirects=3

2. 哨兵模式配置

spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.1.201:26379,192.168.1.202:26379,192.168.1.203:26379

测试策略

1. 单元测试示例

@SpringBootTest
public class RedisIntegrationTest {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    void testBasicOperations() {
        redisTemplate.opsForValue().set("testKey", "testValue");
        assertEquals("testValue", redisTemplate.opsForValue().get("testKey"));
    }
}

2. 集成测试要点

  • 验证缓存注解行为
  • 测试事务回滚场景
  • 模拟网络分区下的故障转移

总结与最佳实践

  1. 连接管理

    • 始终配置连接池参数
    • 生产环境使用集群或哨兵模式
  2. 数据结构选择

    • 字符串:简单键值对
    • Hash:对象存储
    • Sorted Set:排行榜场景
  3. 监控与日志

    • 使用 INFO 命令监控 Redis 状态
    • 集成 Spring Boot Actuator 的 /health 端点
  4. 版本兼容性

    • Spring Data Redis 与 Redis Server 版本匹配
    • 定期更新客户端依赖
正文到此结束
评论插件初始化中...
Loading...