一次线上Redis类转换异常排查引发的思考
之前同事反馈说线上遇到Redis反序列化异常问题,异常如下: XxxClass1 cannot be cast to XxxClass2 已知信息如下:
因为偶尔出现,首先看了报异常那块业务逻辑是不是有问题,看了一遍也发现什么问题。看了下对应日志,发现是在Redis读超时之后才出现的该异常,因此怀疑redis client操作逻辑那块导致的(公司架构组对redis做了一层封装),发现获取/释放redis连接如下代码: 1 try { 2 jedis = jedisPool.getResource(); 3 // jedis业务读写操作 4 } catch (Exception e) { 5 异常处理 6 } finally 7 if (jedis != null) { 8 归还给连接池 9 jedisPool.returnResourceObject(jedis); 10 } 11 } 初步认定原因为:发生了读写超时的连接,直接归还给连接池,下次使用该连接时读取到了上一次Redis返回的数据。因此本地验证下,示例代码如下: @Data 2 @NoArgsConstructor 3 @AllArgsConstructor 4 static class Person implements Serializable { private String name; 6 private int age; 7 } 8 11 class Dog 12 13 14 15 public void main(String[] args) throws Exception { 16 JedisPoolConfig config = new JedisPoolConfig(); 17 config.setMaxTotal(1); 18 JedisPool jedisPool = new JedisPool(config,"192.168.193.133",6379,2000,"123456"19 20 Jedis jedis =21 jedis.set("key1".getBytes(),serialize(new Person("luoxn28",26))); 22 jedis.set("key2".getBytes(),1)">new Dog("tom"23 jedisPool.returnResourceObject(jedis); 24 25 26 jedis =27 Person person = deserialize(jedis.get("key1".getBytes()),Person.class28 System.out.println(person); 29 } 30 发生了异常之后,未对该连接做任何处理 31 System.out.println(e.getMessage()); 32 } 33 34 jedisPool.returnResourceObject(jedis); 35 } 36 37 38 39 jedis =40 Dog dog = deserialize(jedis.get("key2".getBytes()),Dog.41 System.out.println(dog); 42 } 43 44 } 45 46 47 48 49 } 连接超时时间设置2000ms,为了方便测试,可以在redis服务器上使用gdb命令断住redis进程(如果redis部署在Linux系统上的话,还可以使用iptable命令在防火墙禁止某个回包),比如在执行? Person cannot be cast to Dog 既然已经知道了该问题原因并且本地复现了该问题,对应解决方案是,在发生异常时归还给连接池时关闭该连接即可(jedis.close内部已经做了判断),代码如下: jedis.close(); 11 } 至此,该问题解决。注意,因为使用了hessian序列化(其包含了类型信息,类似的有Java本身序列化机制),所有会报类转换异常;如果使用了json序列化(其只包含对象属性信息),反序列化时不会报异常,只不过因为不同类的属性不同,会导致反序列化后的对象属性为空或者属性值混乱,使用时会导致问题,并且这种问题因为没有报异常所以更不容易发现。 ? 既然说到了Redis的连接,要知道的是,Redis基于 MULTI ECHO "唯一序列号" GET key1 EXEC 然后客户端收到的结果是一个? 为什么Redis通信方式并没有采用类似于dubbo这种通信方式呢,个人认为有以下几点:
? 推荐阅读:
?欢迎小伙伴扫描以下二维码阅读更多精彩好文。 (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |