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…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...