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…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
