消息队列导致数据库数据读取不一致解决方案

embedded/2025/3/18 8:41:34/

我使用的是在数据库添加一个版本字段,记录版本,保证版本一致性,就能保证每次读取的是需要的内容。

具体问题:使用消息队列时,发送方给接收方发送消息,接收方修改了数据库的同时发送方查询数据库,由于是异步操作,会导致发送方读取的数据是修改前的数据,导致数据不一致的问题。

代码:

发送方

// 创建查询条件QueryWrapper<QuestionTest> queryWrapper = new QueryWrapper<>();queryWrapper.eq("userId", loginUser.getId()).eq("questionId", questionId);
// 查询是否存在记录QuestionTest existingRecord = questionTestMapper.selectOne(queryWrapper);插入一条新记录existingRecord.setQuestionId(questionId);existingRecord.setUserId(loginUser.getId());if (existingRecord.getId() == null) {existingRecord.setVersion(Long.valueOf(0));questionTestMapper.insert(existingRecord);}Long id = existingRecord.getId(); // 获取新插入记录的idLong version = existingRecord.getVersion();existingRecord.setVersion(version);Map<String, Object> taskMessage = new HashMap<>();taskMessage.put("id", id);taskMessage.put("questionId", questionId);taskMessage.put("userId", loginUser.getId());taskMessage.put("codeLanguage", questionSubmitAddRequest.getCodeLanguage());taskMessage.put("userCode", questionSubmitAddRequest.getUserCode());taskMessage.put("input", questionSubmitAddRequest.getUserJudgeCase().getInput());taskMessage.put("answer", question.getAnswer());taskMessage.put("version", version);
//        System.out.println(taskMessage);String message = JSONUtil.toJsonStr(taskMessage);
//        System.out.println(message);myMessageProducer.sendMessage("code_exchange", "my_routingKey_test", message);// 等待接收方处理完毕
//        Long newVersion = null;while (!existingRecord.getVersion().equals(version + 1)) {existingRecord = questionTestMapper.selectById(id);}return existingRecord;

 接收方:

Map<String, Object> taskMessage = JSONUtil.toBean(message, Map.class);Long questionId = Long.valueOf(taskMessage.get("questionId") != null ? String.valueOf(taskMessage.get("questionId")) : "0");Long id = Long.valueOf(taskMessage.get("id") != null ? String.valueOf(taskMessage.get("id")) : "0");Long userId = Long.valueOf(taskMessage.get("userId") != null ? String.valueOf(taskMessage.get("userId")) : "0");String codeLanguage = String.valueOf(taskMessage.get("codeLanguage"));String userCode = String.valueOf(taskMessage.get("userCode"));String input = String.valueOf(taskMessage.get("input"));String answer = String.valueOf(taskMessage.get("answer"));Long version = Long.valueOf(taskMessage.get("version") != null ? String.valueOf(taskMessage.get("version")) : "0");
//            System.out.println(answer);// 使用正确代码生成预期结果String output = judgeService.dojudgeTestCode(answer, input, codeLanguage);// 使用用户代码生成实际结果String predicted = judgeService.dojudgeTestCode(userCode, input, codeLanguage);JudgeCase currentJudgeCase = new JudgeCase();currentJudgeCase.setInput(input);currentJudgeCase.setOutput(output);JudgeCase userJudgeCase = new JudgeCase();userJudgeCase.setInput(input);userJudgeCase.setOutput(predicted);log.info("测试任务处理成功,Id = {}", id);// 5. 将结果存储到数据库或缓存中// 修保存到数据库中的测试结果version = version + 1;QuestionTest questionTest = new QuestionTest();questionTest.setVersion(version);questionTest.setId(id);questionTest.setQuestionId(questionId);questionTest.setUserId(userId);questionTest.setUserCode(userCode);questionTest.setCodeLanguage(codeLanguage);questionTest.setCurrentJudgeCase(JSONUtil.toJsonStr(currentJudgeCase));questionTest.setUserJudgeCase(JSONUtil.toJsonStr(userJudgeCase));
//            System.out.println("QuestionTest:"+questionTest);questionFeignClient.updateQuestionTestById(questionTest);// 6. 手动确认消息channel.basicAck(deliveryTag, false);


http://www.ppmy.cn/embedded/173538.html

相关文章

MongoDB 和 Elasticsearch的区别、优缺点对比,以及选型建议

MongoDB 和 Elasticsearch 在存储和搜索方面各有特点&#xff0c;适用于不同的场景。以下是它们的区别、优缺点对比&#xff0c;以及选型建议。 1. 概述 MongoDB&#xff1a;分布式 NoSQL 文档数据库&#xff0c;基于 BSON&#xff08;类似 JSON&#xff09;的文档存储&#x…

app.config.globalProperties

目录 一:基础使用 1、简介 2、使用 3、打印结果: 二:封装 1、创建一个.ts文件(utils/msg.ts) 2、在main.ts中全局注册 3、在页面中使用 4、打印结果 一:基础使用 1、简介 app.config.globalProperties 是 Vue 3 应用实例&#xff08;app&#xff09;的一个配置属性&…

海绵音乐 3.4.0 | 免费AI音乐创作软件,支持多种风格智能生成

海绵音乐是一款专为Android用户设计的免费AI音乐创作软件&#xff0c;搭载深度神经网络作曲引擎&#xff0c;支持流行、电子、古风等12种音乐风格智能生成。提供多轨道编辑界面&#xff08;8轨同步混音&#xff09;&#xff0c;可自定义鼓点、旋律和和弦进行实时混音&#xff0…

用Deepseek写一个 HTML 和 JavaScript 实现一个简单的飞机游戏

大家好&#xff01;今天我将分享如何使用 HTML 和 JavaScript 编写一个简单的飞机游戏。这个游戏的核心功能包括&#xff1a;控制飞机移动、发射子弹、敌机生成、碰撞检测和得分统计。代码简洁易懂&#xff0c;适合初学者学习和实践。 游戏功能概述 玩家控制&#xff1a;使用键…

基于javaweb的SpringBoot校园运动会管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…

网络华为HCIA+HCIP数据链路层协议-以太网协议

以太网协议 以太网是当今现有局域网(Local Area Network,LAN)采用的最通用的通信协议标准&#xff0c;该标准定义了在局域网中采用的电缆类型和信号处理方法。以太网是建立在CSMA/CD(Carrier Sense Multiple Access/Collision Detection,载波监听多路访问/冲突检测)机制上的广…

Bash中小数的大小比较以及if条件中小数的大小判断

1、在Bash中对小数进行大小判断时&#xff0c;需要使用bc命令进行判断&#xff0c;用-gt、-lt、-eq等或使用>、<、运算符比较。 注意&#xff1a;用bc命令比较时&#xff0c;真返回1&#xff0c;假返回0。 [rootCentos7-4 ~]# [ echo "120.5 > 88.8" | bc…

新能源汽车IGBT电压平台与SiC器件应用

一、引言 随着全球环保意识的增强和能源危机的加剧&#xff0c;新能源汽车&#xff08;包括纯电动汽车和插电式混合动力汽车&#xff09;市场迅速崛起。作为新能源汽车的核心动力系统&#xff0c;电机控制器在提升车辆性能、降低能耗方面发挥着至关重要的作用。目前&#xff0…