当前位置: 首页 > ai >正文

Spring Data Redis 从入门到精通:原理与实战指南

一、Redis 基础概念
Redis(Remote Dictionary Server)是开源的内存键值对数据库,以高性能著称。它支持多种数据结构(String、Hash、List、Set、ZSet),并提供持久化机制(RDB、AOF)。
核心特点:
内存存储,读写速度极快(单线程处理命令,QPS 可达 10w+)
支持数据持久化,避免重启数据丢失
提供丰富的数据结构操作
支持主从复制、哨兵模式和集群部署
单线程模型,避免上下文切换开销


典型应用场景:
缓存(减轻数据库压力)
计数器 / 限速器(如点赞数、限流)
消息队列(基于 List 或 Pub/Sub)
会话存储(分布式系统共享 Session)
排行榜(ZSet 有序集合)


二、Spring Data Redis 入门
Spring Data Redis 是 Spring 家族的一部分,提供了简化 Redis 操作的抽象层。
核心组件:
RedisTemplate:操作 Redis 的核心类
StringRedisTemplate:RedisTemplate 的子类,专门处理字符串
RedisConnectionFactory:连接工厂,管理 Redis 连接
RedisSerializer:序列化器,处理数据的序列化与反序列化
快速上手步骤:
添加依赖(Maven)
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置连接信息(application.properties)
properties
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword
使用 RedisTemplate 操作数据
java
@Service
public class RedisExampleService {
private final RedisTemplate<String, Object> redisTemplate;

    public RedisExampleService(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}

    // 存储字符串
public void setString(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}

    // 获取字符串
public String getString(String key) {
return (String) redisTemplate.opsForValue().get(key);
}

    // 存储 Hash
public void setHash(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}

    // 获取 Hash
public Object getHash(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
}
三、序列化机制详解
RedisTemplate 默认使用 JDK 序列化器,会导致存储的键值带有类信息前缀(如 \xAC\xED\x00\x05t\x00\x03key),可读性差且占用空间。
推荐配置 JSON 序列化:
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);

        // 使用 Jackson 2 序列化器处理值
Jackson2JsonRedisSerializer<Object> jsonSerializer = 
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(
om.getPolymorphicTypeValidator(), 
ObjectMapper.DefaultTyping.NON_FINAL
);
jsonSerializer.setObjectMapper(om);

        // 使用 String 序列化器处理键
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);

        template.afterPropertiesSet();
return template;
}
}
四、缓存注解实战
Spring Data Redis 提供了基于注解的缓存抽象,简化缓存操作。
核心注解:
@Cacheable:查询时先查缓存,没有则执行方法并缓存结果
@CachePut:强制更新缓存(无论是否存在)
@CacheEvict:清除缓存
@Caching:组合多个缓存注解
@CacheConfig:类级别的缓存配置
示例代码:
java
@Service
@CacheConfig(cacheNames = "users") // 默认缓存名称
public class UserService {

    @Cacheable(key = "#id") // 缓存键为方法参数 id
public User getUserById(Long id) {
System.out.println("查询数据库: " + id);
return userRepository.findById(id).orElse(null);
}

    @CachePut(key = "#user.id") // 更新缓存
public User updateUser(User user) {
return userRepository.save(user);
}

    @CacheEvict(key = "#id") // 清除缓存
public void deleteUser(Long id) {
userRepository.deleteById(id);
}

    @Caching(
evict = {
@CacheEvict(key = "#id"),
@CacheEvict(cacheNames = "userList", allEntries = true)
}
)
public void deleteAndFlush(Long id) {
userRepository.deleteById(id);
}
}
五、高级特性与最佳实践
Redis 事务
java
public void transactionExample() {
redisTemplate.execute(new SessionCallback<List<Object>>() {
@Override
public List<Object> execute(RedisOperations operations) throws DataAccessException {
operations.multi(); // 开启事务
operations.opsForValue().set("key1", "value1");
operations.opsForValue().increment("counter");
return operations.exec(); // 执行事务
}
});
}
分布式锁实现
java
public Boolean acquireLock(String lockKey, String requestId, long expireTime) {
return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
JedisCommands commands = (JedisCommands) connection.getNativeConnection();
return "OK".equals(commands.set(lockKey, requestId, "NX", "PX", expireTime));
});
}

