JFinal Redis plugin 有关数值类型incr操作的bug

先上测试代码:

public class TestCache {
    private static final Cache testCache = Redis.use(CacheCons.TEST) ;
    public static void incrThenGet() {
        testCache.incr("ikey") ;
        testCache.get("ikey") ;
    }
    public static void setThenIncr() {
        testCache.set("ikey", 0) ;
        testCache.incr("ikey") ;
    }
}


执行incrThenGet(),抛出错误:

java.lang.RuntimeException: java.io.IOException: java.lang.NullPointerException
at com.jfinal.plugin.redis.serializer.FstSerializer.valueFromBytes(FstSerializer.java:84)


执行setThenIncr(),抛出错误:

redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range
at redis.clients.jedis.Protocol.processError(Protocol.java:127)


错误分析

incrThenGet()中,调用redis incr命令,当时ikey并不存在,redis会创建ikey,并将值初始化为0,然后执行incr加1操作,执行后的值为1.

get的时候,redis plugin默认redis中所有值都是java类型序列化之后的值,取到值后,会用FstSerializer这个类去反序列化。但是redis返回的值是字符1的ASCII值49,FstSerializer无法识别类型,因此抛出错误。


同理,在setThenIncr()中,redis plugin将ikey的值设为整型数值0,经过序列化后的二进制值为\xf7\x00,然后incr,redis只能对数值类型的值进行递增,\xf7\x00不认识,所以抛出错误。

redis hash类型的hincr也存在同样的问题。

这个问题如何解决呢?

评论区

JFinal

2017-11-02 21:28

incr(...) 放入的值,需要用 getCounter(key) 去获取,而其它获取方法必然是要做反序列化的,否则无法与其它 set 类型的方法协同工作

Brentwu

2017-11-02 21:35

谢谢。set怎么办呢?还有hash的呢?

JFinal

2017-11-02 22:36

@Brentwu set 的就用 get 取,总之与 incr 相关的才用 getCounter(key) 其它都有相关配套的 get 方法取

Brentwu

2017-11-03 09:01

明白了,JFinal Redis plugin的Cache类大都是调用BinaryJedis,我改Cache类,增加几个调用Jedis字符串参数类的方法就可以了

晨曦君

2018-09-17 19:59

阿里云redis的值是隐藏的,应该怎么获取,使用 getCounter(key) 去获取会报NumberFormatException的异常

热门反馈

扫码入社