Spring-RedisTemplate写入数据乱码问题的复现与解决

告别开发“坐牢”:Spring Boot集成Redis缓存实战多练辅助方法论 缓存是提升系统性能、降低数据库负载的核心技术之一,其原理是将高频访问的数据存储在更快的介质中,减少对后端数据源的直接访问。在分布式系统中,缓存技术对于应对高并发场景、保障系统响应速度具有关键价值,广泛应用于电商秒杀、社交动态、内容推荐等场景。然而,在实际集成缓存时,开发者常因环境配置、缓存穿透、数据一致性等问题陷入调试困境,即所谓的“坐牢”状态。本文以Spring Boot集成Redis为具体案例,系统性地演示了如何通过**环境辅助****任务拆解**的方法论,将复杂的技术集成过程工程化,从搭建可复现的D 阅读详情

org.springframework.data.redis是Spring框架对Redis的默认集成,我们在实际项目中,也经常使用它的RedisTemplate去操作Redis,一般来说没什么问题,但是细心一点的同学会发现,经过这种方法写入redis的数据会出现乱码问题

问题复现

项目依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Redis配置

  • yaml文件配置
spring:
  application:
    name: booklet-redis
  redis:
    host: 127.0.0.1
    port: 6379
    password: adminadmin
    timeout: 5000ms

  • Redis配置类

