SpringBoot 整合 Redis 缓存

Redis 作为最主流的分布式缓存,几乎是 SpringBoot 项目的"标配"------无论是减轻数据库压力、提升接口响应速度,还是实现会话共享、分布式锁,都离不开它。

本篇文章就来介绍一下 SpringBoot 整合 Redis的操作步骤, 同时讲讲Redis中 String、Hash、List、Set、ZSet 五种核心数据类型 的增删改查,还有缓存失效、序列化配置、注意事项等。


一、为什么用 Redis 做缓存?

在项目中引入 Redis,核心解决两个核心问题:

  • 减轻数据库压力:把高频查询数据(如用户信息、商品列表)缓存到 Redis,避免每次请求都查数据库,接口响应速度从毫秒级提升到微秒级;

  • 支持多种场景:除了缓存,还能实现分布式锁、计数器、限流、消息队列(简单场景)、排行榜等功能;

  • 高性能、高可用:Redis 基于内存操作,读写速度极快,支持主从复制、哨兵模式,稳定性拉满。


二、第一步:引入依赖

SpringBoot 提供了专门的 Redis 启动器,无需手动配置复杂依赖,直接引入即可:

go 复制代码
<!-- SpringBoot Redis 启动器 -->
<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>

<!-- Lombok  -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

说明spring-boot-starter-data-redis 底层已经集成了 Redis 客户端(默认 Lettuce,替代了早期的 Jedis),配合 commons-pool2 连接池,性能更优。


三、第二步:application.yml 核心配置

配置 Redis 连接信息、连接池、序列化方式:

go 复制代码
spring:
  redis:
    # Redis 服务器地址(本地/线上地址)
    host: localhost
    # 端口(默认6379)
    port: 6379
    # 密码(如果没设置密码,注释掉即可)
    password: 123456
    # 数据库索引(Redis 默认有16个库,0-15,可按需切换)
    database: 0
    # 超时时间(连接、读取、写入超时,单位毫秒)
    timeout: 5000
    # 连接池配置(Lettuce 连接池)
    lettuce:
      pool:
        # 最大连接数(核心,根据业务压测调整,默认8)
        max-active: 100
        # 最大空闲连接
        max-idle: 20
        # 最小空闲连接
        min-idle: 5
        # 连接等待超时时间(毫秒)
        max-wait: 1000

# 自定义 Redis 序列化配置(避免缓存乱码,可选但推荐)
redis:
  serialization:
    key-prefix: "springboot:redis:"  # 缓存key前缀,避免不同项目key冲突
    expire-default: 3600  # 默认缓存过期时间(秒),1小时

四、第三步:Redis 序列化配置

SpringBoot 默认的 Redis 序列化方式会导致缓存的 key、value 乱码,不利于调试,我们自定义配置,使用 JSON 序列化,兼顾可读性和性能:

go 复制代码
package com.demo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
@ConfigurationProperties(prefix = "redis.serialization")
public class RedisConfig {

    // 缓存key前缀
    private String keyPrefix;
    // 默认缓存过期时间(秒)
    private Long expireDefault;

    // 1. 配置 RedisTemplate(操作Redis的核心工具类)
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        // 配置key序列化(String类型,避免乱码)
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        // 配置value序列化(JSON类型,可读性强,支持对象)
        GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setValueSerializer(jsonSerializer);
        redisTemplate.setHashValueSerializer(jsonSerializer);

        // 初始化参数
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    // 2. 配置 RedisCacheManager(配合@Cacheable注解使用,缓存管理)
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        // 基础配置(序列化、过期时间)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 过期时间
                .entryTtl(Duration.ofSeconds(expireDefault))
                // key序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // value序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                // 允许缓存null值(可选,根据业务调整)
                .disableCachingNullValues();

        // 自定义不同缓存的过期时间(可选)
        Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();
        // 比如:用户缓存过期时间2小时,商品缓存过期时间1小时
        cacheConfigs.put("userCache", config.entryTtl(Duration.ofSeconds(7200)));
        cacheConfigs.put("productCache", config.entryTtl(Duration.ofSeconds(3600)));

        // 构建缓存管理器
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .withInitialCacheConfigurations(cacheConfigs)
                .build();
    }

    // getter/setter(Lombok可省略)
    public String getKeyPrefix() {
        return keyPrefix;
    }

    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    public Long getExpireDefault() {
        return expireDefault;
    }

    public void setExpireDefault(Long expireDefault) {
        this.expireDefault = expireDefault;
    }
}

