springboot mongodb分片集群事务
前置
mongodb分片集群想要使用事务,需要对应分片没有仲裁节点
代码
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>2.1.0.RELEASE</version></dependency>
如果是单个mongos
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
import org.springframework.stereotype.Component;/*** @author kittlen* @date 2024-04-09 17:20* @description*/@Component
public class MongodbConfig {@Beanpublic MongoTransactionManager transactionManager(MongoDbFactory factory) {return new MongoTransactionManager(factory);}
}
使用
@Autowiredprivate MongoTemplate mongoTemplate;@Autowiredprivate MongoTransactionManager mongoTransactionManager;public int dbFunc(){TransactionTemplate transactionTemplate = new TransactionTemplate(mongoTransactionManager);return transactionTemplate.execute(status -> {try {UpdateResult updateResult = mongoTemplate.updateFirst(query, update, collection1);long l = updateResult.getUpsertedId() == null ? updateResult.getModifiedCount() : 1;if (l > 0) {mongoTemplate.insert(saveEntity, collection2);}return 1;} catch (Exception e) {// 如果发生异常,事务将在此处回滚,通过status.setRollbackOnly();或者抛出异常都可回滚status.setRollbackOnly();return 0;}});
}
如果连接是多mongos,则需要重写BaseCluster类
多mongos时使用的是随机获取的方式获取mongosClient,通过记录第一次调用的client使后续事务内的请求都通过同一个client请求,防止出现不同mongos导致事务失败情况
事务记录类
import com.mongodb.connection.Server;import java.util.function.Supplier;/*** @author kittlen* @date 2024-04-29 12:08* @description*/public class MultiServiceTransactionConfig {/*** mongodb多实例事务使用*/private static ThreadLocal<Server> mongoMultiServerTransactionUserService = new ThreadLocal<>();/*** 是否开启多实例事务*/private static ThreadLocal<Boolean> mongoMultiServerTransactionCanUser = new ThreadLocal<>();/*** 获取service** @param supplier 如果该service不存在,则获取新service的方法* @return*/public static Server getService(Supplier<Server> supplier) {Server server = mongoMultiServerTransactionUserService.get();if (server != null) {return server;} else {Server saveServer = supplier.get();mongoMultiServerTransactionUserService.set(saveServer);return saveServer;}}/*** 开启事务记录*/public static void openMultiServerTransaction() {mongoMultiServerTransactionCanUser.set(true);}/*** 是否开启多实例事务** @return*/public static boolean canOpenMultiServerTransaction() {Boolean b = mongoMultiServerTransactionCanUser.get();return Boolean.TRUE.equals(b);}/*** 清除事务配置信息*/public static void clean() {mongoMultiServerTransactionCanUser.remove();mongoMultiServerTransactionUserService.remove();}
}
重写mongodb的类com.mongodb.internal.connection.BaseCluster的selectServer方法
@Overridepublic Server selectServer(final ServerSelector serverSelector) {isTrue("open", !isClosed());try {CountDownLatch currentPhase = phase.get();ClusterDescription curDescription = description;ServerSelector compositeServerSelector = getCompositeServerSelector(serverSelector);Server server;if (this instanceof MultiServerCluster) {server = MultiServiceTransactionConfig.canOpenMultiServerTransaction() ? MultiServiceTransactionConfig.getService(() -> selectRandomServer(compositeServerSelector, description)) : selectRandomServer(compositeServerSelector, curDescription);} else {server = selectRandomServer(compositeServerSelector, curDescription);}boolean selectionFailureLogged = false;long startTimeNanos = System.nanoTime();long curTimeNanos = startTimeNanos;long maxWaitTimeNanos = getMaxWaitTimeNanos();while (true) {throwIfIncompatible(curDescription);if (server != null) {return server;}if (curTimeNanos - startTimeNanos > maxWaitTimeNanos) {throw createTimeoutException(serverSelector, curDescription);}if (!selectionFailureLogged) {logServerSelectionFailure(serverSelector, curDescription);selectionFailureLogged = true;}connect();currentPhase.await(Math.min(maxWaitTimeNanos - (curTimeNanos - startTimeNanos), getMinWaitTimeNanos()), NANOSECONDS);curTimeNanos = System.nanoTime();currentPhase = phase.get();curDescription = description;server = selectRandomServer(compositeServerSelector, curDescription);}} catch (InterruptedException e) {throw new MongoInterruptedException(format("Interrupted while waiting for a server that matches %s", serverSelector), e);}}
重点为:
Server server;if (this instanceof MultiServerCluster) {server = MultiServiceTransactionConfig.canOpenMultiServerTransaction() ? MultiServiceTransactionConfig.getService(() -> selectRandomServer(compositeServerSelector, description)) : selectRandomServer(compositeServerSelector, curDescription);} else {server = selectRandomServer(compositeServerSelector, curDescription);}
使用
try {TransactionTemplate transactionTemplate = new TransactionTemplate(mongoTransactionManager);MultiServiceTransactionConfig.openMultiServerTransaction();return transactionTemplate.execute(status -> {try {UpdateResult updateResult = mongoTemplate.updateFirst(query, update,ollection1);long l = updateResult.getUpsertedId() == null ? updateResult.getModifiedCount() : 1;if (l > 0) {mongoTemplate.insert(historyDetailsEntity, collection2);}return 1;} catch (Exception e) {// 如果发生异常,事务将在此处回滚,通过status.setRollbackOnly();或者抛出异常都可回滚status.setRollbackOnly();return 0;}});} finally {MultiServiceTransactionConfig.clean();}
相关文章:

springboot mongodb分片集群事务
前置 mongodb分片集群想要使用事务,需要对应分片没有仲裁节点 代码 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>2.1.0.RELEASE</version></d…...

node报错——解决Error: error:0308010C:digital envelope routines::unsupported——亲测可用
今天在打包vue2项目时,遇到一个报错: 最关键的代码如下: Error: error:0308010C:digital envelope routines::unsupportedat new Hash (node:internal/crypto/hash:80:19)百度后发现是node版本的问题。 在昨天我确实操作了一下node&…...
golang系统内置函数整理
go语言中有很多系统内置的函数, 为了方便学习,对系统内置函数的函数定义 入参和返回值做如下整理,以方便学习和记忆。 Go语言系统级别的内置函数不多,但是包含的知识点可不少,是学习go语言说必须要搞明白的基础知识 …...

武汉星起航:五对一服务体系,助力创业者成功进军跨境电商市场
随着全球化的深入发展和互联网的普及,跨境电商已成为越来越多国内创业者的首选。然而,跨境电商市场的复杂性和多变性使得许多新手创业者望而却步。在这样的背景下,武汉星起航电子商务有限公司以其独特的五对一服务体系,为创业者提…...

C++常用库函数——strcmp、strchr
1、strcmp:比较两个字符串的值是否相等 例如 char a1[6] "AbDeG",*s1 a1;char a2[6] "AbdEg",* s2 a2;s1 2;s2 2;printf("%d \n", strcmp(s1, s2));return(0); s1指向a1,s2指向a2,strcmp表示比较s1和s…...
vue3怎么使用vant的IndexBar 索引栏
Vant 是一个基于 Vue 的移动端 UI 组件库,它提供了许多常见的移动端组件,包括 IndexBar 索引栏。以下是如何在 Vue 3 中使用 Vant 的 IndexBar 索引栏的步骤: 安装 Vant 如果你还没有安装 Vant,你可以使用 npm 或 yarn 来安装它…...
VMware常见问题(技巧)总结
目录 问题虚拟机中windows11如何开启vt 虚拟化?虚拟机Windows 11 中的相机使用失败问题? 待续、更新中 问题 虚拟机中windows11如何开启vt 虚拟化? 编辑设置—打对钩 选对正确镜像( 可翻看以往文章,有提到) 虚拟机Windows 11 中的相机使用失败问题? 1 . 没安装合适的驱动 …...

VS Code 保存+格式化代码
在 VSCode 中,使用 Ctrl S 快捷键直接保存并格式化代码: 打开 VSCode 的设置界面:File -> Preferences -> Settings在设置界面搜索框中输入“format on save”,勾选“Editor: Format On Save”选项,表示在保存…...

word启动缓慢之Baidu Netdisk Word Addin
word启动足足花了7秒钟,你知道我这7秒是怎么过来的吗? 原因就是我们可爱的百度网盘等APP,在我们安装客户端时,默认安装了Office加载项,不仅在菜单栏上加上了一个丑陋的字眼,也拖慢了word启动速度........ 解…...

获取波形极值与间距并显示
获取并显示波形的极值与极值间距 1、流程 1、通过signal.find_peaks获取极大值 2、获取极大值下标 3、获取极大值对应的值 4、获取极大值的下标间距(就是隔多远有一个极大值) 5、获取极大值间距的标准差、方差、均值、最大值 6、图形展示波形图并标记极大值2、效果图 3、示…...

视频素材哪个app好?8个视频素材库免费使用
视频内容已成为现代传播中不可或缺的一部分,具备卓越的视频素材对于提升任何媒体作品的质量和吸引力尤为关键。这里列举的一系列精挑细选的全球视频素材网站,旨在为您的商业广告、社交媒体更新或任何其他类型的视觉项目提供最佳支持。 1. 蛙学府&#x…...
002 validation自定义校验器
文章目录 pom.xmlValidatorUtil.javaIsMobileValidator.javaIsMobile.javaLoginVo.javaLoginController.java pom.xml <!-- 引入validation依赖,完成校验 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-s…...
SQL-Server数据库--视图
1.创建视图 create view as 子查询 子查询可以是任意发杂的select语句,但通常不允许含有order by和distinct短语 --使用T-SQL语句创建新视图view_score, 要求只显示学生的学号、姓名、课号、课程名称及成绩。 create view view_score as select from tb_stude…...

Flink 部署模式
目录 概述 部署模式 会话模式(Session Mode) 单作业模式(Per-Job Mode) 应用模式(Application Mode) 运行模式(资源管理模式) Standalone运行模式 会话模式部署 应用模式部署 Yarn运行模式 会话模式部署 单作业模式部…...
第十三节:Vben Admin实战-系统管理之菜单管理
系列文章目录 基础篇 第一节:Vben Admin介绍和初次运行 第二节:Vben Admin 登录逻辑梳理和对接后端准备 第三节:Vben Admin登录对接后端login接口 第四节:Vben Admin登录对接后端getUserInfo接口 第五节:Vben Admin权限-前端控制方式 第六节:Vben Admin权限-后端控制方式…...

2024------MySQL数据库基础知识点总结
-- 最好的选择不是最明智的,而是最勇敢的,最能体现我们真实意愿的选择。 MySQL数据库基础知识点总结 一、概念 数据库:DataBase,简称DB。按照一定格式存储数据的一些文件的组合顾名思义: 存储数据的仓库,实际上就是一…...

机器学习之基于Jupyter中国环境治理投资数据分析及可视化
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 机器学习之基于Jupyter中国环境治理投资数据分析及可视化项目是一个结合了机器学习和数据可视化技术的项目…...

【Word】写论文,参考文献涉及的上标、尾注、脚注 怎么用
一、功能位置 二、脚注和尾注区别 1.首先脚注是一个汉语词汇,论文脚注就是附在论文页面的最底端,对某些内容加以说明,印在书页下端的注文。脚注和尾注是对文本的补充说明。 2.其次脚注一般位于页面的底部,可以作为文档某处内容的…...

能将图片转为WebP格式的WebP Server Go
本文完成于 2023 年 11 月 之前老苏介绍过 webp2jpg-online,可以将 webp 格式的图片,转为 jpg 等,今天介绍的 WebP Server Go 是将 jpg 等转为 webp 格式 文章传送门:多功能图片转换器webp2jpg-online 什么是 WebP ? WebP 它是由…...

省份数量00
题目链接 省份数量 题目描述 注意点 1 < n < 200isConnected[i][j] 为 1 或 0isConnected[i][i] 1isConnected[i][j] isConnected[j][i] 解答思路 最初想到的是广度优先遍历,当某个城市不属于省份,需要从该城市开始,根据isConne…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...