public Boolean releaseLock(String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
JedisCommands commands = (JedisCommands) connection.getNativeConnection();
return commands.eval(script, Collections.singletonList(lockKey), 
Collections.singletonList(requestId))
.equals(1L);
});
}
消息发布与订阅
java
// 发布者
public void publishMessage(String channel, String message) {
redisTemplate.convertAndSend(channel, message);
}

// 订阅者配置
@Configuration
public class RedisMessageConfig {
@Bean
RedisMessageListenerContainer container(
RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {

RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}

    @Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
}

// 消息接收者
@Component
public class Receiver {
public void receiveMessage(String message) {
System.out.println("收到消息: " + message);
}
}


六、性能优化与监控
连接池配置
properties
spring.redis.lettuce.pool.max-active=8   # 最大连接数
spring.redis.lettuce.pool.max-wait=-1ms  # 获取连接的最大等待时间
spring.redis.lettuce.pool.max-idle=8     # 最大空闲连接数
spring.redis.lettuce.pool.min-idle=0     # 最小空闲连接数
慢查询日志
properties
# redis.conf 配置
slowlog-log-slower-than 10000  # 记录超过 10ms 的命令
slowlog-max-len 128            # 最多保留 128 条日志
内存优化
合理设置过期时间
使用 Hash 结构减少键数量
避免大 Value(建议不超过 10KB)
七、集群与高可用
哨兵模式配置
properties
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.1.1:26379,192.168.1.2:26379
spring.redis.password=yourpassword
集群模式配置
properties
spring.redis.cluster.nodes=192.168.1.1:7000,192.168.1.2:7001,192.168.1.3:7002
spring.redis.cluster.max-redirects=3  # 最大重定向次数
八、常见问题与解决方案
缓存穿透
空值缓存:查询不存在时也缓存空结果
布隆过滤器:预先过滤不可能存在的 key
缓存雪崩
过期时间打散:为缓存设置随机过期时间
多级缓存:本地缓存 + Redis 结合
缓存击穿
互斥锁:查询数据库时加锁,保证单线程访问
永不过期:热点数据不过期,异步更新
序列化异常
统一序列化方式
确保实体类实现 Serializable 接口
九、总结
Spring Data Redis 提供了强大而灵活的 Redis 操作能力,通过模板类和注解简化了开发流程。合理使用 Redis 可以显著提升应用性能,但需要注意分布式环境下的一致性、并发控制等问题。
建议实践:
优先使用 JSON 序列化
为缓存设置合理的过期时间
对热点数据进行预加载
监控 Redis 性能指标(内存、QPS、命中率)
生产环境采用集群部署确保高可用

http://www.xdnf.cn/news/16046.html

相关文章:

  • C++刷题 - 7.23
  • kettle 8.2 ETL项目【一、初始化数据库及介绍】
  • 【MySQL】MySQL 索引详解
  • UniappDay01
  • 计算机毕设分享-基于SpringBoot的房屋租赁系统(开题报告+源码+Lun文+开发文档+数据库设计文档)
  • 【Spring Cloud Gateway 实战系列】进阶篇:过滤器高级用法、动态路由配置与性能优化
  • 【计算机网络】正/反向代理服务器,有状态/无状态应用
  • 漏洞生命周期管理:从发现到防护的全流程方案
  • AI产品经理面试宝典第48天:产品设计与用户体验优化策略
  • log4j2漏洞
  • 无人机光伏巡检误检率↓78%!陌讯多模态融合算法实战解析
  • Linux Debian操作系统、Deepin深度操作系统手动分区方案参考
  • 【数据结构初阶】--树和二叉树先导篇
  • C++题解 P2288 家谱(gen)
  • 2025.7.15vlan作业
  • 1553B心得总结
  • 对象\数组\Map按属性值排序迭代器
  • 达索×杰克×安托:开启服装智造“新宇宙”
  • 密码学中的概率论与统计学:从频率分析到现代密码攻击
  • 不止于“亮”:一盏智慧路灯的技术进化史——塔能科技用“落地性”定义行业标准
  • Python 程序设计讲义(9):Python 的基本数据类型——复数
  • Python-Pytorch编码习惯
  • 如何最简单、通俗地理解Python的numpy库?
  • 前端项目下载发票pdf文件要求改文件名笔记
  • [hot 100] 移动零-Python3
  • AI替代人工:浪潮中的沉浮与觉醒
  • MCP客户端架构与实施
  • 智能小e-集成配置
  • 自动化运维:从脚本到DevOps的演进
  • Java设计模式-备忘录模式