Original link: http://blog.csdn.net/yunhaibin/article/details/9001198
Recent research into Redis, and spring data support for Redis, has found a strange phenomenon
First say the phenomenon, through the redistemplate under the Opsforhash method to store the value of the hash type, after the successful operation, to the Redis console to display the keys *, found a strange phenomenon, the inserted hash type of key in front of a bunch of \xac\ XED\X00\X05T\X00\TB This kind of thing, see figure 1
(Fig. 1)
Did you see it? is the second line that a string of things they come out of, analysis Spring-data org.springframework.data.redis.core.RedisTemplate source code later found:
[Java]View PlainCopy
- 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 ();
Found a:
[Java]View PlainCopy
- Private redisserializer<?> Defaultserializer = new Jdkserializationredisserializer ();
Because spring operations Redis is based on the Jedis client, while the Jedis client interacts with Redis, the protocol defines a byte type to interact with, Jedis provides a type of string to byte[]. But see Spring-data-redis in Redistemplate<k, v> in the operation of the time k,v is generic, so redistemplate in the above code, in the absence of a special definition of the case, Spring uses defaultserializer = new Jdkserializationredisserializer () by default, to serialize the Key,value, In a series of operations that have been serialized in the view Jdkserializationredisserializer, the following code is found:
[Java]View PlainCopy
- 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);
- }
- }
Serialization supports object objects, calls the Convert method under the Serializingconverter class, and transforms the object by:
[Java]View PlainCopy
- 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);
- }
- }
The reason is actually here, the solution is to manually define the method of serialization, Spring-data-redis also provides a serialized class specifically for the serialization of string type Org.springframework.data.redis.serializer.StringRedisSerializer, which can be used in XML to refer to the Availability
[HTML]View PlainCopy
- <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>
Where I have specified the Key,value and hash type key,value of the base type in Redis as the Stringredisserializer class for serialization, and then found an error, and found my code:
[Java]View PlainCopy
- Public void Setbank (final 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 is of type integer because the key and value in HashMap are also serialized, and the Serialize method in Stringredisserializer only receives a string of value, as follows:
[Java]View PlainCopy
- Public byte[] Serialize (string string) {
- return (String = = null?) null:string.getBytes (CharSet));
- }
So here's the type conversion error, apart direct Bank.getid (). toString (), execute successfully, and then go to the Redis console open to see that the heap of disgusting \xac\xed\x00\x05t\x00\tb is gone.
(Red part)
In fact, Redis in use, must be considered in advance is the memory of the problem (another article in the blog is very classic, elaborated a foreigner to do the test, the same storage can save dozens of g of memory "Redis memory Optimization" Save memory: Instagram's redis practice), In the design of the use of hash can save a lot of memory, and when stored if each piece of data put a heap of \XAC\XED\X00\X05T\X00\TB this thing, must not look straight
------------------------------------------------------------------------------------------------
When Spring data operates Redis, it finds that the key value appears \XAC\XED\X00\X05T\X00\TB