当前位置: 首页 > news >正文

jedis+redis pipeline诡异的链接损坏、数据读取异常问题解决

文章目录

    • 问题现象
      • 栈溢出(不断的重连)
      • 读取超时
      • 未知响应
      • 尝试读取损坏的链接
      • 读取到的数据和自己要读的无关,导致空指针、类型转换错误,数据读取错乱
    • 问题写法
    • 问题分析
    • 修复
    • 注意点

问题现象

栈溢出(不断的重连)

		at redis.clients.jedis.Connection.sendCommand(Connection.java:163)at redis.clients.jedis.Connection.sendCommand(Connection.java:154)at redis.clients.jedis.BinaryClient.auth(BinaryClient.java:815)at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:145)at redis.clients.jedis.Connection.sendCommand(Connection.java:163)at redis.clients.jedis.Connection.sendCommand(Connection.java:154)at redis.clients.jedis.BinaryClient.auth(BinaryClient.java:815)at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:145)

在这里插入图片描述

读取超时

在这里插入图片描述

未知响应

在这里插入图片描述

尝试读取损坏的链接

在这里插入图片描述

读取到的数据和自己要读的无关,导致空指针、类型转换错误,数据读取错乱

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

问题写法

对Redis操作封装了一个Redis类
在这里插入图片描述
同事对pipeline加了这个方法
在这里插入图片描述
使用的时候

   public Map<String, AnswerModel> batchGetAnswersPipeline(List<String> answerIdList) {Map<String, AnswerModel> resultMap = new HashMap<>();try (Pipeline pipelined = redis.pipelined()) {List<Response<Map<String, String>>> responses = new ArrayList<>();for (String answerId : answerIdList) {String key = String.format(MOMENT_ANSWER_INFO, answerId);responses.add(pipelined.hgetAll(key));}pipelined.sync();for (Response<Map<String, String>> response : responses) {Map<String, String> map = response.get();AnswerModel answers = BeanUtil.mapToBean(map, AnswerModel.class);if (answers != null){resultMap.put(answers.getAnswerId(), answers);}}} catch (Exception e) {log.error("执行batchGetAnswersPipeline发生异常, redis pipeline error", e);throw new CatVillageException();}return resultMap;}

问题分析

在redis这个工具类中调pipelined时获取一个Pinelined对象,而获取这个方法里用了try with ,with了一个jedis链接,当try结束时链接会被归还jedispool连接池。而返回的这个pipeline仍然在用这个链接,当其他线程去拿链接的时候可能拿到的正好是这个链接,导致多个线程共用一个链接,一个线程在执行pipeline多条命令,另一个线程也在用这个链接。而jedis底层执行命令的时候是使用的OutputStream流式去执行命令,使用二进制流读取结果。当出现这种线程不安全问题的时候,读取写入就会有问题。

修复

删除Redis工具类中的pipelined方法,使用getJedis方法获取链接对象,再获取管道Pineline对象,自行close管道,最后执行完释放管道,链接。

public Map<String, QuestionModel> batchGetQuestionPipeline(List<String> questionIdList) {if (CollectionUtils.isEmpty(questionIdList)){return new HashMap<>();}Map<String, QuestionModel> resultMap = new HashMap<>();try (Jedis jedis = redis.getJedis()) {Pipeline pipelined = jedis.pipelined();List<Response<Map<String, String>>> responses = new ArrayList<>();for (String questionId : questionIdList) {String key = String.format(MOMENT_QUESTION_INFO, questionId);responses.add(pipelined.hgetAll(key));}pipelined.sync();for (Response<Map<String, String>> response : responses) {Map<String, String> map = response.get();QuestionModel question = convertFromMap(map);if (question != null) {resultMap.put(question.getPostId(), question);}}pipelined.close();} catch (Exception e) {log.error("执行batchGetQuestionPipeline发生异常, redis pipeline error", e);throw new CatVillageException();}return resultMap;}

注意点

若jedis在3.7版本以下的版本也会有管道二进制读取异常问题,请升级到3.7.0+版本

http://www.dtcms.com/a/192368.html

相关文章:

  • vue使用vite, 渲染glb模型时报错
  • Nginx与Tomcat负载均衡集群配置指南
  • 牛客网NC21994:分钟计算
  • 计量经济学——预测与chow检验
  • [6-8] 编码器接口测速 江协科技学习笔记(7个知识点)
  • 虚拟网络编辑器
  • 【数据结构入门训练DAY-35】棋盘问题
  • Python-Django系列—日志
  • 张 提示词优化(相似计算模式)深度学习中的损失函数优化技巧
  • ES常识9:如何实现同义词映射(搜索)
  • 平滑过滤值策略
  • 时序数据库IoTDB分布式架构解析与运维指南
  • DeepSeek 赋能物联网:从连接到智能的跨越之路
  • 【Pandas】pandas DataFrame diff
  • 语音识别——通过PyAudio录入音频
  • Linux线程控制
  • 【Pandas】pandas DataFrame eval
  • CertiK助力以太坊扩展战略,解析Pectra升级的变革与挑战
  • 5G + 区块链:技术巨浪下的新型数字生态!
  • 数字孪生工厂实战指南:基于Unreal Engine/Omniverse的虚实同步系统开发
  • 如何使用WordPress SEO检查器进行实时内容分析
  • 【OpenGL学习】(一)创建窗口
  • 边缘计算平台
  • Unity光照笔记
  • 如何使用 Google Gemini API 和 Python 从航行情报通告 (NOTAM) 中提取结构化空域信息
  • RiDoc:高效文档扫描与图像处理工具,助力高效办公
  • mavgenerate 在 win11 下环境搭建注意问题
  • Top-p采样:解锁语言模型的创意之门
  • Redis--基础知识点--27--redis缓存分类树
  • 【AI论文】用于评估和改进大型语言模型中指令跟踪的多维约束框架