五、Redis 五种数据类型操作

我们通过 RedisTemplate 操作 Redis,下面分别实战 String、Hash、List、Set、ZSet 五种核心数据类型,每种类型都包含「增、删、改、查」完整用法,可直接复制到项目中使用。

1. String 类型(最常用,适合单个值、字符串、对象缓存)

适用场景:用户信息、验证码、令牌、单个数值(如计数器),是最基础、最常用的类型。

go 复制代码
package com.demo.service;

import com.demo.entity.User;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class RedisStringService {

    private final RedisTemplate<String, Object> redisTemplate;
    // 从配置文件读取key前缀
    private final RedisConfig redisConfig;

    // 拼接key(避免重复,规范写法)
    private String getKey(String key) {
        return redisConfig.getKeyPrefix() + key;
    }

    // 1. 新增String缓存(无过期时间)
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(getKey(key), value);
    }

    // 2. 新增String缓存(带过期时间)
    public void setWithExpire(String key, Object value, Long expireTime, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(getKey(key), value, expireTime, timeUnit);
    }

    // 3. 获取String缓存
    public Object get(String key) {
        return redisTemplate.opsForValue().get(getKey(key));
    }

    // 4. 修改String缓存(直接覆盖)
    public void update(String key, Object value) {
        this.set(key, value);
    }

    // 5. 删除String缓存
    public Boolean delete(String key) {
        return redisTemplate.delete(getKey(key));
    }

    // 6. 自增(计数器场景,如文章阅读量、点赞数)
    public Long increment(String key, Long delta) {
        return redisTemplate.opsForValue().increment(getKey(key), delta);
    }

    // 7. 自减
    public Long decrement(String key, Long delta) {
        return redisTemplate.opsForValue().decrement(getKey(key), delta);
    }

    // 实战示例:缓存用户信息
    public void cacheUser(User user) {
        // 缓存key:springboot:redis:user:1(1是用户ID)
        String key = "user:" + user.getId();
        // 过期时间:2小时(7200秒)
        this.setWithExpire(key, user, 7200L, TimeUnit.SECONDS);
    }

    // 实战示例:获取缓存的用户信息
    public User getCachedUser(Long userId) {
        String key = "user:" + userId;
        return (User) this.get(key);
    }
}

2. Hash 类型(适合存储对象,可单独操作对象字段)

适用场景:用户信息、商品信息等对象缓存,无需修改整个对象,可单独修改某个字段(如用户昵称、商品库存),节省内存和带宽。

go 复制代码
package com.demo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class RedisHashService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisConfig redisConfig;

    private String getKey(String key) {
        return redisConfig.getKeyPrefix() + key;
    }

    // 获取Hash操作对象
    private HashOperations<String, String, Object> getHashOps() {
        return redisTemplate.opsForHash();
    }

    // 1. 新增Hash缓存(存储整个对象,key是对象标识,hashKey是字段名)
    public void putAll(String key, Map<String, Object> hashMap) {
        String redisKey = getKey(key);
        getHashOps().putAll(redisKey, hashMap);
        // 设置过期时间
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
    }

    // 2. 新增单个Hash字段
    public void put(String key, String hashKey, Object value) {
        String redisKey = getKey(key);
        getHashOps().put(redisKey, hashKey, value);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
    }

    // 3. 获取单个Hash字段值
    public Object get(String key, String hashKey) {
        return getHashOps().get(getKey(key), hashKey);
    }

    // 4. 获取整个Hash对象(所有字段和值)
    public Map<String, Object> getAll(String key) {
        return getHashOps().entries(getKey(key));
    }

    // 5. 获取所有Hash字段名
    public Set<String> getHashKeys(String key) {
        return getHashOps().keys(getKey(key));
    }

    // 6. 修改单个Hash字段
    public void update(String key, String hashKey, Object value) {
        this.put(key, hashKey, value);
    }

    // 7. 删除单个Hash字段
    public Long delete(String key, String... hashKeys) {
        return getHashOps().delete(getKey(key), (Object[]) hashKeys);
    }

    // 实战示例:缓存用户信息(Hash类型)
    public void cacheUserHash(Long userId, Map<String, Object> userMap) {
        // 缓存key:springboot:redis:user:hash:1
        String key = "user:hash:" + userId;
        this.putAll(key, userMap);
    }

    // 实战示例:修改用户昵称(单独修改Hash字段)
    public void updateUserName(Long userId, String newName) {
        String key = "user:hash:" + userId;
        this.put(key, "username", newName);
    }
}

