使用spring-redis-data 的hIncrBy增加值后,用get报错

使用spring-redis-data 的hIncrBy增加值后,用get报错,错误信息如下:

 org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: 31332E35
 at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:41)
 at org.springframework.data.redis.core.AbstractOperations.deserializeHashValue(AbstractOperations.java:316)
 at org.springframework.data.redis.core.DefaultHashOperations.get(DefaultHashOperations.java:55)
 at com.yss.sofa.whale.cache.codis.client.CodisHashClient.getValue(CodisHashClient.java:103)
 at com.yss.sofa.whale.cache.redis.client.junit.client.CodisHashClientTest.incrbyDouble(CodisHashClientTest.java:80)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
 at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
 at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: 31332E35
 at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:64)
 at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:34)
 at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:39)
 ... 29 more
Caused by: java.io.StreamCorruptedException: invalid stream header: 31332E35
 at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
 at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
 at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:39)
 at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:59)
 ... 31 more

跟代码发现:

JedisConnection里:

public Double hIncrBy(byte[] key, byte[] field, double delta) {
		try {
			if (isPipelined()) {
				pipeline(new JedisResult(pipeline.hincrByFloat(key, field, delta)));
				return null;
			}
			if (isQueueing()) {
				transaction(new JedisResult(transaction.hincrByFloat(key, field, delta)));
				return null;
			}
			return jedis.hincrByFloat(key, field, delta);
		} catch (Exception ex) {
			throw convertJedisAccessException(ex);
		}
	}

BinaryJedis:

 

 public Double hincrByFloat(final byte[] key, final byte[] field, final double value) {
    checkIsInMultiOrPipeline();
    client.hincrByFloat(key, field, value);
    final String dval = client.getBulkReply();
    return (dval != null ? new Double(dval) : null);
  }

BinaryClient:

 public void hincrByFloat(final byte[] key, final byte[] field, double increment) {
    sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment));
  }
...
  public static final byte[] toByteArray(final double value) {

    return SafeEncoder.encode(String.valueOf(value));
  
}

SafeEncoder:

 

 public static byte[] encode(final String str) {
    try {
      if (str == null) {
        throw new JedisDataException("value sent to redis cannot be null");
      }
      return str.getBytes(Protocol.CHARSET);
    } catch (UnsupportedEncodingException e) {
      throw new JedisException(e);
    }
  }

    

 

此处输入的值double 是按string的方式进行序列化的并存入缓存的。

下面再看从缓存中取值的过程 :

 DefaultHashOperations:

public HV get(K key, Object hashKey) {
		final byte[] rawKey = rawKey(key);
		final byte[] rawHashKey = rawHashKey(hashKey);

		byte[] rawHashValue = execute(new RedisCallback<byte[]>() {

			public byte[] doInRedis(RedisConnection connection) {
				return connection.hGet(rawKey, rawHashKey);
			}
		}, true);

		return (HV) deserializeHashValue(rawHashValue);
	}
...
<HV> HV deserializeHashValue(byte[] value) {

  if (hashValueSerializer() == null) {
   
	return (HV) value;
  
	}
  
return (HV) hashValueSerializer().deserialize(value);
 }

 可以看出取值后的反序列化是按照配置文件里配置的hashValueSerializer()序列化方式进行反序列化的,如果hashValueSerializer()配置的是JdkSerializationRedisSerializer,就会报上述的错误。

解决办法:

在取值时把序列化方法设为stringSerializer,取后再恢复。

	public Object getValue(Object key, Object field) {
		RedisSerializer<?> hValueSerializer=	template.getHashValueSerializer();
		template.setHashValueSerializer(stringSerializer);
		 Object  value = operations.get(key, field);
		...
		template.setHashValueSerializer(hValueSerializer);
		return value;
	}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值