Spring Boot 3 实现 MySQL 主从数据库之间的数据同步
✅ Spring Boot 3 实现 MySQL 主从数据库之间的数据同步
在实际项目中,为了提高 系统的读性能 和 数据的可用性,通常会使用 主从数据库架构。Spring Boot 提供了对 多数据源 的良好支持,可以轻松配置 主从数据库 的数据同步,实现 读写分离。
🎯 方案介绍
我们将通过 Spring Boot 3 来实现以下目标:
- 主库(Master):处理所有的 写操作(
INSERT
、UPDATE
、DELETE
)。 - 从库(Slave):处理所有的 读操作(
SELECT
)。
通过 读写分离 的方式,我们可以有效减轻主库的压力,同时提升系统的读性能。
📋 步骤 1:配置 MySQL 主从同步
首先,确保你的 MySQL 主从服务器已经配置好。
如果你还没有配置主从,请参考以下步骤:
- 在 主库 上启用 binlog 日志。
- 在 从库 上配置
CHANGE MASTER TO
语句。
具体配置可以参考这里的指南:
👉 MySQL 主从同步配置
📋 步骤 2:Spring Boot 多数据源配置
1️⃣ 添加依赖
在 pom.xml
文件中添加 MySQL 驱动 和 Spring Data JPA 依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
2️⃣ 配置 application.properties
配置 主库 和 从库 的数据源。
# 主库数据源
spring.datasource.master.url=jdbc:mysql://localhost:3306/master_db
spring.datasource.master.username=root
spring.datasource.master.password=master_password
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver# 从库数据源
spring.datasource.slave.url=jdbc:mysql://localhost:3306/slave_db
spring.datasource.slave.username=root
spring.datasource.slave.password=slave_password
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
3️⃣ 配置多数据源
创建 MasterDataSourceConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.repository",entityManagerFactoryRef = "masterEntityManager",transactionManagerRef = "masterTransactionManager"
)
public class MasterDataSourceConfig {@Primary@Bean(name = "masterDataSource")@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDataSource() {return DataSourceBuilder.create().build();}@Primary@Bean(name = "masterEntityManager")public LocalContainerEntityManagerFactoryBean masterEntityManager(EntityManagerFactoryBuilder builder,@Qualifier("masterDataSource") DataSource dataSource) {return builder.dataSource(dataSource).packages("com.example.entity").persistenceUnit("master").build();}@Primary@Bean(name = "masterTransactionManager")public PlatformTransactionManager masterTransactionManager(@Qualifier("masterEntityManager") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}
}
创建 SlaveDataSourceConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.repository",entityManagerFactoryRef = "slaveEntityManager",transactionManagerRef = "slaveTransactionManager"
)
public class SlaveDataSourceConfig {@Bean(name = "slaveDataSource")@ConfigurationProperties(prefix = "spring.datasource.slave")public DataSource slaveDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "slaveEntityManager")public LocalContainerEntityManagerFactoryBean slaveEntityManager(EntityManagerFactoryBuilder builder,@Qualifier("slaveDataSource") DataSource dataSource) {return builder.dataSource(dataSource).packages("com.example.entity").persistenceUnit("slave").build();}@Bean(name = "slaveTransactionManager")public PlatformTransactionManager slaveTransactionManager(@Qualifier("slaveEntityManager") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}
}
4️⃣ 实现读写分离的 AOP 拦截器
为了自动将 写操作 路由到主库、读操作 路由到从库,可以使用 AOP 来实现。
创建 DataSourceContextHolder
public class DataSourceContextHolder {private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();public static void setDataSource(String dataSource) {CONTEXT.set(dataSource);}public static String getDataSource() {return CONTEXT.get();}public static void clear() {CONTEXT.remove();}
}
创建 DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSource();}
}
创建 DataSourceAspect
@Aspect
@Component
public class DataSourceAspect {@Pointcut("execution(* com.example.service..*.read*(..))")public void readPointcut() {}@Pointcut("execution(* com.example.service..*.write*(..))")public void writePointcut() {}@Before("readPointcut()")public void useSlaveDataSource() {DataSourceContextHolder.setDataSource("slaveDataSource");}@Before("writePointcut()")public void useMasterDataSource() {DataSourceContextHolder.setDataSource("masterDataSource");}@After("readPointcut() || writePointcut()")public void clearDataSource() {DataSourceContextHolder.clear();}
}
📋 步骤 3:测试读写分离
创建一个测试服务类
@Service
public class UserService {@Transactionalpublic void writeUser(User user) {userRepository.save(user);}@Transactional(readOnly = true)public List<User> readUsers() {return userRepository.findAll();}
}
测试读写操作
@RestController
@RequestMapping("/users")
public class UserController {private final UserService userService;public UserController(UserService userService) {this.userService = userService;}@PostMappingpublic void createUser(@RequestBody User user) {userService.writeUser(user);}@GetMappingpublic List<User> getUsers() {return userService.readUsers();}
}
🎯 总结
主从同步架构的优势:
优势 | 描述 |
---|---|
提升读性能 | 将大量读请求分发到从库,减轻主库压力 |
提高可用性 | 从库可用作备份库,主库故障时从库可切换为主库 |
数据一致性保障 | 通过半同步或异步复制保障数据一致性 |
相关文章:
Spring Boot 3 实现 MySQL 主从数据库之间的数据同步
✅ Spring Boot 3 实现 MySQL 主从数据库之间的数据同步 在实际项目中,为了提高 系统的读性能 和 数据的可用性,通常会使用 主从数据库架构。Spring Boot 提供了对 多数据源 的良好支持,可以轻松配置 主从数据库 的数据同步,实现…...