3. List 类型(有序、可重复,适合队列、列表场景)

适用场景:消息队列(简单场景)、最新列表、历史记录(如浏览记录、消息列表),支持从头部、尾部插入/删除数据。

go 复制代码
package com.demo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class RedisListService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisConfig redisConfig;

    private String getKey(String key) {
        return redisConfig.getKeyPrefix() + key;
    }

    // 获取List操作对象
    private ListOperations<String, Object> getListOps() {
        return redisTemplate.opsForList();
    }

    // 1. 从列表头部插入数据
    public Long leftPush(String key, Object value) {
        String redisKey = getKey(key);
        Long result = getListOps().leftPush(redisKey, value);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
        return result;
    }

    // 2. 从列表尾部插入数据
    public Long rightPush(String key, Object value) {
        String redisKey = getKey(key);
        Long result = getListOps().rightPush(redisKey, value);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
        return result;
    }

    // 3. 从列表头部弹出数据(弹出后删除)
    public Object leftPop(String key) {
        return getListOps().leftPop(getKey(key));
    }

    // 4. 从列表尾部弹出数据(弹出后删除)
    public Object rightPop(String key) {
        return getListOps().rightPop(getKey(key));
    }

    // 5. 获取列表指定范围的数据(start=0,end=-1 表示所有数据)
    public List<Object> range(String key, Long start, Long end) {
        return getListOps().range(getKey(key), start, end);
    }

    // 6. 获取列表长度
    public Long size(String key) {
        return getListOps().size(getKey(key));
    }

    // 7. 删除列表中指定值(count=0删除所有,count=1删除第一个,count=-1删除最后一个)
    public Long remove(String key, Long count, Object value) {
        return getListOps().remove(getKey(key), count, value);
    }

    // 实战示例:存储用户浏览记录(从尾部插入,保留最新10条)
    public void addBrowseRecord(Long userId, String productId) {
        String key = "browse:record:" + userId;
        // 从尾部插入最新浏览的商品ID
        this.rightPush(key, productId);
        // 限制列表长度,只保留最新10条
        Long size = this.size(key);
        if (size > 10) {
            // 从头部删除多余数据
            this.leftPop(key);
        }
    }

    // 实战示例:获取用户最新浏览记录
    public List<Object> getBrowseRecords(Long userId) {
        String key = "browse:record:" + userId;
        // 获取所有浏览记录(从第0条到最后一条)
        return this.range(key, 0L, -1L);
    }
}

四、Set 类型(无序、不可重复的集合)

Set 是 Redis 中一种无序元素不可重复 的数据结构。它非常适合处理需要去重 、计算交集/并集的场景。

🎯 核心适用场景

  • 标签系统:用户标签、商品标签等。

  • 数据去重:例如去重的用户ID集合。

  • 社交关系:好友列表、共同好友(交集)、推荐好友(差集)。

下面是一个完整的 RedisSetService 服务类,封装了 Set 的常用操作。

go 复制代码
package com.demo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;

import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class RedisSetService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisConfig redisConfig;

    private String getKey(String key) {
        return redisConfig.getKeyPrefix() + key;
    }

    // 获取Set操作对象
    private SetOperations<String, Object> getSetOps() {
        return redisTemplate.opsForSet();
    }

    // 1. 向Set中添加数据(可添加多个)
    public Long add(String key, Object... values) {
        String redisKey = getKey(key);
        Long result = getSetOps().add(redisKey, values);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
        return result;
    }

    // 2. 获取Set中所有数据
    public Set<Object> members(String key) {
        return getSetOps().members(getKey(key));
    }

    // 3. 判断数据是否在Set中(去重校验)
    public Boolean isMember(String key, Object value) {
        return getSetOps().isMember(getKey(key), value);
    }

    // 4. 删除Set中的指定数据
    public Long remove(String key, Object... values) {
        return getSetOps().remove(getKey(key), values);
    }

    // 5. 获取Set的长度
    public Long size(String key) {
        return getSetOps().size(getKey(key));
    }

    // 6. 交集(两个Set的共同数据,如共同好友)
    public Set<Object> intersect(String key1, String key2) {
        return getSetOps().intersect(getKey(key1), getKey(key2));
    }

    // 7. 并集(两个Set的所有数据,去重)
    public Set<Object> union(String key1, String key2) {
        return getSetOps().union(getKey(key1), getKey(key2));
    }

    // 实战示例:给用户添加标签(去重)
    public void addUserTag(Long userId, String... tags) {
        String key = "user:tag:" + userId;
        this.add(key, tags);
    }

    // 实战示例:获取用户所有标签
    public Set<Object> getUserTags(Long userId) {
        String key = "user:tag:" + userId;
        return this.members(key);
    }

    // 实战示例:获取两个用户的共同标签
    public Set<Object> getCommonTags(Long userId1, Long userId2) {
        String key1 = "user:tag:" + userId1;
        String key2 = "user:tag:" + userId2;
        return this.intersect(key1, key2);
    }
}

