redis存数字读出为字符串是默认行为,因客户端默认用stringredisserializer将数字转为字符串存储;改用genericjackson2jsonredisserializer可保留类型,但体积增大、性能下降且跨语言不友好。

Redis 里存的数字读出来变成字符串,不是 bug,是默认行为;改用 GenericJackson2JsonRedisSerializer 能解决,但得清楚它改了什么、代价在哪。
为什么 set("count", 123) 读出来是 "123"?
Redis 服务端本身只认字节流,不存类型信息。Java 客户端(如 Spring Data Redis)默认用 JdkSerializationRedisSerializer 或 StringRedisSerializer,前者把整数序列化成二进制 blob(带类信息),后者强制转成字符串——所以 redisTemplate.opsForValue().set("count", 123) 实际发给 Redis 的是字符串 "123"。
常见现象:
-
get("count")返回"123"(String 类型),强转Integer报ClassCastException -
incr("count")成功,但后续get("count")还是字符串,只是值变了 - 用
redis-cli看到的值是"123",object encoding count返回"int"——这是 Redis 内部优化,不影响客户端反序列化逻辑
改用 GenericJackson2JsonRedisSerializer 怎么配?
它把对象序列化为 JSON 字符串,保留原始类型(数字 → JSON number,字符串 → JSON string),反序列化时也能按字段类型还原。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
配置要点:
- 必须配合
@Data或显式 getter/setter,否则 Jackson 找不到字段 - 对简单类型(如
Integer、Long)直接可用,不需要包装类 - 要避免循环引用,否则序列化失败;可加
@JsonIgnore或配置SimpleModule - 示例配置片段:
@Bean
public RedisTemplate<string object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<string object> template = new RedisTemplate();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}</string></string>
用 GenericJackson2JsonRedisSerializer 的代价
它不是银弹,实际用起来有几个硬约束:
- 序列化后体积变大:
123变成"123"(多一对引号),复杂对象更明显 - 性能略低:JSON 解析比纯字节拷贝慢,高并发计数场景慎用
- 跨语言不友好:PHP/Go 客户端读这个 key 需要自己解析 JSON,不能直接当数字用
- 空值处理麻烦:
null字段默认被忽略,若需保留得配JsonInclude.Include.NON_NULL
真要存纯数字,还有更轻量的方案吗?
如果只是存 ID、计数这类简单整数,没必要上 JSON 序列化器:
- 统一用
StringRedisSerializer,读取后手动Integer.parseInt()——明确、可控、零额外开销 - 用 Redis 原生命令:如
INCR/DECR操作计数器,返回值本身就是 long,无需反序列化 - 自定义
IntegerRedisSerializer(参考知识库中IntegerRedisSerializer配置),但注意它不支持 null,且无法兼容其他类型
类型转换问题的本质,是客户端在「数据可读性」和「类型安全性」之间做的权衡。JSON 方案偏向后者,但代价得自己扛;而手动 parse 是多数业务更实际的选择——毕竟,你真的需要 Redis 帮你记住那个 123 是 int 还是 long 吗?










