alibaba / jetcache

JetCache is a Java cache framework.
Apache License 2.0
5.14k stars 1.06k forks source link

可有redis不可用时的异常扩展 #174

Closed icemoff closed 6 years ago

icemoff commented 6 years ago

redis不可用的情况下,应该让业务继续可用,可以在此扩展下做邮件预警和其它处理

areyouok commented 6 years ago

Cache上可以添加monitor,如果针对单个Cache实例添加,直接cache.config().getMonitors().add(myMonitor)就可以,如果希望所有注解创建出来的实例都有一个全局的monitor,可以在spring中声明一个SpringConfigProvider实例,它会自动注入到GlobalCacheConfig中,你覆盖这个SpringConfigProvider的buildRemote方法,对每个返回的Cache实例添加你的monitor就可以。

icemoff commented 6 years ago

没看到这个方法啊

icemoff commented 6 years ago

考察这个框架一天了,现在就想找到redis不可用时的自定义处理,还有value序列化的扩展

areyouok commented 6 years ago

没看到这个方法啊

我说错了,是SpringConfigProvider的newContext方法,需要返回一个覆盖了buildRemote方法的SpringCacheContext。

序列化可以自己定制的,参考SpringConfigProvider的parseValueEncoder和parseValueDecoder方法。

icemoff commented 6 years ago
  1. 第一个问题可能我描述得不是很清楚,重新描述一下: 当程序运行的时候,redis故障不可用,此时需要走db继续业务。目前实测情况是一直尝试重连,接口请求挂起

  2. 第二个value Json序列化问题: 自定义了valueEncoder 和 valueDecoder代码如下:

`public class JsonEncoder extends AbstractValueEncoder {

public JsonEncoder(boolean useIdentityNumber) { super(useIdentityNumber); } @Override public byte[] apply(Object value) { String json = JSON.toJSONString(value); return json.getBytes(); } }`

`public class JsonDecoder extends AbstractValueDecoder { public JsonDecoder(boolean useIdentityNumber) { super(useIdentityNumber); } @Override protected Object doApply(byte[] buffer) throws Exception {

String json = new String(buffer);
return JSON.parseObject(json);

} }`

再定义自己的SpringConfigProvider,代码如下:

`public class CacheConfigProvider extends SpringConfigProvider {

@Override public Function<Object, byte[]> parseValueEncoder(String valueEncoder) { return new JsonEncoder(false); }

@Override public Function<byte[], Object> parseValueDecoder(String valueDecoder) { return new JsonDecoder(false); } }`

springboot中声明此provider

@Bean public SpringConfigProvider springConfigProvider() { return new CacheConfigProvider(); }

查看redis 中是已经是json序列化成功了,但取不到值,依然走了业务方法,应该是valueDecoder写得有问题,求指点

---- and 有更好的交流方式吗,比如qq群,想把jetCache在项目中用起来

areyouok commented 6 years ago

首先你的第一个问题应该是不存在的,cache查不到去数据库这就是正常的逻辑,jetcache决不会因为cache操作失败而让cached注解标记的方法跑出异常。

第二个问题,你可能没有处理好IdentityNumber,它是用来做兼容的,比如你修改了序列化的方式后,另一个decoder仍然可以把原来的encoder放进去的值解出来。如果你想简单点就不需要继承AbstractValueDecoder,你再看看相关代码,这块很简单。还有就是jetcache本来有fastjson encoder/decoder的,后来由于兼容性原因,删掉了,现在代码在这里: https://github.com/alibaba/jetcache/blob/master/jetcache-test/src/main/java/com/alicp/jetcache/examples/FastjsonValueDecoder.java 但是也要在DecoderMap中注册过才能用。

icemoff commented 6 years ago

首先你的第一个问题应该是不存在的,cache查不到去数据库这就是正常的逻辑,jetcache决不会因为cache操作失败而让cached注解标记的方法跑出异常。

问题一重现步骤(jetcache-starter-redis-lettuce):

  1. 启动redis服务,启动业务系统,访问请求正常 2.停止redis服务(模拟生产redis会挂掉),访问请求挂起,无法请求到数据库,看业务系统日志,一直在打reconnect日志,无法住下走到数据库。

问题二已解决,THX

areyouok commented 6 years ago

lettuce在异步情况下没有超时,这个我看一下,你可以先用jedis。

icemoff commented 6 years ago

lettuce在异步情况下没有超时,这个我看一下,你可以先用jedis。

lettuce 的valueDecoder也不起效。

areyouok commented 6 years ago

lettuce的RedisCodec是在连接的时候统一设置的,现在用的是JetCache自己的JetCacheCodec

areyouok commented 6 years ago

针对lettuce在redis重连时堵塞的问题,如果你的RedisClient是自己创建的(即没有使用spring boot的配置方式),可以用下面的代码让它快速失败:

        client.setOptions(ClientOptions.builder().
               disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
               .build());

否则默认情况下它会一直尝试重连。

jetcache下个版本2.5.9会对异步Future的get加上超时设置,同时基于spring boot的自动配置中会设置好以上快速失败的逻辑。