You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot下Redis缓存无法获取所有键?匹配异常问题咨询

问题原因分析

1. RedisTemplate默认序列化器导致keys("*")返回空

你使用的Spring Boot 1.5.6版本中,默认的RedisTemplate采用JdkSerializationRedisSerializer作为键和值的序列化器。这会带来两个关键影响:

  • 当你调用getTestObject("Joe")时,缓存的键会被序列化成JDK序列化后的字节数组(而非明文字符串"Joe")存储在Redis中。
  • 执行redisTemplate.keys("*")时,RedisTemplate会先把字符串"*"用相同的序列化器转成字节数组,再发送给Redis执行KEYS命令。Redis会基于这个序列化后的字节数组模式去匹配键,但实际存储的键是序列化后的"Joe"字节数组,两者没有匹配关系,因此返回0个键。

2. 对hasKey方法的行为误解

Redis的HASKEY命令是精确匹配键,完全不支持通配符。你测试中hasKey("J*e")返回true,说明你的Redis中确实存在一个序列化后的"J*e"键——大概率是你之前调用过getTestObject("J*e"),导致该键被缓存。而Jo*、*oe、*返回false,是因为Redis中没有对应的精确键。

3. 为什么hasKey("Joe")返回true?

当你调用hasKey("Joe")时,RedisTemplate会把字符串"Joe"用Jdk序列化器转成和缓存时一致的字节数组,去Redis中精确匹配,因此能找到对应的键,返回true。

解决方法

方法1:替换为字符串序列化器(推荐用于可视化需求)

如果你希望键以明文字符串形式存储,方便直接用Redis客户端查询,可以自定义RedisTemplate,指定键序列化器为StringRedisSerializer:

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 设置键和哈希键为字符串序列化器
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        // 值序列化器可根据需求选择,比如JSON序列化器
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        template.afterPropertiesSet();
        return template;
    }
}

方法2:绕过序列化直接执行原生命令

如果你不想修改序列化器,可以通过RedisCallback直接执行原生KEYS命令,手动处理序列化:

RedisTemplate redisTemplate = (RedisTemplate) cacheManager.getCache("test").getNativeCache();
Set<Object> keys = redisTemplate.execute((RedisCallback<Set<Object>>) connection -> {
    // 直接发送字节数组形式的"*",避免RedisTemplate自动序列化
    Set<byte[]> keyBytes = connection.keys("*".getBytes());
    // 用键序列化器反序列化字节数组,得到原始键值
    return keyBytes.stream()
            .map(redisTemplate.getKeySerializer()::deserialize)
            .collect(Collectors.toSet());
});

方法3:用SCAN替代KEYS(大键量场景推荐)

KEYS命令在Redis键数量较多时会阻塞服务器,推荐使用SCAN命令迭代查询:

RedisTemplate redisTemplate = (RedisTemplate) cacheManager.getCache("test").getNativeCache();
Set<Object> keys = new HashSet<>();
redisTemplate.execute((RedisCallback<Void>) connection -> {
    ScanOptions options = ScanOptions.scanOptions().match("*").count(100).build();
    Cursor<byte[]> cursor = connection.scan(options);
    while (cursor.hasNext()) {
        keys.add(redisTemplate.getKeySerializer().deserialize(cursor.next()));
    }
    return null;
});

内容的提问来源于stack exchange,提问作者Don Rhummy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:43:52