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 {

    

    @Bean
    public MongoTransactionManager transactionManager(MongoDbFactory factory) {
        return new MongoTransactionManager(factory);
    }
}

使用


	@Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private 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方法


	@Override
    public 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();
            }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/585207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决NetworkManager覆盖/etc/resolv.conf的问题

发布时间&#xff1a;2024.4.27 问题 /etc/resolv.conf是Linux下DNS的配置文件。 但是NetworkManager会用覆盖它&#xff0c;导致我们每次都要重新配置。 解决办法 这是官方推荐的做法。或者你可以用resolveconf工具。 $ nm-connection-editor会调起一个界面&#xff0c;…

AI视频教程下载:用ChatGPT提示词开发AI应用和GPTs

在这个课程中&#xff0c;你将深入ChatGPT的迷人世界&#xff0c;学习如何利用其能力构建创新和有影响力的工具。你将发现如何创建不仅吸引而且保持用户参与度的应用程序&#xff0c;将流量驱动到你的网站&#xff0c;并开辟新的货币化途径。 **课程的主要特点&#xff1a;** …

聊聊Mysql的两阶段提交

从图中可看出&#xff0c;事务的提交过程有两个阶段&#xff0c;就是将 redo log 的写入拆成了两个步骤&#xff1a;prepare 和 commit&#xff0c;中间再穿插写入bin log&#xff0c;具体如下&#xff1a; prepare 阶段&#xff1a;将 事务的修改写入到 redo log&#xff0c;同…

软件测试的内容包含什么内容

软件测试的内容涵盖了多个方面&#xff0c;以确保软件的质量和性能达到既定的标准。这些内容包括但不限于以下几点&#xff1a; 注册信息验证&#xff1a;对软件产品的基本信息进行验证&#xff0c;如软件名称、版本号、开发者等&#xff0c;确保这些信息的准确性和一致性。功…

图论单源最短路径——spfa

【模板】单源最短路径&#xff08;弱化版&#xff09; 本题用的spfa 题目背景 本题测试数据为随机数据&#xff0c;在考试中可能会出现构造数据让SPFA不通过&#xff0c;如有需要请移步 P4779。 题目描述 如题&#xff0c;给出一个有向图&#xff0c;请输出从某一点出发到…

React、React Router 和 Redux 常用Hooks 总结,提升您的开发效率!

Hooks 是 React 16.8 中引入的一种新特性&#xff0c;它使得函数组件可以使用 state 和其他 React 特性&#xff0c;从而大大提高了函数组件的灵活性和功能性。下面分别总结React、React Router 、Redux中常用的Hooks。 常用Hooks速记 React Hooks useState&#xff1a;用于…

单片机Debug的这几种方式,你都知道吗?

目录 一、仿真器调试 二、调试器调试 三、逻辑分析仪分析波形 四、示波器捕捉信号 五、串口调试 六、LED/蜂鸣器/显示屏调试 七、单元测试 嵌入式工程师在对单片机进行编程、结果验证、查找bug都需要用到调试的方法&#xff0c;用来进行调试定位&#xff0c;方便找出应…

相对通用大模型,企业更需要适合自身的英智私有化大模型

通用大模型虽然能在多个领域表现出强大的能力&#xff0c;但应用在特定行业时&#xff0c;表现效果并不能达到预期。因为这些模型在训练过程中并没有使用到特定行业的数据和专业知识&#xff0c;它们并不能理解和处理行业的问题。 相比之下&#xff0c;适合自身行业的私有化大…

从零开始构建大语言模型(MEAP)

原文&#xff1a;annas-archive.org/md5/c19a4ef8ab1664a3c5a59d52651430e2 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、理解大型语言模型 本章包括 大型语言模型&#xff08;LLM&#xff09;背后的基本概念的高层次解释 探索 ChatGPT 类 LLM 源自的 Transfo…

OpenTK:安装和说明

