Redis框架在项目中的实战

一、Redis 哨兵模式(Redis Sentinel)

Redis Sentinel 是 Redis 官方提供的高可用解决方案,核心作用是监控 Redis 主从集群、自动完成主从切换、通知客户端主节点变更,解决单机 Redis 宕机后无法自动恢复的问题。

Lettuce 是一款高性能、异步非阻塞的 Redis 客户端,基于 Netty 框架开发,也是 Spring Boot 2.x 及以上版本默认的 Redis 客户端客户端(Lettuce)只需配置哨兵节点地址和主节点名称,无需知道主从节点的具体地址,哨兵会自动告知客户端当前的主节点。

二、Lettuce 和Redission 如何选择

在实际项目中,Lettuce 和 Redisson 是互补使用的 ------Lettuce 作为底层高性能 Redis 客户端负责基础通信,Redisson 基于 Lettuce 封装了丰富的分布式数据结构和服务(如分布式锁、分布式 Map),既发挥 Lettuce 的性能优势,又利用 Redisson 简化业务开发。

  1. 依赖引入(pom.xml)
xml 复制代码
<!-- Spring Boot 整合 Redis(默认内置 Lettuce) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- Redisson 核心依赖(适配 Spring Boot) -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.0</version> <!-- 选稳定版本 -->
</dependency>
  • 配置文件:
yaml 复制代码
redis.lettuce.client.enable=true # 启用Lettuce客户端
# 连接池配置(核心)
redis.lettuce.client.pool.minIdle=6 # 最小空闲连接(保活)
redis.lettuce.client.pool.maxIdle=21 # 最大空闲连接
redis.lettuce.client.pool.maxTotal=100 # 最大连接数
redis.lettuce.client.pool.maxWaitMillis=4000 # 最大等待时间
redis.lettuce.client.sentinel.mastername=master # 监控的主节点名称
redis.lettuce.client.sentinel.password=***
redis.lettuce.client.sentinel.database=0
redis.lettuce.client.sentinel.nodeInfo[0]=10.193.114.0:26379 # 哨兵节点列表
redis.lettuce.client.sentinel.nodeInfo[0]=10.193.114.2:26379 # 哨兵节点列表
redis.lettuce.client.sentinel.nodeInfo[0]=10.193.114.3:26379 # 哨兵节点列表

三、代码示例

场景 1:用 Lettuce 做基础缓存读写(Spring RedisTemplate)

Spring Data Redis 封装了 Lettuce,提供 RedisTemplate 简化操作,这是项目中最基础的用法:

java 复制代码
@Component
public class CacheService {
    // 注入 Spring 封装的 RedisTemplate(底层是 Lettuce)
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // 存储合约基础信息(String 类型)
    public void setTestInfo(String testKey, Object testInfo) {
        // 底层通过 Lettuce 发送 SET 命令到 Redis 哨兵集群
        redisTemplate.opsForValue().set(
            testKey, 
            testInfo, 
            1, // 过期时间 1 小时
            TimeUnit.HOURS
        );
    }

    public Object getTestInfo(String testKey) {
        // 底层通过 Lettuce 发送 GET 命令
        return redisTemplate.opsForValue().get(testKey);
    }

    // 异步操作(Lettuce 核心优势,高并发场景用)
    public void setTestInfoAsync(String testKey, Object testInfo) {
        // 异步设置,不阻塞主线程(高并发场景推荐)
        redisTemplate.opsForValue().setAsync(testKey, testInfo);
    }
}

场景 2:用 Redisson 操作分布式 Map(对应你的 INFO:TEST_KEY)

Redisson 封装的 RMap 是分布式 Map,比 Lettuce 的 Hash 更易用,支持自动序列化 / 反序列化:

java 复制代码
@Component
public class TestMapService {
    // 注入 RedissonClient(底层复用 Lettuce 连接)
    @Resource
    private RedissonClient redissonClient;

    // 批量存储合约信息到分布式 Map
    public void batchSaveTestInfo(List<TestInfoPO> testList) {
        // 获取 Redis 中的分布式 Map(INFO:TEST_KEY)
        RMap<String, TestInfoPO> testMap = 
            redissonClient.getMap("INFO:TEST_KEY");
        
        // 批量存入:INFO:TEST_KEY
        testList.forEach(d -> {
            String key = ...
            testMap.put(key, d); // 原子操作,线程安全
        });
    }

    // 获取单个test信息
    public TestInfoPO getTestInfo(String testId) {
        RMap<String, TestInfoPO> testMap = redissonClient.getMap("INFO:TEST_KEY");
        String key = ...;
        return testMap.get(key);
    }
}

场景 3:用 Redisson 实现分布式锁(防并发修改)

java 复制代码
@Component
public class UpdateService {
    @Resource
    private RedissonClient redissonClient;

    // 修改(加分布式锁)
    public void updateTestInfo(String testtId, TestInfoPO newInfo) {
        // 1. 定义锁的唯一标识
        String lockKey = "lock:test:update:" + testId;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 2. 获取锁:最多等5秒,持有锁10秒(自动释放,防止死锁)
            boolean locked = lock.tryLock(5, 10, TimeUnit.SECONDS);
            if (!locked) {
                throw new RuntimeException("正在修改中,请稍后重试");
            }

            // 3. 执行业务逻辑
            // ... 你的更新数据库/缓存逻辑 ...

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("获取锁失败", e);
        } finally {
            // 4. 释放锁(必须在 finally 中,防止锁泄露)
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

四、项目中的最佳实践

  1. 分工明确:简单的缓存读写(String/Hash)用 RedisTemplate(底层 Lettuce);
  2. 分布式锁、分布式集合、延迟队列等复杂场景用 Redisson;
  3. 复用连接池:让 Redisson 复用 Lettuce 的连接池配置,避免重复创建连接;
  4. 异步优先:高并发场景(如期货行情缓存)用 Lettuce 的异步 API(setAsync/getAsync),提升吞吐量;
  5. 锁的规范:分布式锁必须设置超时时间,且在 finally 中释放,防止死锁;
  6. 序列化配置:统一配置 RedisTemplate 的序列化方式(如 Jackson2JsonRedisSerializer),避免乱码:
java 复制代码
@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);
        template.setValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}
相关推荐
小高不会迪斯科12 小时前
CMU 15445学习心得(二) 内存管理及数据移动--数据库系统如何玩转内存
数据库·oracle
e***89012 小时前
MySQL 8.0版本JDBC驱动Jar包
数据库·mysql·jar
l1t12 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
失忆爆表症14 小时前
03_数据库配置指南:PostgreSQL 17 + pgvector 向量存储
数据库·postgresql
AI_567814 小时前
Excel数据透视表提速:Power Query预处理百万数据
数据库·excel
SQL必知必会14 小时前
SQL 窗口帧:ROWS vs RANGE 深度解析
数据库·sql·性能优化
Gauss松鼠会15 小时前
【GaussDB】GaussDB数据库开发设计之JDBC高可用性
数据库·数据库开发·gaussdb
+VX:Fegn089515 小时前
计算机毕业设计|基于springboot + vue鲜花商城系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
程序猿阿伟15 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
识君啊15 小时前
SpringBoot 事务管理解析 - @Transactional 的正确用法与常见坑
java·数据库·spring boot·后端