五、ZSet 类型(有序集合)

ZSet (Sorted Set) 在 Set 的基础上,为每个元素关联了一个 分数(score) ,并根据分数进行排序。它是实现排行榜功能的绝佳选择。

🎯 核心适用场景

  • 各类排行榜:商品销量榜、文章点赞榜、用户积分榜、游戏高分榜。

以下 RedisZSetService 展示了 ZSet 的核心操作和排行榜实现。

go 复制代码
package com.demo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class RedisZSetService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RedisConfig redisConfig;

    private String getKey(String key) {
        return redisConfig.getKeyPrefix() + key;
    }

    // 获取ZSet操作对象
    private ZSetOperations<String, Object> getZSetOps() {
        return redisTemplate.opsForZSet();
    }

    // 1. 向ZSet中添加数据(指定分数)
    public Boolean add(String key, Object value, Double score) {
        String redisKey = getKey(key);
        Boolean result = getZSetOps().add(redisKey, value, score);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
        return result;
    }

    // 2. 批量添加ZSet数据
    public Long addBatch(String key, Set<ZSetOperations.TypedTuple<Object>> tuples) {
        String redisKey = getKey(key);
        Long result = getZSetOps().add(redisKey, tuples);
        redisTemplate.expire(redisKey, redisConfig.getExpireDefault(), TimeUnit.SECONDS);
        return result;
    }

    // 3. 增加元素的分数(如点赞数+1、积分+10)
    public Double incrementScore(String key, Object value, Double delta) {
        return getZSetOps().incrementScore(getKey(key), value, delta);
    }

    // 4. 按分数升序排序,获取指定范围的数据
    public Set<ZSetOperations.TypedTuple<Object>> rangeByScore(String key, Double min, Double max) {
        return getZSetOps().rangeByScoreWithScores(getKey(key), min, max);
    }

    // 5. 按分数降序排序,获取指定范围的数据(排行榜常用,如前10名)
    public Set<ZSetOperations.TypedTuple<Object>> reverseRangeByScore(String key, Double min, Double max, Long start, Long end) {
        return getZSetOps().reverseRangeByScoreWithScores(getKey(key), min, max, start, end);
    }

    // 6. 获取元素的分数
    public Double score(String key, Object value) {
        return getZSetOps().score(getKey(key), value);
    }

    // 7. 获取ZSet的长度
    public Long size(String key) {
        return getZSetOps().size(getKey(key));
    }

    // 8. 删除ZSet中的指定元素
    public Long remove(String key, Object... values) {
        return getZSetOps().remove(getKey(key), values);
    }

    // 实战示例:商品销量排行榜(降序,取前10名)
    public Set<ZSetOperations.TypedTuple<Object>> getProductSalesTop10() {
        String key = "product:sales:rank";
        // 分数从0到无穷大,取前10名,降序排列
        return this.reverseRangeByScore(key, 0.0, Double.MAX_VALUE, 0L, 9L);
    }

    // 实战示例:更新商品销量(销量+1,分数+1)
    public void updateProductSales(String productId) {
        String key = "product:sales:rank";
        this.incrementScore(key, productId, 1.0);
    }
}

六、@Cacheable 注解缓存

如果业务场景只是简单的 "查询-缓存" ,无需复杂的 Redis 操作,强烈推荐使用 Spring 提供的 @Cacheable 注解。它能自动实现 "查询数据库 → 存入缓存 → 后续命中缓存" 的完整流程,极大简化代码。

