Skip to content

Spring集成Redis面试题库 ​

生成时间:2026-05-22 22:28


【面试题】1. Redis的String类型底层编码有哪几种?什么条件下会转换? ​

【标准答案】 String类型有三种编码:int、embstr、raw。

  • int:存储整数值且范围在long内(-2^63到2^63-1)
  • embstr:字符串长度≤44字节,一次内存分配,obj和sds连续存放
  • raw:字符串长度>44字节,两次内存分配,obj和sds分离

转换条件:整数运算结果超出long范围会转embstr;embstr做追加操作会转raw(因为embstr是只读的)。

面试加分点:Redis 3.2后embstr阈值从39改为44字节;int编码不完全是整数,要区分场景。


【面试题】2. Spring Data Redis中RedisTemplate和StringRedisTemplate有什么区别?生产中怎么选? ​

【标准答案】 核心区别:

  1. StringRedisTemplate继承自RedisTemplate<String, String>,强制String序列化
  2. RedisTemplate默认用JdkSerializationRedisSerializer,存入数据带类型信息,占用更大

生产选型:

  • 推荐StringRedisTemplate,配合JSON序列化,跨语言通用
  • 如果需要存复杂对象,自定义Jackson2JsonRedisSerializer
java
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

避坑:用默认JDK序列化,Redis-cli看到的是乱码,调试困难。


【面试题】3. Redis持久化RDB和AOF怎么选?线上怎么配置? ​

【标准答案】 RDB优点:文件小、恢复快、适合备份。缺点:可能丢数据(最后一次快照后的数据)。

AOF优点:数据更完整(默认每秒刷盘最多丢1秒)。缺点:文件大、恢复慢。

线上配置(推荐混合持久化):

save 900 1
save 300 10
save 60 10000
appendonly yes
aof-use-rdb-preamble yes
appendfsync everysec

选型依据:

  • 允许几分钟数据丢失:纯RDB
  • 要求高可用、最多丢1秒:AOF或混合
  • 纯缓存场景:可关闭持久化

面试加分:Redis 4.0后混合持久化成为默认推荐,兼顾恢复速度和数据完整性。


【面试题】4. Spring Cache的@Cacheable注解如何配置TTL?能动态设置吗? ​

【标准答案】 基础配置:

java
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
        .entryTtl(Duration.ofMinutes(30))
        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    return RedisCacheManager.builder(factory).cacheDefaults(config).build();
}

动态TTL方案:

java
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
    Map<String, RedisCacheConfiguration> cacheConfig = new HashMap<>();
    cacheConfig.put("user", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)));
    cacheConfig.put("product", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)));
    return RedisCacheManager.builder(factory)
        .withInitialCacheConfigurations(cacheConfig)
        .build();
}

使用时指定cacheNames:@Cacheable(value = "user", key = "#id")


【面试题】5. 缓存穿透、缓存击穿、缓存雪崩分别是什么?怎么解决? ​

【标准答案】 缓存穿透:查询不存在的数据,请求直达数据库。

  • 解决:布隆过滤器拦截、空值缓存(TTL设短)

缓存击穿:热点key过期瞬间大量请求打到数据库。

  • 解决:互斥锁(只让一个线程查库)、逻辑过期(不删缓存,后台异步更新)

缓存雪崩:大量key同时过期或Redis宕机。

  • 解决:TTL加随机值、多级缓存(本地+Redis)、熔断降级、Redis集群高可用

实战代码(互斥锁防击穿):

java
public String getWithMutex(String key) {
    String value = redisTemplate.opsForValue().get(key);
    if (value != null) return value;
    String lockKey = "lock:" + key;
    try {
        boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
        if (locked) {
            value = queryFromDB(key);
            redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
        } else {
            Thread.sleep(50);
            return getWithMutex(key); // 重试
        }
    } finally {
        redisTemplate.delete(lockKey);
    }
    return value;
}

【面试题】6. Redisson分布式锁的看门狗机制是什么?为什么要它? ​

【标准答案】 背景:锁设置过期时间后,如果业务执行超时,锁自动释放,其他线程获取锁,导致并发问题。

看门狗机制:Redisson默认锁30秒,后台线程每10秒检查一次,如果锁还被当前线程持有,自动续期到30秒。

核心源码逻辑:

