您的位置:首页 > 产品设计 > UI/UE

ERR hash value is not an integer

2017-12-06 12:07 1391 查看

HINCRBY

浏览数业务

使用了redis

spring中的RedisTemplate

增加浏览数量

//简单的获取浏览数量,然后加一
Long previewNumber = getPreviewNumber(sourceId, previewType);
String key = getKey(previewType, sourceId);
previewNumber = previewNumber < 0 ? 0L : previewNumber + 1;
redisTemplate.opsForHash().put(PRIVIEW_KEY, key, previewNumber);


获取浏览数

//获取缓存数量,不存在,设置为-1
private Long getCacheNumber( Map<String, Long> map, PreviewType previewType,Object sourceId) {
String key = getKey(previewType, sourceId.toString());
Long number = map.get(key);
return null == number ? -1 :number;
}
//获取如果cacheNumber小于0
Long cacheNumber = getCacheNumber(map,previewType, sourceId);
if (cacheNumber < 0) {
cacheNumber = 0L;
Preview preview = previewDao.getPreview(previewType.getCode(), sourceId);
if (null != preview) {
number = preview.getNumber();
//缓存不存在,数据库存在, 添加缓存
hashOperations.put(PRIVIEW_KEY, getKey(previewType, sourceId), number);
} else {
//没有浏览记录,增加缓存为 0的记录
hashOperations.put(PRIVIEW_KEY, getKey(previewType, sourceId), number);

}
}
return cacheNumber;


这什么烂代码!是的,改下,起码用redis 的 increment 来做增加数量

开始给自己挖坑

做了简单的修改

Long number =  redisTemplate.opsForHash().increment(THUMB_UP_KEY, getKey(previewType, sourceId), 1);


error

Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR hash value is not an integer


调用个简单的方法也报错?

debug



jedis直接调用了redis的hincrby命令,没什么可说的。



然后直接调用getIntegerReply获取redis服务器返回的信息



直接是minus_byte类型



抛出了异常,发生了什么?

找到了如下资料

https://jira.spring.io/browse/DATAREDIS-103

应该是和序列化有关系的。

使用redis 会配置对应的key和value序列化方式。

例如:

RedisTemplate<String, String> temp = new RedisTemplate<String, String>();
temp.setKeySerializer(new StringRedisSerializer());
temp.setValueSerializer(new StringRedisSerializer());


但是不应该啊,存储到redis使用什么序列化方式,获取时肯定是用对应方式反序列化嘛,

问题应该不是出在这里。

代码注意到这里



spring直接调用了connection,并没有对delta进行序列化操作,接着点进去看到,



jedis提供的connection直接转换成String,然后使用String的getBytes();方法



然后看了下对应key再redis的数据



搞了个新key



原因很明显了

increment 会直接对值进行做增加操作,不会使用对应的redistemplate中设置的序列化方式

原来redis中的旧数据是通过redisTemplate.opsForHash().put进去的,会先通过设置的序列化方式进行序列化,

后面对key进行increment redis没办法对应value转成long进行操作,所以返回了ERR hash value is not an integer异常信息。

删除旧数据就可以了吧。

清空redis数据后

//这里出现了异常
hashOperations.entries(PRIVIEW_KEY)


org.springframework.data.redis.serializer.SerializationException: fst-deserialization-error; nested exception is java.io.IOException: java.lang.NullPointerException


原因和上面大同小异,这里获取的时候依然会进行序列化操作,而且increment设置的值是没有进行对应序列化的。这里是FST 进行反序列化时异常。

总结

increment使用要避免和其他需要经过序列化的操作混用。

对用到的东西要有全面的了解,才能避免各种坑。

为什么会这么累,就是喜欢给自己挖坑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