💡 核心注解说明

  • @Cacheable:在方法执行前检查缓存,命中则直接返回,未命中则执行方法并将结果存入缓存。

  • @CachePut :无论缓存是否存在,都会执行方法,并用结果更新缓存。常用于更新操作。

  • @CacheEvict删除指定缓存。常用于删除操作。

go 复制代码
package com.demo.service;

import com.demo.entity.User;
import com.demo.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserCacheService {

    private final UserMapper userMapper;

    // 1. @Cacheable:查询时缓存,key是用户ID,缓存名称是userCache(对应RedisCacheManager配置)
    @Cacheable(value = "userCache", key = "#userId", unless = "#result == null")
    public User getUserById(Long userId) {
        // 若缓存中没有,才会执行此方法(查询数据库)
        return userMapper.selectById(userId);
    }

    // 2. @CachePut:更新数据时,同步更新缓存(保证缓存与数据库一致)
    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        userMapper.updateById(user);
        return user;
    }

    // 3. @CacheEvict:删除数据时,删除对应的缓存
    @CacheEvict(value = "userCache", key = "#userId")
    public void deleteUser(Long userId) {
        userMapper.deleteById(userId);
    }
}

重要提示 :使用 @Cacheable 等注解,必须 在 SpringBoot 启动类上添加 @EnableCaching 注解来开启缓存功能。


七、注意事项

从开发到上线,以下要点能帮你避开大多数"坑"。

问题 现象与风险 解决方案
1. 缓存乱码 读取出的值是乱码或无法反序列化。 必须配置自定义序列化 (如 Jackson2JsonRedisSerializer),避免使用默认的 JdkSerializationRedisSerializer。
2. 缓存穿透 查询一个数据库中根本不存在的数据,导致请求直达数据库。 1. 缓存空值(null)并设置较短过期时间。 2. 使用布隆过滤器预先校验。
3. 缓存击穿 某个热点Key突然过期,大量并发请求瞬间涌向数据库。 1. 设置热点Key永不过期 。 2. 使用互斥锁(Mutex),只让一个线程去查库,其他线程等待。
4. 缓存雪崩 大量Key在同一时间过期,导致所有请求落库,数据库压力骤增。 1. 给缓存过期时间加上随机值 ,分散过期时间。 2. 核心数据永不过期,通过后台任务异步更新。
5. Key命名规范 不同项目或模块的Key冲突,导致数据错乱。 统一添加前缀 ,如 项目名:模块名:业务名:id
6. 过期时间设置 过长占用内存,过短导致缓存命中率低。 根据业务特点设置,高频变化数据 时间短,低频稳定数据时间长。
7. Redis安全 线上环境未设密码,导致被恶意攻击或数据泄露。 必须设置强密码 ,并配置防火墙限制访问IP。
8. 连接池配置 高并发下连接池耗尽,出现获取连接超时错误。 根据压测结果,合理调整 max-activemax-idlemin-idle 等参数。

大家在项目中用 Redis 时,有没有遇到过缓存穿透、雪崩的"惊险"时刻?或者有什么独家的 Redis 调优技巧?

欢迎在评论区留言交流,分享你的实战经验~ 关注我 ,后续持续更新 SpringBoot 实战教程,从基础到高级,带你轻松搞定后端开发,少踩坑、多高效,我们下期再见!

相关推荐
Counter-Strike大牛14 小时前
SpringBoot中使用POI+EasyExcel批量导出主子表信息,以箱单为例
windows·spring boot·后端
医疗信息化王工14 小时前
基于ASP.NET Core的医院不良事件管理系统的架构设计
后端·asp.net
小谢小哥14 小时前
53-熔断降级详解
java·后端·架构
满天星830357714 小时前
【Linux/多路复用】poll和epoll的使用
linux·服务器·c++·后端
覆东流14 小时前
第6天:python综合练习——制作简易计算器
开发语言·后端·python
CodeMartain15 小时前
shardingsphere-spring 实现数据分片(一)
java·后端·spring
rleS IONS15 小时前
Redis五种用途
数据库·redis·缓存
Kiyra15 小时前
为什么远程调用别包进 Spring 事务里
java·后端·spring
武子康15 小时前
大数据-277 Spark MLib-梯度提升树(GBDT)算法原理与工程实现指南
大数据·后端·spark
空中海16 小时前
Redis 原理深度解析:持久化 × 主从复制 × Sentinel × Cluster × 性能排查全攻略
数据库·redis·sentinel