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

Spring Data Redis读取含AtomicInteger缓存抛出类型转换异常如何解决?

错误根因

Spring Data Redis 默认的类型转换体系没有内置 byte[]/String 到 AtomicInteger 的转换逻辑:你写入缓存时 AtomicInteger 类型的 rate 字段会被序列化为普通数值字符串,读取时框架无法直接把数值字符串映射回 AtomicInteger 类型,因此抛出转换异常。

解决方案

方案1:调整字段类型(改动最小,适合低并发场景)

直接把实体类中的AtomicInteger字段改为Integer,仅在需要原子操作时转换为AtomicInteger处理:

@RedisHash(value = "ThottleRate", timeToLive = 5)
public class ThottleRate implements Serializable  {
    private static final long serialVersionUID = 1L;
    @Id
    private String url;
    // 改为Integer适配默认序列化规则
    private Integer rate;

    public ThottleRate(String url, int rate) {
        super();
        this.url = url;
        this.rate = rate;
    }

    public boolean isAllowed(){
        AtomicInteger atomicRate = new AtomicInteger(this.rate);
        int current = atomicRate.decrementAndGet();
        this.rate = current;
        return current > 0;
    }
}

注意:该方案的读-改-写逻辑存在并发安全问题,仅适合并发量不高的场景。

方案2:自定义类型转换器(保留原有字段定义,零业务逻辑改动)

自定义两个转换器处理AtomicInteger和String的互转,注册到Spring Data Redis的转换体系即可:

  1. 定义转换器类:
import org.springframework.core.convert.converter.Converter;
import java.util.concurrent.atomic.AtomicInteger;

// 读取缓存时用:String转AtomicInteger
public class StringToAtomicIntegerConverter implements Converter<String, AtomicInteger> {
    @Override
    public AtomicInteger convert(String source) {
        return new AtomicInteger(Integer.parseInt(source));
    }
}

// 写入缓存时用:AtomicInteger转String
public class AtomicIntegerToStringConverter implements Converter<AtomicInteger, String> {
    @Override
    public String convert(AtomicInteger source) {
        return source.toString();
    }
}
  1. 注册转换器到Redis配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import java.util.Arrays;

@Configuration
public class RedisConfig {
    @Bean
    public RedisCustomConversions redisCustomConversions() {
        return new RedisCustomConversions(Arrays.asList(
                new StringToAtomicIntegerConverter(),
                new AtomicIntegerToStringConverter()
        ));
    }
}

方案3:配置支持原子类的序列化器

使用Jackson序列化器并注册JDK类型支持模块,直接适配AtomicInteger等原子类的序列化:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisSerializerConfig {
    @Bean
    public RedisSerializer<Object> redisSerializer() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册JDK扩展类型模块,内置Atomic系列类的序列化逻辑
        objectMapper.registerModule(new JavaTimeModule());
        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }
}
可选优化

如果追求更高的限流性能和并发安全性,建议直接使用Redis原生的INCR+EXPIRE命令实现限流,无需定义实体类存储,性能更优且天然原子性。

内容的提问来源于stack exchange,提问作者Anton Cavanaugh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:45:05