一、基础配置
1.Maven依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- Jackson序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2. application.yml基础配置
yaml
spring:
redis:
# 单节点配置
host: localhost
port: 6379
password: 123456
database: 0
# 连接池配置
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: -1ms
timeout: 2000ms
# 集群配置
# cluster:
# nodes: 192.168.1.101:6379,192.168.1.102:6379,192.168.1.103:6379
# max-redirects: 3
# 哨兵配置
# sentinel:
# master: mymaster
# nodes: 192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379
# 主从配置(自定义配置,需要代码支持)
二、高级配置类
1. RedisTemplate配置
java
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// 使用Jackson2JsonRedisSerializer序列化value
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(
LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.WRAPPER_ARRAY
);
serializer.setObjectMapper(mapper);
// 使用StringRedisSerializer序列化key
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
2. 自定义序列化配置
java
@Configuration
public class RedisSerializationConfig {
/**
* 通用序列化配置
*/
@Bean
public RedisSerializer<Object> redisSerializer() {
// 创建JSON序列化器
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(
PropertyAccessor.ALL,
JsonAutoDetect.Visibility.ANY
);
objectMapper.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL
);
serializer.setObjectMapper(objectMapper);
return serializer;
}
/**
* 专门处理LocalDateTime的序列化
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory,
RedisSerializer<Object> redisSerializer) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// Key和HashKey使用String序列化
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// Value和HashValue使用JSON序列化
template.setValueSerializer(redisSerializer);
template.setHashValueSerializer(redisSerializer);
template.afterPropertiesSet();
return template;
}
}
3. 缓存配置
java
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> jacksonSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 默认缓存1小时
.serializeKeysWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(redisSerializer)
)
.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jacksonSerializer)
)
.disableCachingNullValues(); // 不缓存null值
// 针对不同缓存设置不同的过期时间
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put("userCache",
config.entryTtl(Duration.ofMinutes(30)));
cacheConfigurations.put("productCache",
config.entryTtl(Duration.ofHours(2)));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.withInitialCacheConfigurations(cacheConfigurations)
.build();
}
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append(":");
sb.append(method.getName());
for (Object obj : params) {
if (obj != null) {
sb.append(":").append(obj.toString());
}
}
return sb.toString();
};
}
}
三、多数据源配置
1. 多Redis实例配置
java
@Configuration
public class MultipleRedisConfig {
@Primary
@Bean(name = "primaryRedisTemplate")
public RedisTemplate<String, Object> primaryRedisTemplate(
@Qualifier("primaryRedisConnectionFactory")
RedisConnectionFactory factory) {
return createRedisTemplate(factory);
}
@Bean(name = "secondaryRedisTemplate")
public RedisTemplate<String, Object> secondaryRedisTemplate(
@Qualifier("secondaryRedisConnectionFactory")
RedisConnectionFactory factory) {
return createRedisTemplate(factory);
}
@Primary
@Bean(name = "primaryRedisConnectionFactory")
public RedisConnectionFactory primaryRedisConnectionFactory() {
RedisStandaloneConfiguration config =
new RedisStandaloneConfiguration("127.0.0.1", 6379);
config.setPassword(RedisPassword.of("password1"));
config.setDatabase(0);
return new LettuceConnectionFactory(config);
}
@Bean(name = "secondaryRedisConnectionFactory")
public RedisConnectionFactory secondaryRedisConnectionFactory() {
RedisStandaloneConfiguration config =
new RedisStandaloneConfiguration("127.0.0.1", 6380);
config.setPassword(RedisPassword.of("password2"));
config.setDatabase(0);
return new LettuceConnectionFactory(config);
}
private RedisTemplate<String, Object> createRedisTemplate(
RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 序列化配置
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
2. 动态数据源切换
java
@Component
public class RedisContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER =
new ThreadLocal<>();
public static void setDataSource(String dataSource) {
CONTEXT_HOLDER.set(dataSource);
}
public static String getDataSource() {
return CONTEXT_HOLDER.get();
}
public static void clearDataSource() {
CONTEXT_HOLDER.remove();
}
}
@Configuration
public class DynamicRedisConfig {
@Bean
public RedisTemplate<String, Object> dynamicRedisTemplate(
RedisConnectionFactory dynamicRedisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(dynamicRedisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
@Bean
public RedisConnectionFactory dynamicRedisConnectionFactory(
@Qualifier("primaryRedisConnectionFactory")
RedisConnectionFactory primary,
@Qualifier("secondaryRedisConnectionFactory")
RedisConnectionFactory secondary) {
Map<Object, Object> targetConnectionFactories = new HashMap<>();
targetConnectionFactories.put("primary", primary);
targetConnectionFactories.put("secondary", secondary);
DynamicRedisConnectionFactory factory =
new DynamicRedisConnectionFactory();
factory.setDefaultTargetConnectionFactory(primary);
factory.setTargetConnectionFactories(targetConnectionFactories);
return factory;
}
}
四、Redis集群配置
1. 集群配置
yaml
spring:
redis:
cluster:
nodes:
- 192.168.1.101:7001
- 192.168.1.101:7002
- 192.168.1.102:7001
- 192.168.1.102:7002
- 192.168.1.103:7001
- 192.168.1.103:7002
max-redirects: 3 # 最大重定向次数
timeout: 5000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
2. 哨兵配置
yaml
spring:
redis:
sentinel:
master: mymaster
nodes:
- 192.168.1.101:26379
- 192.168.1.102:26379
- 192.168.1.103:26379
password: yourpassword
database: 0
timeout: 3000ms
3. Redis集群配置类
java
@Configuration
@ConditionalOnProperty(name = "spring.redis.cluster.nodes")
public class RedisClusterConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory(
RedisProperties properties) {
RedisClusterConfiguration clusterConfig =
new RedisClusterConfiguration(
properties.getCluster().getNodes()
);
if (properties.getPassword() != null) {
clusterConfig.setPassword(
RedisPassword.of(properties.getPassword())
);
}
LettuceClientConfiguration clientConfig =
LettuceClientConfiguration.builder()
.commandTimeout(properties.getTimeout())
.clientOptions(ClientOptions.builder()
.autoReconnect(true)
.disconnectedBehavior(
ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
.build())
.build();
return new LettuceConnectionFactory(clusterConfig, clientConfig);
}
}
五、高级特性配置
1. 发布订阅配置
java
@Configuration
public class RedisPubSubConfig {
@Bean
public RedisMessageListenerContainer redisContainer(
RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container =
new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// 订阅频道
container.addMessageListener(listenerAdapter,
new PatternTopic("news.*"));
container.addMessageListener(listenerAdapter,
new PatternTopic("logs.*"));
return container;
}
@Bean
public MessageListenerAdapter listenerAdapter(
RedisMessageReceiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Component
public static class RedisMessageReceiver {
public void receiveMessage(String message, String channel) {
System.out.println("收到消息: " + message + ",频道: " + channel);
}
}
}
2. Lua脚本支持
java
@Component
public class RedisScriptService {
@Autowired
private StringRedisTemplate redisTemplate;
// 限流脚本
private static final String RATE_LIMIT_SCRIPT =
"local key = KEYS[1]\n" +
"local limit = tonumber(ARGV[1])\n" +
"local window = tonumber(ARGV[2])\n" +
"local current = redis.call('GET', key)\n" +
"if current and tonumber(current) >= limit then\n" +
" return 0\n" +
"end\n" +
"current = redis.call('INCR', key)\n" +
"if tonumber(current) == 1 then\n" +
" redis.call('EXPIRE', key, window)\n" +
"end\n" +
"return 1";
private final RedisScript<Long> rateLimitScript =
new DefaultRedisScript<>(RATE_LIMIT_SCRIPT, Long.class);
public boolean tryAcquire(String key, int limit, int windowSeconds) {
Long result = redisTemplate.execute(
rateLimitScript,
Collections.singletonList(key),
String.valueOf(limit),
String.valueOf(windowSeconds)
);
return result != null && result == 1;
}
}
3. 分布式锁
java
@Component
public class RedisDistributedLock {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String LOCK_SCRIPT =
"if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then\n" +
" redis.call('pexpire', KEYS[1], ARGV[2])\n" +
" return 1\n" +
"else\n" +
" return 0\n" +
"end";
private static final String UNLOCK_SCRIPT =
"if redis.call('get', KEYS[1]) == ARGV[1] then\n" +
" return redis.call('del', KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
private final RedisScript<Long> lockScript =
new DefaultRedisScript<>(LOCK_SCRIPT, Long.class);
private final RedisScript<Long> unlockScript =
new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
public boolean tryLock(String lockKey, String requestId, long expireMillis) {
Long result = redisTemplate.execute(
lockScript,
Collections.singletonList(lockKey),
requestId,
String.valueOf(expireMillis)
);
return result != null && result == 1;
}
public boolean unlock(String lockKey, String requestId) {
Long result = redisTemplate.execute(
unlockScript,
Collections.singletonList(lockKey),
requestId
);
return result != null && result == 1;
}
}
六、性能优化配置
1. 连接池优化配置
yaml
spring:
redis:
lettuce:
pool:
# 最大连接数(根据业务量调整)
max-active: 20
# 最大空闲连接数
max-idle: 10
# 最小空闲连接数
min-idle: 5
# 最大等待时间(毫秒),-1表示无限等待
max-wait: 1000ms
# 关闭超时时间
shutdown-timeout: 100ms
# 连接超时时间
connect-timeout: 2000ms
# 命令超时时间
timeout: 5000ms
2. 客户端配置优化
java
@Configuration
public class RedisClientOptimizationConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory(
RedisProperties properties) {
RedisStandaloneConfiguration config =
new RedisStandaloneConfiguration();
config.setHostName(properties.getHost());
config.setPort(properties.getPort());
config.setPassword(
RedisPassword.of(properties.getPassword())
);
// 客户端优化配置
LettuceClientConfiguration clientConfig =
LettuceClientConfiguration.builder()
.useSsl() // 启用SSL
.and()
.commandTimeout(properties.getTimeout())
.shutdownTimeout(
properties.getLettuce().getShutdownTimeout()
)
.clientOptions(
ClientOptions.builder()
.autoReconnect(true)
.publishOnScheduler(true) // 在调度器上发布
.requestQueueSize(1000) // 请求队列大小
.socketOptions(
SocketOptions.builder()
.keepAlive(true)
.connectTimeout(
properties.getConnectTimeout()
)
.build()
)
.build()
)
.clientResources(
DefaultClientResources.builder()
.ioThreadPoolSize(4) // I/O线程数
.computationThreadPoolSize(4) // 计算线程数
.build()
)
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
}
七、监控配置
1. 健康检查配置
java
@Configuration
public class RedisHealthConfig {
@Bean
public RedisHealthIndicator redisHealthIndicator(
RedisConnectionFactory connectionFactory) {
return new RedisHealthIndicator(connectionFactory);
}
}
// 自定义健康检查
@Component
public class CustomRedisHealthIndicator
implements HealthIndicator {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public Health health() {
try {
String result = redisTemplate.execute(
(RedisCallback<String>) connection ->
connection.ping()
);
if ("PONG".equals(result)) {
return Health.up()
.withDetail("version", getRedisVersion())
.build();
}
return Health.down()
.withDetail("error", "Ping failed")
.build();
} catch (Exception e) {
return Health.down(e).build();
}
}
private String getRedisVersion() {
Properties info = redisTemplate
.execute((RedisCallback<Properties>) connection ->
connection.info("server")
);
return info.getProperty("redis_version");
}
}
2. 指标监控
java
@Configuration
public class RedisMetricsConfig {
@Bean
public MeterBinder redisMetrics(RedisConnectionFactory factory) {
return new RedisMetrics(factory);
}
@Bean
public RedisTemplate<String, String> redisTemplateForMetrics(
RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
template.setEnableTransactionSupport(true);
return template;
}
}
八、常用工具类
1. Redis工具类
java
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// ============================ Common ============================
public Boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
return false;
}
}
public Boolean delete(String key) {
return redisTemplate.delete(key);
}
public Long delete(Collection<String> keys) {
return redisTemplate.delete(keys);
}
public Boolean expire(String key, long time, TimeUnit unit) {
try {
if (time > 0) {
return redisTemplate.expire(key, time, unit);
}
return false;
} catch (Exception e) {
return false;
}
}
// ============================ String ============================
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public void set(String key, Object value, long time, TimeUnit unit) {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, unit);
} else {
set(key, value);
}
}
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
// ============================ Hash ==============================
public void hSet(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
public Object hGet(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
public Map<Object, Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
// ============================ List ==============================
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
return Collections.emptyList();
}
}
// ============================ Set ===============================
public Set<Object> sMembers(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
return Collections.emptySet();
}
}
// ============================ ZSet ==============================
public Set<Object> zRange(String key, long start, long end) {
try {
return redisTemplate.opsForZSet().range(key, start, end);
} catch (Exception e) {
return Collections.emptySet();
}
}
// ============================ Lock ==============================
public Boolean tryLock(String key, String value, long expireTime) {
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
return Boolean.TRUE.equals(result);
}
public void unlock(String key, String value) {
Object currentValue = redisTemplate.opsForValue().get(key);
if (value.equals(currentValue)) {
redisTemplate.delete(key);
}
}
}
九、配置文件示例
1. 生产环境配置(application-prod.yml)
yaml
spring:
redis:
host: ${REDIS_HOST:redis-cluster.prod.svc.cluster.local}
port: 6379
password: ${REDIS_PASSWORD:}
timeout: 3000ms
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
max-wait: 1000ms
shutdown-timeout: 100ms
# 集群配置
cluster:
nodes:
- redis-node-1:6379
- redis-node-2:6379
- redis-node-3:6379
max-redirects: 3
# SSL配置
ssl: true
2. 开发环境配置(application-dev.yml)
yaml
spring:
redis:
host: localhost
port: 6379
password:
timeout: 2000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: -1ms
database: 0
十、常见问题解决
1. 序列化问题
java
// 解决LocalDateTime序列化问题
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 解决LocalDateTime序列化
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(mapper, Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
return template;
}
2. 连接超时配置
java
@Configuration
public class RedisTimeoutConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config =
new RedisStandaloneConfiguration();
LettuceClientConfiguration clientConfig =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(5))
.shutdownTimeout(Duration.ofSeconds(1))
.clientOptions(
ClientOptions.builder()
.socketOptions(
SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(2))
.build()
)
.build()
)
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
}