1、设置源码:
public Long hincrBy(Object key, Object field, long value) { Jedis jedis = getJedis(); try { return jedis.hincrBy(keyToBytes(key), fieldToBytes(field), value); } finally {close(jedis);} }
设置时,field使用的是:fieldToBytes(field);
2、获取源码:
public Long hgetCounter(Object key, Object field) { Jedis jedis = getJedis(); try { String ret = jedis.hget(keyNamingPolicy.getKeyName(key), keyNamingPolicy.getKeyName(field)); return ret != null ? Long.parseLong(ret) : null; } finally {close(jedis);} }
获取时,field使用的是keyNamingPolicy.getKeyName(field);
由于field字段错误,导致拿不到值;
3、问题分析,查看FST源码得知:
fieldToBytes(field)使用了valueToBytes(field);
valueToBytes(field)源码:
public byte[] valueToBytes(Object value) { FSTObjectOutput fstOut = null; try { ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); fstOut = new FSTObjectOutput(bytesOut); fstOut.writeObject(value); fstOut.flush(); return bytesOut.toByteArray(); } catch (Exception e) { throw new RuntimeException(e); } finally { if(fstOut != null) try {fstOut.close();} catch (IOException e) {LogKit.error(e.getMessage(), e);} } }
查看keyNamingPolicy.getKeyName(field):
public String getKeyName(Object key) { return key.toString(); }
查看Jedis.hget()源码:
public String hget(final String key, final String field) { checkIsInMultiOrPipeline(); client.hget(key, field); return client.getBulkReply(); }
查看Client.hget()源码:
public void hget(final String key, final String field) { hget(SafeEncoder.encode(key), SafeEncoder.encode(field)); }
综上,得知field字段由于设置和获取不一致,导致获取不到值
4、总结:
设置field时用的是FstSerializer.valueToBytes(field);
获取field时用的是SafeEncoder.encode(field);
5、临时解决办法(不设置ISerializer和IKeyNamingPolicy的前提下):
private static Long hgetCounter(Object key, Object field) { Jedis jedis = cache.getJedis(); try { byte[] hget = jedis.hget(FstSerializer.me.keyToBytes(key.toString()), FstSerializer.me.fieldToBytes(field.toString())); if (ArrayUtil.isEmpty(hget)) { return null; } String encode = SafeEncoder.encode(hget); return encode != null ? Long.parseLong(encode) : null; } finally { cache.close(jedis); } }
@JFinal 望尽快修复
-----------------------------------------------------2020-07-07.分割线--------------------------------------------------------
现有hgetCounter:
@JFinal 波总可以试试
https://gitee.com/jfinal/jfinal/commit/900b4ac402bcdc1e2fb3c9bec08a9c9e6493689f
用下面的方法用上最新版本:
https://jfinal.com/share/2093
然后尽快给我反馈,这样可以确保线上的版本是没问题的
除了你反馈的 hgetCounter 以外,顺便改进了 getCounter 这个方法,希望你也帮忙试一试