Redis 简介
Redis(Remote Dictionary Server)是一个开源的 NoSQL 数据库,数据存储在内存中以实现高速读写,同时支持持久化到磁盘,可以用作数据库、缓存和消息代理。
主要特性
- 内存优先:数据存储在内存中,读写速度极快(读约 10 万次 / 秒,写约 8 万次 / 秒)。
- 持久化支持:通过 RDB 快照和 AOF 日志实现数据持久化,保障数据安全。
- 多数据结构:支持字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)、位图(Bitmap)、HyperLogLog 等,满足不同场景需求。
- 原子操作:所有操作都是原子性的,确保数据一致性。
- 分布式架构:支持主从复制、哨兵(Sentinel)、集群(Cluster)模式,提升可用性和扩展性。
- 丰富功能:发布 / 订阅、Lua 脚本、事务、管道(Pipeline)、LRU 淘汰策略等。
在 Spring Boot 中使用 Redis
环境准备
首先需要本地安装 redis,Mac 用户可以使用 homebrew 安装,安装完成后启动服务
bash
redis-server
添加依赖
在 Spring Boot 项目中添加 redis 依赖
xml
<!-- Spring Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置 Redis
java
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器端口
spring.redis.port=6379
# Redis连接超时(毫秒)
spring.redis.timeout=60000
# 设置密码
# spring.redis.password=yourpassword
# Spring缓存配置
spring.cache.type=redis
启用缓存
在 Spring Boot 应用的主类或配置类上添加@EnableCaching
注解,启用缓存功能。
java
@SpringBootApplication
@EnableCaching // 启用缓存
public class RedisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(RedisDemoApplication.class, args);
}
}
构建实体类
@RedisHash("User")
:指示这个实体类在 Redis 中存储时的键前缀为 "User"@Id
:标识该字段为主键
java
package com.example.rediscrud.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import java.io.Serializable;
@RedisHash("User")
public class User implements Serializable {
@Id
private String id;
private String name;
// 无参构造器
public User() {}
// 全参构造器
public User(String id, String name) {
this.id = id;
this.name = name;
}
// Getters 和 Setters
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name){
this.name=name;
}
}
Redis 并没有 namespace 的概念,所有 key 在相同层级存储,一般通过 key 的前缀来区分
创建 Repository 接口
可以直接使用 Redis API 来操作缓存内容
java
@Repository
public class UserRepository {
private static final String KEY_PREFIX = "user:";
@Autowired
private RedisTemplate<String, User> redisTemplate;
// 创建用户
public void save(User user) {
String key = KEY_PREFIX + user.getId();
redisTemplate.opsForValue().set(key, user);
}
// 根据 ID 获取用户
public User findById(String id) {
String key = KEY_PREFIX + id;
return redisTemplate.opsForValue().get(key);
}
// 更新用户信息
public void update(User user) {
String key = KEY_PREFIX + user.getId();
redisTemplate.opsForValue().set(key, user);
}
// 根据 ID 删除用户
public void delete(String id) {
String key = KEY_PREFIX + id;
redisTemplate.delete(key);
}
}
但 Spring Data Redis 提供了 RedisRepository(继承自 CrudRepository)接口,允许我们方便地进行 CRUD 操作。
java
package com.example.rediscrud.repository;
import com.example.rediscrud.model.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends CrudRepository<User, String> {
// 继承了CrudRepository,已经包含了常用的CRUD方法
}
创建 Service 类
创建一个 UserService 类,封装业务逻辑,利用 UserRepository 进行数据操作,并可以添加缓存逻辑
@CachePut
: 更新缓存。每次调用该方法都会将返回值更新到缓存中。@Cacheable
: 先从缓存中获取数据,如果不存在则调用方法并将结果存入缓存。@CacheEvict
: 从缓存中移除数据。
java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
/**
* 创建/更新用户
*
* @param user 用户对象
* @return 保存后的用户对象
*/
@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
return userRepository.save(user);
}
/**
* 根据ID获取用户信息
*
* @param id 用户ID
* @return Optional<User>
*/
@Cacheable(value = "users", key = "#id")
public Optional<User> getUserById(String id) {
return userRepository.findById(id);
}
/**
* 获取所有用户
*
* @return Iterable<User>
*/
public Iterable<User> getAllUsers() {
return userRepository.findAll();
}
/**
* 根据ID删除用户
*
* @param id 用户ID
*/
@CacheEvict(value = "users", key = "#id")
public void deleteUserById(String id) {
userRepository.deleteById(id);
}
}
序列化
默认情况下,Spring Boot 使用 JDK 序列化 来存储缓存数据。这可能导致 Redis 中存储的数据不可读,且性能较低。为了提高效率和可读性,可以创建 RedisConfig 类配置Redis使用 Jackson 进行JSON 序列化。
@Configuration
:标识一个类为 Spring 配置类,允许定义多个@Bean
方法,生成 Spring 容器管理的 bean。@Bean
:标识一个方法,表示该方法将返回一个需要由 Spring 容器管理的 bean
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 允许访问所有属性
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 启用默认Typing。Deprecated from Jackson 2.10, use `activateDefaultTyping` with appropriate settings
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
// 设置key和value的序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}