java
RLock lock = redissonClient.getLock("myLock");
lock.lock(); // 默认30秒,自动续期
// 或
lock.lock(10, TimeUnit.SECONDS); // 手动指定时间,不续期

避坑点:

  • 手动指定leaseTime会关闭看门狗
  • 看门狗在业务异常退出时也能正常释放(持锁线程数为0时删除锁)
  • 程序崩溃时锁会在30秒后自动释放

面试加分:提Redisson实现是Lua脚本保证原子性,可重入锁用hash结构存线程ID和重入次数。


【面试题】7. Redis Cluster为什么用16384个槽位?节点通信用啥协议? ​

【标准答案】 为什么16384:

  • 槽位太少:节点多时分配不均匀
  • 槽位太多:节点握手时传递的槽位信息包太大(心跳包携带每个槽位归属)
  • 16384是权衡值:支持最多1000节点,每个节点心跳包最大约1KB

节点通信协议:Gossip协议。

  • 每个节点随机选部分节点交换信息
  • 包含:节点状态、槽位映射、故障检测信息
  • 频率:每秒10次,避免广播风暴

槽位迁移:

CLUSTER SETSLOT 1000 IMPORTING sourceNodeId
CLUSTER GETKEYSINSLOT 1000 100  # 获取槽位下的key
# 逐个迁移key
CLUSTER SETSLOT 1000 NODE targetNodeId

面试加分:提CLUSTER ADDSLOTS分配槽位,MOVED重定向是客户端缓存槽位映射的原理。


【面试题】8. 用Redis实现限流,固定窗口、滑动窗口、令牌桶有什么区别? ​

【标准答案】 固定窗口:简单但临界问题(1秒末+下1秒初可能突发2倍流量)。

lua
local count = redis.call('INCR', KEYS[1])
if count == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end
return count

滑动窗口:精确但内存占用大,用ZSET存储每个请求时间戳,ZRANGEBYSCORE统计窗口内请求数。

lua
local now = tonumber(ARGV[1])
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, now - tonumber(ARGV[2]))
local count = redis.call('ZCARD', KEYS[1])
redis.call('ZADD', KEYS[1], now, now)
redis.call('EXPIRE', KEYS[1], ARGV[2])
return count

令牌桶:允许突发流量,更灵活。Redisson内置RRateLimiter。

选型:

  • API限流:滑动窗口或令牌桶
  • 简单场景:固定窗口
  • 高性能场景:本地Guava限流 + Redis分布式限流结合

【面试题】9. Spring Session + Redis实现分布式Session共享的原理是什么? ​

【标准答案】 核心原理:

  1. Filter拦截请求,从Redis获取Session(按Session ID)
  2. 请求结束自动将Session变更写回Redis
  3. 多服务节点共享Redis,实现Session共享

配置:

java
@EnableRedisHttpSession
public class SessionConfig {
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }
}

存储结构:

  • Key:spring:session:sessions:sessionId
  • Hash结构存储:creationTime、lastAccessedTime、maxInactiveInterval、attrs

注意事项:

  • Session对象需要序列化
  • 配置TTL(maxInactiveIntervalInSeconds)
  • 大流量场景注意Redis压力,可结合本地缓存

面试加分:提Spring Session支持多种存储(Redis/JDBC/Mongo),同时支持WebSocket。


【面试题】10. Redis的BigKey和HotKey问题怎么排查和解决? ​

【标准答案】 BigKey问题:

  • 定义:String超过10KB,集合元素超过5000个
  • 危害:内存不均衡、网络阻塞、删除时卡顿

排查:

bash
redis-cli --bigkeys
MEMORY USAGE key

解决:

  • String类型:压缩(GZIP/Snappy)或拆分
  • 集合类型:按业务维度拆分(如用户ID取模)
  • 删除:UNLINK异步删除(4.0+)

HotKey问题:

  • 定义:单Key访问量极高
  • 危害:单节点压力过大、甚至超时

排查:

  • 代理层统计(Twemproxy)
  • 客户端统计
  • Redis 4.0 hotspot功能(需开启)

解决:

  • 本地缓存:Caffeine/Guava Cache
  • 复制HotKey到多个节点(加后缀)
  • 拆分为多个Key分散请求

实战:秒杀场景库存Key拆分为10份,用户随机路由。


共10题