Redis 集群结构

以下是更详细的逐步指南,涵盖从零开始搭建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']

六、关键注意事项

  1. 跨槽位操作限制

    • 事务(Transaction)和Lua脚本只能在单个槽位执行
    • 使用hash tags强制相关数据存储在同一个槽位
  2. 数据迁移

    # 动态添加节点后迁移数据
    redis-cli --cluster reshard 127.0.0.1:7000
    
  3. 备份策略

    # 定期执行BGSAVE
    redis-cli -p 7000 bgsave
    # 备份RDB文件
    cp /opt/redis-cluster/7000/dump.rdb /backup/
    

按照以上步骤操作后,您将拥有一个完整的Redis集群环境,并在Spring Boot中实现了高性能的缓存操作。遇到具体问题时,可根据日志和集群状态命令快速定位原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值