以下是更详细的逐步指南,涵盖从零开始搭建Redis集群到Spring Boot集成的完整流程,配置好之后和单机使用是一样的:
一、Redis集群搭建(6节点,3主3从)
1. 安装Redis
# Ubuntu/Debian
sudo apt update
sudo apt install -y redis-server
# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y redis
# 验证安装
redis-server --version
2. 准备集群目录
# 创建集群节点目录
mkdir -p /opt/redis-cluster/{7000,7001,7002,7003,7004,7005}
3. 配置每个节点
每个端口目录下创建 redis.conf
,以 7000 为例:
cd /opt/redis-cluster/7000
vim redis.conf
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
bind 0.0.0.0 # 允许外部访问(生产环境需限制IP)
dir ./ # 数据存储目录
重复上述步骤,为7001-7005端口创建配置文件。
4. 启动所有节点
redis-server /opt/redis-cluster/7000/redis.conf
redis-server /opt/redis-cluster/7001/redis.conf
# ... 依次启动7002-7005
# 验证进程
ps -ef | grep redis
5. 创建集群
# 使用redis-cli自动分配主从
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
# 输入yes确认配置
6. 验证集群状态
# 检查节点信息
redis-cli -p 7000 cluster nodes
# 检查槽位分配
redis-cli --cluster check 127.0.0.1:7000
二、Spring Boot集成详细配置
1. 添加依赖 (pom.xml
)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 可选:若需要JSON序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2. 配置文件 (application.yml
)
spring:
redis:
cluster:
nodes:
- 192.168.1.100:7000
- 192.168.1.100:7001
- 192.168.1.100:7002
- 192.168.1.100:7003
- 192.168.1.100:7004
- 192.168.1.100:7005
max-redirects: 3 # 允许的最大跳转次数
password: your_password # 如果设置了密码
timeout: 3000 # 连接超时时间(毫秒)
lettuce:
pool:
max-active: 16 # 最大连接数
max-idle: 8 # 最大空闲连接
min-idle: 4 # 最小空闲连接
max-wait: 2000 # 获取连接最大等待时间(毫秒)
shutdown-timeout: 100ms # 关闭超时时间
3. 配置RedisTemplate
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用JSON序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
// Key使用String序列化
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
4. 编写操作类
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 基本操作
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// 使用Hash Tag确保数据在同一个slot
public void setWithHashTag(String userId, String value) {
String key = "{user:" + userId + "}:profile";
redisTemplate.opsForValue().set(key, value);
}
// 集群操作示例
public void printClusterInfo() {
RedisClusterConnection conn = (RedisClusterConnection) redisTemplate.getConnectionFactory().getConnection();
ClusterInfo clusterInfo = conn.clusterGetClusterInfo();
System.out.println("Cluster State: " + clusterInfo.getState());
}
}
三、验证集群操作
1. 编写测试用例
@SpringBootTest
public class RedisClusterTest {
@Autowired
private RedisService redisService;
@Test
void testClusterWriteRead() {
String key = "test:key1";
String value = "cluster_value";
// 写入数据
redisService.set(key, value);
// 读取数据
String result = (String) redisService.get(key);
Assertions.assertEquals(value, result);
}
@Test
void testHashTag() {
String userId = "1001";
String profile = "{'name':'John', 'age':28}";
redisService.setWithHashTag(userId, profile);
// 验证数据所在slot
RedisClusterConnection conn = (RedisClusterConnection) redisTemplate.getConnectionFactory().getConnection();
int slot = ClusterSlotHashUtil.calculateSlot("{user:1001}".getBytes());
System.out.println("Data stored in slot: " + slot);
}
}
四、故障排查指南
1. 连接失败检查
# 检查节点是否运行
ps -ef | grep redis
# 检查端口监听
netstat -tuln | grep 7000
# 测试节点可达性
telnet 192.168.1.100 7000
# 检查防火墙规则
sudo ufw status
2. Spring Boot日志调试
logging:
level:
org.springframework.data.redis: DEBUG
io.lettuce.core: WARN # 避免过多网络日志
3. 强制重新分配槽位
# 如果出现[ERR] Not all slots are covered
redis-cli --cluster fix 127.0.0.1:7000
五、生产环境优化
1. 安全加固
spring:
redis:
password: your_strong_password
ssl: true # 启用SSL加密
2. 高可用配置
spring:
redis:
cluster:
max-redirects: 5
lettuce:
cluster:
refresh:
adaptive: true # 自动发现拓扑变化
period: 5000 # 刷新间隔(毫秒)
3. 监控配置
# 使用redis-exporter监控
docker run -d --name redis-exporter \
-p 9121:9121 \
oliver006/redis_exporter \
--redis.addr=redis://192.168.1.100:7000 \
--redis.password=your_password
- Prometheus配置示例:
scrape_configs:
- job_name: 'redis_cluster'
static_configs:
- targets: ['192.168.1.100:9121']
六、关键注意事项
-
跨槽位操作限制
- 事务(Transaction)和Lua脚本只能在单个槽位执行
- 使用
hash tags
强制相关数据存储在同一个槽位
-
数据迁移
# 动态添加节点后迁移数据 redis-cli --cluster reshard 127.0.0.1:7000
-
备份策略
# 定期执行BGSAVE redis-cli -p 7000 bgsave # 备份RDB文件 cp /opt/redis-cluster/7000/dump.rdb /backup/
按照以上步骤操作后,您将拥有一个完整的Redis集群环境,并在Spring Boot中实现了高性能的缓存操作。遇到具体问题时,可根据日志和集群状态命令快速定位原因。