【小程序开发】- 小程序版本迭代指南(版本发布教程)
一,版本号 版本号是小程序版本的标识,通常由一系列数字组成,如 1.0.0、1.1.0 等。版本号的格式通常是 主版本号.次版本号.修订号 主版本号:当小程序有重大更新或不兼容的更改时,主版本号会增加。 次版本号:…...
MySQL 间隙锁避免“可重复读”出现“幻读”
在数据库事务处理中,可重复读(Repeatable Read)是一个常用的隔离级别,但其默认行为可能导致幻读现象。然而,在 MySQL 的实现中,通过 **间隙锁(Gap Lock)**机制,能够避免幻…...

揭秘区块链隐私黑科技:零知识证明如何改变未来
文章目录 1. 引言:什么是零知识证明?2. 零知识证明的核心概念与三大属性2.1 完备性(Completeness)2.2 可靠性(Soundness)2.3 零知识性(Zero-Knowledge) 3. 零知识证明的工作原理4. 零…...
JavaWeb开发:从入门到精通
近年来,JavaWeb开发已经成为了互联网开发领域的重要技术之一。无论是大型企业还是个人项目,都离不开JavaWeb开发。本文将为您介绍JavaWeb开发的基本概念、常用技术和开发流程,帮助您快速入门并掌握这一技术。 一、JavaWeb开发的基本概念 Jav…...

2025年01月07日Github流行趋势
项目名称:khoj 项目地址url:https://github.com/khoj-ai/khoj项目语言:Python历史star数:20105今日star数:363项目维护者:debanjum, sabaimran, MythicalCow, aam-at, shantanuSakpal项目简介:你…...

c#集成npoi根据excel模板导出excel
NuGet中安装npoi 创建excel模板,替换其中的内容生成新的excel文件。 例子中主要写了这四种情况: 1、替换单个单元格内容; 2、替换横向多个单元格; 3、替换表格; 4、单元格中插入图片; using System.IO; …...

Vue2移动端(H5项目)项目封装switch组件支持动态设置开启关闭背景色、值及组件内显示文字描述、禁用、switch 的宽度
前言 近期产品需求:Vue2移动端项目需要在switch开关内显示文字,看Vantui没有对应功能,因此自己手撸写了这个组件。 一、最终效果 二、参数配置 1、代码示例: <t-switch v-model"check"/>2、配置参数(…...
MATLAB语言的语法糖
MATLAB语言的语法糖 引言 在编程语言的发展历程中,语法糖(Syntactic Sugar)被广泛提及。它指的是一种编程语言的语法特性,旨在使代码更易读、更易写,虽然这些特性并不增加语言的表达能力,但能使程序员的生…...

数字IC设计高频面试题
在数字IC设计领域,面试是评估候选人技术能力和问题解决能力的重要环节。数字IC设计的复杂性和要求在不断提高。面试官通常会提出一系列面试题,以考察应聘者在数字设计、验证、时钟管理、功耗优化等方面的专业知识和实践经验。 这些题目不仅涉及理论知识…...
OpenCV 4.5至4.10版本更新概述
OpenCV 4.5至4.10版本更新概述 OpenCV 从 4.5 到 4.10 版本的更迭中,每个版本都引入了新功能、优化和修复。以下是主要版本的更新内容概述: OpenCV 4.5.x 系列 4.5.0 (2020年10月) 新增对 YOLOv4 的支持。引入 DNN 模块的改进,包括对 ONNX …...
OSPF - LSA对照表
LSA的三要素,如何唯一表示一条LSA Type:表示是几类的LSA Link-id:这个比较特殊,不同的LSA的Link-ID不同 Advertising router:谁产生的LSA 常用的就是1、2、3、4、5、7型LSA 点击蓝字跳转LSA详细介绍(持续更新中…...

游戏引擎学习第77天
仓库: https://gitee.com/mrxiao_com/2d_game 回顾昨天的 bug 今天我们继续开发进度,进行调试昨天代码的问题,主要是关于如何跟踪玩家和敌人在世界中的高度位置。虽然我们做的是一款 2D 游戏,但我们希望能够处理多层的房间,玩家…...

【项目实战1】五子棋游戏
目录 C语言编程实现五子棋:: game.h game.c 1.打印菜单 2.打印棋盘 3.玩家下棋 4.判断五子连珠 5.判断输赢 6.游戏运行 game.c完整源代码展示 test.c C语言编程实现五子棋:: game.h #pragma once #include<stdio.h> …...
HTML5 动画效果:淡入淡出(Fade In/Out)详解
HTML5 动画效果:淡入淡出(Fade In/Out)详解 淡入淡出(Fade In/Out)是一种常见的动画效果,使元素逐渐显现或消失,增强用户体验。以下是淡入淡出的详细介绍及实现示例。 1. 淡入淡出的特点 平滑…...
Conmi的正确答案——Cordova使用“src-cordova/config.xml”编辑“Android平台”的“uses-permission”
Cordova版本:12.0.0 (cordova-lib12.0.1) 1、配置例程: <platform name"android"><config-file target"AndroidManifest.xml" parent"/manifest"><uses-permission android:name"android.permission…...

在Mysql环境下对数据进行增删改查
一、插入数据: insert into 表名 [(字段名)] values (字段对应的值1,字段对应的值2,…)[,(字段对应的值1,字段对应的值2,…)]; insert into students (id,name,age,height,gender,cls_id,is_delete) values (0,小明,18,180.00,2,1,0)在学生表中插入“小明”数据的…...

Spring 设计模式:经典设计模式
Spring 设计模式:经典设计模式 引言 Spring 框架广泛使用了经典设计模式。 这些模式在 Spring 内部发挥着重要作用。 通过理解这些设计模式在 Spring 中的应用,开发者可以更深入地掌握 Spring 框架的设计哲学和实现细节。 经典设计模式 控制反转&am…...
OneFlow和PyTorch在性能上有哪些区别?
OneFlow 和 PyTorch 在性能上的区别主要体现在以下几个方面: 本篇文章的目录 分布式训练性能 硬件利用率和显存优化 模型训练速度 OneFlow:默认采用静态图模式,在模型训练前会对计算图进行编译优化,能够减少运行时的开销&…...

win下搭建elk并集成springboot
一、ELK 是什么? ELK 实际上是三个工具的集合,Elasticsearch Logstash Kibana,这三个工具组合形成了一套实用、易用的监控架构,很多公司利用它来搭建可视化的海量日志分析平台。 ElasticSearch ElasticSearch 是一个基于 Lucen…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...