OpenTK介绍 OpenTK是一个开源、跨平台的游戏开发库&#xff0c;由MonoGame团队创建。它为C#开发者提供了一个简单易用的接口&#xff0c;以便使用OpenGL、OpenAL和OpenCL进行3D渲染、音频处理和并行计算。OpenTK的目标是提供一个一致且高效的框架&#xff0c;让开发者能够专注于…

IDEA 编码规约扫描 Code inspection did not find anything to report.

IDEA安装了Alibaba Java Coding Guidelines插件&#xff0c;却看不到规约检查结果。手动进行编码规约扫描&#xff0c;弹窗提示“Code inspection did not find anything to report.”&#xff1a; 这种情况是因为代码文件所在的目录被标记成了测试文件&#xff08;Test Source…

【ZYNQ】Zynq 开发流程

Zynq 芯片架构由嵌入式处理器&#xff08;Processing System, PS&#xff09;与可编程逻辑&#xff08;Programmable Logic, PL&#xff09;&#xff0c;以及 PS 与 PL 之间的互联总线组成。本文主要介绍 Xilinx Zynq 芯片开发所使用的软件&#xff0c;包括 Vivado IDE 与 Xili…

基于遗传算法的TSP算法(matlab实现)

一、理论基础 TSP(traveling salesman problem,旅行商问题)是典型的NP完全问题&#xff0c;即其最坏情况下的时间复杂度随着问题规模的增大按指数方式增长&#xff0c;到目前为止还未找到一个多项式时间的有效算法。TSP问题可描述为&#xff1a;已知n个城市相互之间的距离&…

JavaScript云LIS系统源码 B/S架构+SaaS模式+SQLserver可扩展性强,商业运营级区域医疗云LIS系统源码

JavaScript云LIS系统源码 B/S架构SaaS模式SQLserver可扩展性强&#xff0c;商业运营级区域医疗云LIS系统源码 云LIS&#xff08;云实验室信息管理系统&#xff09;是一种结合了计算机网络化信息系统的技术&#xff0c;它无缝嵌入到云HIS&#xff08;医院信息系统&#xff09;…

国内独家|阿里云瑶池发布ClickHouse企业版:云原生Serverless新体验

日前&#xff0c;阿里云联合ClickHouse Inc.成功举办了「ClickHouse企业版商业化发布会」。阿里云ClickHouse企业版是阿里云和ClickHouse原厂独家合作的存算分离的云原生版本&#xff0c;支持资源按需弹性Serverless&#xff0c;在帮助企业降低成本的同时&#xff0c;为企业带来…

Java学习第01天-Java及开发序言

目录 Java技术体系 Java安装 Hello World程序 JDK & JRE IDEA安装和使用 Java技术体系 技术体系说明Java SE(Java Standard Edition)&#xff1a;标准版 Java技术的核心和基础Java EE(Java Enterprise Edition)&#xff1a;企业版企业级应用开发的一套解决方案Java M…

Windows下搭建Flutter开发环境

IDE:VS code Flutter官网:Flutter: 为所有屏幕创造精彩 - Flutter 中文开发者网站 - Flutter 下载&安装 下载Flutter SDK,如图,建议自行下载安装: SDK还是挺大的,近1G,使用迅雷下载会快不少。 下载完成,解压缩到指定目录即可! 设置Local SDK,按下面步骤操作即…

经典网络解读——Efficientnet

论文&#xff1a;EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks&#xff08;2019.5&#xff09; 作者&#xff1a;Mingxing Tan, Quoc V. Le 链接&#xff1a;https://arxiv.org/abs/1905.11946 代码&#xff1a;https://github.com/tensorflow/t…

超简单的Spring-mvc示例

超简单的Spring-mvc示例

【C/C++】动态内存管理(C:malloc,realloc,calloc,free || C++:new,delete)

&#x1f525;个人主页&#xff1a; Forcible Bug Maker &#x1f525;专栏&#xff1a; C | | C语言 目录 前言C/C内存分布C语言中的动态内存管理&#xff1a;malloc/realloc/realloc/freemallocrealloccallocfree C中的动态内存管理&#xff1a;new/deletenew和delete操作内…
最新文章