package com.liumapp.booklet.redis.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * 注入 RedisConnectionFactory
     */
    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisTemplate<String,Object> functionDomainRedisTemplate() {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式
     *
     * @param redisTemplate
     * @param factory
     */
    private void initDomainRedisTemplate(RedisTemplate<String,Object> redisTemplate, RedisConnectionFactory factory) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
    }
    /**
     * 实例化 HashOperations 对象,可以使用 Hash 类型操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /**
     * 实例化 ValueOperations 对象,可以使用 String 操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /**
     * 实例化 ListOperations 对象,可以使用 List 操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();

    }

    /**
     * 实例化 SetOperations 对象,可以使用 Set 操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /**
     * 实例化 ZSetOperations 对象,可以使用 ZSet 操作
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

测试代码

package com.liumapp.booklet.redis;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = BookletRedisMain.class)
@RunWith(SpringRunner.class)
public class BookletRedisMainTest {

    @Resource
    private ListOperations<String, Object> listOperations;

    @Test
    public void leftPushTest () {
        List<String> list = new ArrayList<>();
        list.add("hello world");
        listOperations.leftPush("listKey", list);
    }

}

运行上述测试代码后,我们会在redis中插入一组list类型的数据,其key为listKey,value为只有一个元素的list对象

接下来我们通过redis-cli去获取listKey这个值,可以看到乱码的出现:

127.0.0.1:6379> LRANGE listKey 0 10
1) "\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x01w\x04\x00\x00\x00\x01t\x00\x0bhello worldx"

当然,这对于我们项目的实际使用没有什么影响,在程序中再次获取listKey也不会出现乱码,只有通过redis-cli等工具直接取值的时候,才会出现乱码

问题出现原因

问题原因在于我们对Redis进行配置的这一段代码(事实上这也是redisTemplate的默认配置代码):

private void initDomainRedisTemplate(RedisTemplate<String,Object> redisTemplate, RedisConnectionFactory factory) {
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setHashKeySerializer(new StringRedisSerializer());
    redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
    redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
    redisTemplate.setConnectionFactory(factory);
}

在这里,redisTemplate对HashValue和Value的序列化类采用的是JDK默认的序列化策略,而不是String类型的序列化策略,所以我们在redis-cli中看到的value会因为序列化策略的问题,出现乱码

解决办法

将JDK默认的序列化策略更换为String类型的序列化策略

redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());

但是这样做的话,我们在进行存储的时候,也只能存储String类型的数据,所以测试代码要进行如下修改

@Test
public void leftPushTest () {
    List<String> list = new ArrayList<>();
    list.add("hello world2");

    listOperations.leftPush("listKey", list.toString());
}

再一次去redis-cli中取值,得到如下结果:

127.0.0.1:6379> LRANGE listKey 0 10
1) "[hello world2]"
2) "\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x01w\x04\x00\x00\x00\x01t\x00\x0bhello worldx"

可以发现乱码问题已经解决

总结

不建议更换redisTemplate默认的序列化策略,有乱码就让它乱着吧,反正知道正确的解码策略就不会影响程序的正常运行(不过通过php等其他语言去获取redis的值貌似不太好解决)

如果一定要更换策略,那么前往要注意,存储数据的类型要根据所选择的序列化策略去进行切换

项目案例源代码:github/booklet-redis

Spring Boot整合Redis缓存:从零到生产级实战指南 缓存是提升应用性能、降低数据库负载的核心技术之一,其原理是将高频访问的数据存储在更快的介质中,减少对后端资源的直接请求。在Java生态中,Spring Boot通过其强大的自动配置和缓存抽象,极大地简化了Redis等缓存中间件的集成。这种技术组合的价值在于,开发者能以声明式的方式(如使用@Cacheable注解)快速为应用添加缓存层,从而显著提升查询响应速度系统吞吐量。典型的应用场景包括电商商品详情、用户会话管理、热点数据查询等。本文以Spring Boot整合Redis实现缓存为具体案例,深入探讨了从 阅读详情

相关推荐

Spring Boot Redis Cache 原理生产避坑指南

缓存是提升系统性能的关键技术,其本质是在一致性、吞吐量资源成本间动态权衡。Spring Cache 提供统一抽象层,Redis 作为物理存储载体,二者通过 CacheManager、Cache 和 RedisCacheWriter 构成完整链路:从 @Cacheable 声明意图,到 RedisTemplate 执行 SETEX 命令,再到序列化策略影响数据可读性兼容性。理解 TTL 配置、Key/Value 序列化机制、null 值处理及并发控制逻辑,是解决缓存穿透、击穿、雪崩等高频问题的技术基础。本

weixin_30904593的博客 398

SpringbootredisTemplate乱码或json转换问题

问题1 用RedisTemplate存入map值的时候,用rdm可视化打开,看到的是转码之后的数据,如图: 存入的方法为: public boolean hmset(String key, Map<String, Object> map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { log.err

码农记事本 964

[springboot]redisTemplate操作数据乱码问题解决

RedisTemplate 的封装使我们能够更方便的进行redis数据操作,比直接使用Jedis或者Lettuce的java SDK要方便很多。

字母哥博客 2465

springboot整合redis出现乱码解决方法

第一种情况 通过redisTemplate 设置值时乱码 在RedisConfig中加入序列化 // key序列化 redisTemplate.setKeySerializer(STRING_SERIALIZER); // value序列化 redisTemplate.setValueSerializer(JACKSON__SERIALIZER); // Hash key序列化 redisTemp...

鱿鱼的博客 7015

springboot整合redis时redisTemplate踩坑

springboot项目整合redis,用户注册时会将账号和验证码以K-V键值对存入redis,但是验证时根据手机号得到的验证码数据一直为空,并且数据库keys *查到的数据很奇怪,有韩文乱码: 一开始排查方向就是乱码,重新更换redis配置类的KV序列化方式,还是不行,从数据库角度使用 --raw还是不行,甚至想专门使用redisutil来代替opsForValue().set()结果都不行(笑~),但是奇怪的是我直接在项目中直接get对应key的值却能正常得到value,这里我就奇了个怪了.后来往上搜索

weixin_46087854的博客 644

redis做java项目缓存_Java开发在项目中如何引入Redis缓存

在webshop-prodect项目的pom.xml文件中引入相关依赖,如下: org.springframework.boot spring-boot-starter-data-redis io.lettuce lettuce-core redis.clients jedis 修改webshop-prodect项目的application.yml文件,加上redis的相关配置,如...

weixin_39999209的博客 359

redis 值字符串前面部分乱码_Spring-RedisTemplate写入数据乱码问题复现解决

org.springframework.data.redis是Spring框架对Redis的默认集成,我们在实际项目中,也经常使用它的RedisTemplate去操作Redis,一般来说没什么问题,但是细心一点的同学会发现,经过这种方法写入redis的数据会出现乱码问题问题复现项目依赖org.springframework.bootspring-boot-starter-weborg.spring...

weixin_29905347的博客 1134

使用RedisTemplate存储的key-value乱码解决办法

前言 以前用Jedis操作redis,而目前手上的项目是用springboot写的,用的RedisTemplate,我就想学习一下,自己新建了一个项目复现一下,连了本地的redis,但是当我执行了存储后,发现了存进去的key和value都是乱码,而且我的key没有中文,不知道为啥乱码,value中有中文,也是乱码,网上找了一下,最后从这篇博客找到了解决办法,感谢感谢! 引的包: <dependency> <groupId>org.springframewor

高山仰止,景行行止 5203

Spring Boot 3 + Redis序列化终极方案】:彻底解决乱码问题的5种实战策略

掌握Spring Boot 3整合Redis解决序列化乱码的完整方案,提供JSON、自定义序列化器等5种实战策略,适用于缓存存储分布式会话场景,彻底规避中文乱码问题,提升数据一致性系统稳定性,值得收藏。

CompiWander的博客 690

Springboot+Redis序列化问题解决方案

背景: 啊~今天的杭州在经历昨天星期六一整天的雨过后,终于放晴了,所以心情好,撸一段Springboot集成Redis的代码,并且在新电脑上安装Redis玩一玩时发现的一个坑,哈哈~开心,又学习到了东西。 问题: 1、安装完Redis后,在redis客户端,进行了set key value,然后用代码去获取,居然为null。 2、用jedis成功的将key-value插入到redis中,在...

凌晨四点的博客君 5116

Spring Boot集成Redis认证异常排查:从NOAUTH错误到连接池优化

Redis作为高性能键值数据库,其认证机制是保障数据安全的基础。在Redis协议中,客户端通过AUTH命令进行身份验证,服务器验证通过后才允许执行数据操作。这一机制在分布式系统中尤为重要,能有效防止未授权访问。从技术价值看,正确的认证配置不仅关乎安全性,更直接影响应用的稳定性和性能表现,特别是在微服务和云原生场景下。在实际工程实践中,Spring Boot通过Lettuce客户端Redis交互时,常因连接池管理、配置错位或网络策略等问题触发NOAUTH异常。理解连接池的工作原理和认证时机,结合合理的超时

weixin_30487201的博客 411

redis可视化工具读取数据乱码问题

更改序列化方式即可解决问题,具体代码如下 @Configuration public class RedisConfig { @Autowired private RedisTemplate redisTemplate; /** * 修改Redis序列化方式,解决Redis可视化工具乱码问题 * @return */ @Bean public RedisTemplate redisTemplateInit() { //

qq_44331428的博客 848

reids自定义RedisTemplate以及乱码问题解决

reids自定义RedisTemplate以及乱码问题解决

weixin_54097396的博客 1332

Spring Boot 访问Redis的三种方式

Spring Boot 访问Redis的三种方式

IT宅 4277

RedisTemplate存储对象乱码解决

RedisTemplate存储对象乱码解决

fyhju1的博客 1937

使用RedisTemplate存储到redis的值乱码了怎么解决?

(2)为什么会产生乱码RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,直接使用下图的代码就会出现(1)图所示现象。重新启动,若报了如下错误,说是缺少jackson依赖,引入依赖即可。(1)如下图,key和value都乱码了。至此,问题解决,如有疑问可评论区留言!(2)修改RedisTemplate。(1)创建redis配置类。

weixin_43526092的博客 3552

redis的一些自己的理解

首先什么是redis?百度百科 redis( Remote Dictionary Server) 远程字典服务,C语言写的,开源,可基于内存亦可持久化的日志型数据库 key_value数据库 支持多种语言的api. redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及

AChaiYA的博客 420
上一篇: Bind进阶
下一篇: Gitlab-error: RPC failed; result=22, HTTP code = 500解决
liumapp
博客等级 码龄12年 3粉丝 9原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值