详解Redis中数值乱码的根本原因以及解决方式
目录
- 1. 问题所示
- 2. 原理分析
- 3. 拓展
1. 问题所示
某些信息存储在缓存中,对此修改缓存,想通过可视化的Redis Desktop来操作,但是发现都是二进制的数据,不好操作:
于是想着以命令行的方式修改,但又怕改错,毕竟都是难以读懂的二进制数据,如图所示:(由于信息比较隐私,此处打码了)
2. 原理分析
RedisTemplate
存储的数据通常是二进制的。Redis 是一个键值存储系统,它存储的值可以是字符串、二进制数据、甚至是序列化的对象。RedisTemplate
是 Spring Data Redis 提供的一个类,用于在 Spring 应用中与 Redis 进行交互。它提供了一种在 Java 对象和 Redis 数据之间进行序列化和反序列化的机制。
默认情况下,
RedisTemplate
使用 JDK 的序列化机制将 Java 对象转换为二进制数据,并存储在 Redis 中。3. 拓展
在使用Redis作为数据存储时,合理的键值序列化配置和
RedisTemplate
的使用方式对于应用性能和数据可维护性至关重要。默认情况下,Spring Data Redis使用
JdkSerializationRedisSerializer
作为RedisTemplate
的默认序列化器这意味着键和值都将以Java对象的二进制形式进行序列化,并以字节流的方式存储在Redis中。
不对值进行额外序列化的理由
:虽然值以二进制形式存储,但在Java代码中获取值时会进行反序列化,因此这不会影响业务逻辑和数据的正确性。
同时,对值进行额外的序列化可能会限制存储的数据类型,例如将值序列化为字符串将仅能存储字符串类型的值。额外序列化的场景
如果需要存储复杂的数据结构或非字符串类型的值,可以选择配置RedisTemplate
使用其他序列化器,例如JSON序列化器或自定义序列化器。- 这样可以更灵活地存储各种类型的数据,但需要注意在读取时正确地反序列化。
特殊值的处理
对于包含特殊类型(如LocalDateTime、LocalDate、LocalTime等)的值,可能需要注意转换为字符串或选择合适的序列化方式。
通过理解Redis默认行为和灵活运用
RedisTemplate
,可以更好地应对不同类型数据的存储需求,从而优化系统性能并提升开发效率给出一个Demo代码更加容易懂:
先引入这两个依赖包:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.6.5.RELEASE</version> <!-- 使用你项目中的实际版本 --> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> <!-- 使用你项目中的实际版本 --> </dependency>
对key进行可视化:
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; public class Demo { public static void main(String[] args) { // 创建 Redis 连接配置 JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName("localhost"); jedisConnectionFactory.setPort(6379); // jedisConnectionFactory.setPassword(RedisPassword.of("your-redis-password")); // 手动调用 afterPropertiesSet() jedisConnectionFactory.afterPropertiesSet(); // 创建 RedisTemplate 实例 RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); //设置String类型的key设置序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置Hash类型的key设置序列化器 redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(jedisConnectionFactory); redisTemplate.afterPropertiesSet(); // 存储字符串 redisTemplate.opsForValue().set("message", "Hello, Redis!"); // 获取字符串 String message = (String) redisTemplate.opsForValue().get("message"); System.out.println("Message: " + message); // 存储哈希 HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash(); hashOperations.put("user", "id", "1"); hashOperations.put("user", "name", "码农研究僧"); // 获取哈希 String userId = hashOperations.get("user", "id"); String userName = hashOperations.get("user", "name"); System.out.println("User ID: " + userId); System.out.println("User Name: " + userName); } }
如果不对key可视化,只需要删除这两行代码即可:
//设置String类型的key设置序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置Hash类型的key设置序列化器 redisTemplate.setHashKeySerializer(new StringRedisSerializer());
截图如下: