Spring Data操作Redis时,发现key值出现 \xac\xed\x00\x05t\x00\tb
原文链接:http://blog.csdn.net/yunhaibin/article/details/9001198
最近在研究redis,以及spring data对redis的支持发现了一个奇怪的现象
先说现象吧,通过redisTemplate下的opsForHash方法存储hash类型的值,操作成功以后,去redis控制台显示keys * 的时候,发现一个奇怪的现象,插入的hash类型的key前面会有一堆的\xac\xed\x00\x05t\x00\tb 这种东西,见图1
(图1)
看见了吗?就是第二行那一串自己冒出来的东西,分析spring-data的org.springframework.data.redis.core.RedisTemplate源代码以后发现:
- private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
- private RedisSerializer keySerializer = null;
- private RedisSerializer valueSerializer = null;
- private RedisSerializer hashKeySerializer = null;
- private RedisSerializer hashValueSerializer = null;
- private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
发现了一个:
- private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
因为spring操作redis是在jedis客户端基础上进行的,而jedis客户端与redis交互的时候协议中定义是用byte类型交互,jedis中提供了string类型转为byte[]类型,但是看到spring-data-redis中RedisTemplate<K, V>在操作的时候k,v是泛型的,所以RedisTemplate中有了上面那段代码,在没有特殊定义的情况下,spring默认采用defaultSerializer = new JdkSerializationRedisSerializer();来对key,value进行序列化操作,在经过查看JdkSerializationRedisSerializer中对序列化的一系列操作,发现如下代码:
- private Converter<Object, byte[]> serializer = new SerializingConverter();
- public byte[] serialize(Object object) {
- if (object == null) {
- return SerializationUtils.EMPTY_ARRAY;
- }
- try {
- return serializer.convert(object);
- } catch (Exception ex) {
- throw new SerializationException("Cannot serialize", ex);
- }
- }
序列化支持的是Object对象,调用了SerializingConverter类下的convert方法转换对象,转换对象的方法是:
- private final Serializer<Object> serializer;
- /**
- * Serializes the source object and returns the byte array result.
- */
- public byte[] convert(Object source) {
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
- try {
- this.serializer.serialize(source, byteStream);
- return byteStream.toByteArray();
- }
- catch (Throwable ex) {
- throw new SerializationFailedException("Failed to serialize object using " +
- this.serializer.getClass().getSimpleName(), ex);
- }
- }
原因其实就出现在这里,解决的办法就是手动定义序列化的方法,spring-data-redis中还提供了一个序列化的类专门针对string类型的序列化org.springframework.data.redis.serializer.StringRedisSerializer这个类,可以在xml里面指定:
- <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
- p:connection-factory-ref="jedisConnectionFactory">
- <property name="keySerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- </property>
- <property name="valueSerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- </property>
- <property name="hashKeySerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- </property>
- <property name="hashValueSerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- </property>
- </bean>
其中我将redis中基础类型的key,value和hash类型的key,value都指定为StringRedisSerializer类来进行序列化,然后发现又报错了,找了一会发现我的代码中:
- public void setBank(final Bank bank) {
- // TODO setBank
- final String key = String.format("bank:%s", bank.getId());
- final Map<String, Object> properties = new HashMap<String, Object>();
- properties.put("id", bank.getId());
- properties.put("name", bank.getBank_name());
- redisTemplate.opsForHash().putAll(key, properties);
- }
bank.getId是Integer类型的,因为Hashmap中的key和value也会进行序列化操作,而StringRedisSerializer中的serialize方法只接收String类型的值,如下:
- public byte[] serialize(String string) {
- return (string == null ? null : string.getBytes(charset));
- }
所以这里的类型转换报错了,二话不说直接bank.getId().toString(),执行成功,然后进入redis控制台打开查看发现那堆恶心巴拉的\xac\xed\x00\x05t\x00\tb没有了,大功告成了
(红色部分)
其实redis在使用中,必须要提前考虑的就是内存的占用问题(博客中另外一篇文章很经典,阐述了一个外国人做的测试,同样的存储可以节约几十G的内存【Redis 内存优化】节约内存:Instagram的Redis实践),在设计的时候使用hash可以节约很多的内存,而存储的时候如果每条数据就放一堆\xac\xed\x00\x05t\x00\tb这个东西,肯定是无法直视的
------------------------------------------------------------------------------------------------
Spring Data操作Redis时,发现key值出现 \xac\xed\x00\x05t\x00\tb的更多相关文章
- SpringBoot使用RedisTemplate操作Redis时,key值出现 \xac\xed\x00\x05t\x00\tb
原因分析 原因与RedisTemplate源码中的默认序列化方式有关 defaultSerializer = new JdkSerializationRedisSerializer( classLoa ...
- Spring Data操作Redis详解
Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...
- redis key/value 出现\xAC\xED\x00\x05t\x00\x05
1.问题现象: 最近使用spring-data-redis 和jedis 操作redis时发现存储在redis中的key不是程序中设置的string值,前面还多出了许多类似\xac\xed\x00\x ...
- Java Spring mvc 操作 Redis 及 Redis 集群
本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html 关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用 R ...
- 160309、Spring AOP操作action时无法注入,报空指针错误
今天帮同事看个问题,action注入失败,代码没问题,主要是stuts2权限移交的问题,特此记录一下 Spring AOP操作action时无法注入,报NullPointer异常 当使用Spring ...
- Spring AOP操作action时无法注入,报NullPointer异常
Spring AOP操作action时无法注入,报NullPointer异常当使用Spring AOP对action层进行操作时,会出现注入失败的问题,出现空指针异常.原因是一般struts2+spr ...
- 【redis】java操作redis时,StringRedisTemplate的expire()方法的作用,什么时候使用
java操作redis时,StringRedisTemplate的expire()方法的作用,什么时候使用 //重新设置过期时间为30分钟,刷新时间 redisTemplate.expire(MsOp ...
- 解决Spring Boot 使用RedisTemplate 存储键值出现乱码 \xac\xed\x00\x05t\x00
spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化解决方法 ...
- Spring Data 教程 - Redis
1. Redis简介 Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value ...
随机推荐
- FieldOffset
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.G ...
- hdu 3415 Max Sum of Max-K-sub-sequence 单调队列优化DP
题目链接: https://www.cnblogs.com/Draymonder/p/9536681.html 同上一篇文章,只是 需要记录最大值的开始和结束的位置 #include <iost ...
- AtCoder 杂题训练
前言: 因为要普及了,今年没一等就可以退役去学文化课了,所以暑假把历年noip普及组都刷了一遍,离noip还有50+天,想弄点强化训练什么的. 想了想,就这些天学文化课之余有空就把AtCoder之前那 ...
- axis2框架用wsdl文件生成的服务端MessageReceiveInOut文件注意事项
在用axis2生成服务端文件和客户端文件,当客户端文件调用服务端文件时,都是通过wsdl文件生成的 配置文件进行相互的调用. 在一开始做开发测试的时候,通过soapUI进行调用接口的时候,可以调用成功 ...
- UVa 1620 懒惰的苏珊(逆序数)
https://vjudge.net/problem/UVA-1620 题意:给出一个序列,每次可以翻转4个连续的数,判断是否可以变成1,2,3...n. 思路:考虑逆序数,通过计算可以得出每次翻转4 ...
- UI 自动化测试 Macaca测试框架 安装时遇到的log
https://macacajs.github.io/zh/environment-setup macaca run -d ./macaca-test/desktop-browser-sample.t ...
- RabbitMQ入门_08_所谓的点对点与发布订阅模型
A. JMS 模型 JMS 中定义了点对点和发布订阅两种消息模型,原来以为 AMQP 协议中 direct Exchange 对应点对点模型,topic Exchange 对应发布订阅模型,fanou ...
- RabbitMQ入门_05_多线程消费同一队列
A. 多线程消费同一队列 参考资料:https://www.rabbitmq.com/tutorials/tutorial-two-java.html 消费一条消息往往比产生一条消息慢很多,为了防止消 ...
- 查询ORACLE存储关联表
SELECT DISTINCT * FROM user_sourceWHERE TYPE = 'PROCEDURE'AND upper(text) LIKE '%PS_KL_ABS_002_DATA% ...
- 雷林鹏分享:Ruby 模块(Module)
Ruby 模块(Module) 模块(Module)是一种把方法.类和常量组合在一起的方式.模块(Module)为您提供了两大好处. 模块提供了一个命名空间和避免名字冲突. 模块实现了 mixin 装 ...