Spring Boot+MyBatis+MySQL如何实现读写分离

news2024/11/15 18:52:07

 ​

博客主页:     南来_北往

系列专栏:Spring Boot实战


背景

读写分离是数据库架构中的一种优化策略,它将读操作(查询)和写操作(更新、插入、删除)分开处理,通常通过将读请求和写请求分别发送到不同的数据库服务器来实现。下面介绍实现读写分离的原因:

  1. 提高并发能力:在高并发访问场景下,读写分离可以有效地分散请求,提高系统的整体性能。例如,在电商平台中,用户浏览商品的次数远超实际购买的次数,因此将读取操作分配给专门的读库,可以显著降低对主数据库的压力。
  2. 优化资源利用:对于数据分析和报告生成任务,需要大量数据读取,而通过读写分离,这些操作不会影响在线事务处理的性能。这样,企业可以进行高效的数据分析,同时确保日常业务的稳定运行。
  3. 提升读取性能:读写分离通过多台读库分摊读取压力,从而大幅提升读性能。这对于需要快速响应的数据检索需求尤为关键。
  4. 减轻写入负担:在互联网应用中,写操作通常比读操作耗时得多。通过将写操作集中在一个数据库上,并同步到多个读库,可以保证写操作的效率和一致性。
  5. 应对不同场景:读写分离适用于多种业务场景,包括高并发访问、数据分析和报告、以及数据仓库等。在这些场景中,读写分离能够优化资源分配,满足不同的业务需求。
  6. 支持决策分析:通过读写分离,可以前置处理大量的汇总数据,使得企业的决策分析更加迅速和准确。例如,某公司采用基于FDL的离线数仓方案进行读写分离后,大幅提高了BI报表的稳定性和数据的决策分析能力。

总之,读写分离不仅能有效提升数据库性能,还能根据不同的业务需求,提供灵活的数据处理能力。然而,在实施时也需考虑数据同步延迟、一致性等问题,以确保系统整体的稳定性和可靠性。

实践

1、配置数据源:在application.properties或application.yml文件中配置两个数据源,一个用于读操作(slave),另一个用于写操作(master)。

# application.yml
spring:
  datasource:
    master:
      url: jdbc:mysql://localhost:3306/master_db?useSSL=false&serverTimezone=UTC
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      url: jdbc:mysql://localhost:3306/slave_db?useSSL=false&serverTimezone=UTC
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver

 2、创建数据源配置类:创建一个配置类,用于创建和配置两个数据源。

@Configuration
public class DataSourceConfig {

    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }
}

 3、建SqlSessionFactory:为每个数据源创建一个SqlSessionFactory。

@Configuration
public class MyBatisConfig {

    @Autowired
    @Qualifier("masterDataSource")
    private DataSource masterDataSource;

    @Autowired
    @Qualifier("slaveDataSource")
    private DataSource slaveDataSource;

    @Bean(name = "masterSqlSessionFactory")
    public SqlSessionFactory masterSqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(masterDataSource);
        return factoryBean.getObject();
    }

    @Bean(name = "slaveSqlSessionFactory")
    public SqlSessionFactory slaveSqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(slaveDataSource);
        return factoryBean.getObject();
    }
}

4、建事务管理器:为每个数据源创建一个事务管理器。

@Configuration
public class TransactionManagerConfig {

    @Autowired
    @Qualifier("masterDataSource")
    private DataSource masterDataSource;

    @Autowired
    @Qualifier("slaveDataSource")
    private DataSource slaveDataSource;

    @Bean(name = "masterTransactionManager")
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource);
    }

    @Bean(name = "slaveTransactionManager")
    public DataSourceTransactionManager slaveTransactionManager() {
        return new DataSourceTransactionManager(slaveDataSource);
    }
}

5、建动态数据源:根据需要切换不同的数据源。

public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }
}

 6、配置动态数据源:将动态数据源与SqlSessionFactory和事务管理器关联。

@Configuration
public class DataSourceConfig {

    @Autowired
    @Qualifier("masterSqlSessionFactory")
    private SqlSessionFactory masterSqlSessionFactory;

    @Autowired
    @Qualifier("slaveSqlSessionFactory")
    private SqlSessionFactory slaveSqlSessionFactory;

    @Autowired
    @Qualifier("masterTransactionManager")
    private DataSourceTransactionManager masterTransactionManager;

    @Autowired
    @Qualifier("slaveTransactionManager")
    private DataSourceTransactionManager slaveTransactionManager;

    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterSqlSessionFactory);
        targetDataSources.put("slave", slaveSqlSessionFactory);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterSqlSessionFactory);
        return dynamicDataSource;
    }

    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager() {
        DynamicDataSourceTransactionManager transactionManager = new DynamicDataSourceTransactionManager();
        transactionManager.setTransactionManagers(Arrays.asList(masterTransactionManager, slaveTransactionManager));
        return transactionManager;
    }
}

 7、用注解切换数据源:在Service层的方法上使用@DS注解来切换数据源。例如,读取操作使用从库,写入操作使用主库。

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @DS("master")
    public void addUser(User user) {
        userMapper.insert(user);
    }

    @DS("slave")
    public List<User> findAllUsers() {
        return userMapper.selectAll();
    }
}

8、最后,需要在启动类上添加@EnableTransactionManagement注解以启用事务管理。

@SpringBootApplication
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年全国青少年信息素养大赛总决赛日赛程表

2024全国青少年信息素养大赛赛程表分赛场&#xff08;浙江传媒学院桐乡校区、桐乡技师学院&#xff09;日期地点时间赛项16日传媒学院8:00-9:00检录 9:00-10:30开赛图形化编程挑战赛&#xff08;小学1-3年级&#xff09;A组12:00-13:00检录 13:00-14:30开赛图形化编程挑战赛&am…

最新版Baby Audio Bundle,win和mac,持续更新,长期有效

一。Baby Audio Bundle.2024.07.WiN&MAC Baby Audio让您的混音听起来比以往任何时候都更大&#xff0c;更好&#xff0c;更有活力。这个捆绑包有七个独特的插件&#xff0c;涵盖了从延迟和混响效果&#xff08;Spaced Out&#xff09;到低保真声音&#xff08;Super VHS&am…

MySQL(8.0)数据库安装和初始化以及管理

1.MySQL下载安装和初始化 1.下载安装包 下载地址&#xff1a;https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 2.解压…

手把手使用 SVG + CSS 实现渐变进度环效果

效果 轨道 使用 svg 画个轨道 <svg viewBox"0 0 100 100"><circle cx"50" cy"50" r"40" fill"none" stroke-width"10" stroke"#333"></circle></svg>简单的说&#xff0c;就是…

shell脚本(自动化安装各种服务)

1、自动化配置DNS服务 [rootelemestatic ~]# vim dns.sh [rootelemestatic ~]# bash dns.sh 客户端测试&#xff1a; yum -y install bind-utils echo "nameserevr 192.168.8.161" > /etc/resolv.conf nslookup www.a.com 2、自动化配置rsync服务 [rootele…

如何用Python删除电脑中的重复文件?

在生活中&#xff0c;我们经常会遇到电脑中文件重复的情况。 在文件较少的情况下&#xff0c;这类情况还比较容易处理&#xff0c;最不济就是一个个手动对比删除&#xff1b; 而在重复文件很多的时候&#xff0c;我们很难保证把重复文件全部删完。 这里给大家带来了一个便捷…

《计算机组成原理》(第3版)第2章 计算机的发展及应用 复习笔记

第2章 计算机的发展及应用 一、计算机的产生和发展 &#xff08;一&#xff09;第一代电子管计算机 1943年&#xff0c;美国国防部批准了建造一台用电子管组成的电子数字积分机和计算机&#xff08;Electronic Numerica1 Integrator And Computer&#xff0c;ENIAC&#xff…

2024年06月 Scratch 图形化(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共10题,共30分) 第1题 运行下列程序,输入单词“PLAY”,最后角色说?( ) A:LY4AP B:AP4LY C:YA4PL D:PL4AY 答案:B 根据程序分析可知,首先获取单词字符数,然后奇数位的字母放在字符数左侧,偶数位…

基于STM32的嵌入式深度学习系统教程

目录 引言环境准备嵌入式深度学习系统基础代码实现&#xff1a;实现嵌入式深度学习系统 数据采集与预处理深度学习模型训练与优化模型部署与推理实时数据处理与反馈应用场景&#xff1a;智能物联网设备常见问题与解决方案收尾与总结 引言 随着深度学习在各种应用中的广泛采用…

HBuilder在uni-admin实现unicloud-map中poi管理

文章目录 新建uni-admin项目下载并导入插件申请地图key并配置&#xff08;本人使用的腾讯地图&#xff09;配置WebServiceAPI配置HBuilder中Web配置 启动项目进行菜单管理 新建uni-admin项目 新建项目时选择uni-admin模板 下载并导入插件 在unicloud介绍页面https://doc.dc…

GraphGNSSLib的RTKLIB——gnss_preprocessor.node的理解

gnss_preprocessor部分的理解&#xff0c;这是简单的几张流程图截图&#xff0c;自己的分析总结pdf在资源里&#xff0c;免费的&#xff0c;如果不占用大家资源可以下载&#xff0c;交流 整体的逻辑详见资源 &#xff0c;我承诺这是自己系统分析RTKLIB后&#xff0c;进行的…

苹果iOS开发中的网络数据任务API:URLSession入门实战

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 URLSession 是 iOS 开发中的一个 API&#xff0c;用于执行网络数据任务&#xff0c;如 HTTP 请求、文件下载和上传等。URLSession 提供了一种高…

射频工程师主要是干什么?

在硬件从业者中&#xff0c;有一部分从业者是专门负责射频&#xff0c;天线&#xff0c;基站信号相关工作内容的&#xff0c;他们也被称为射频工程师。并且相比与普通的硬件工程师&#xff0c;硬件测试工程师&#xff0c;专门做射频部分的射频工程师&#xff0c;相同年限下薪资…

LLM:混合精度量化概述

浮点数在计算机中的存储方式由符号位&#xff08;sign&#xff09;、指数位&#xff08;exponent&#xff09;和小数位&#xff08;fraction&#xff0c;也称为尾数、mantissa&#xff09;组成。以下是对这些部分的详细说明&#xff1a; 符号位&#xff08;Sign Bit&#xff09…

【Vue3】组件通信之props

【Vue3】组件通信之props 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日…

发送邮箱调用接口时需要注意哪些安全事项?

发送邮箱调用接口的使用方法&#xff1f;如何集成三方API接口&#xff1f; 无论是系统通知、用户注册验证还是营销邮件&#xff0c;这些功能都依赖于邮件发送接口的稳定和安全。然而&#xff0c;确保这些接口的安全性是至关重要的&#xff0c;AokSend将详细讨论在发送邮箱调用…

超13万律师使用的工具,启信宝推出“司法大数据”功能

合合信息旗下的启信宝&#xff0c;作为行业领先的商业查询APP&#xff0c;依托其3亿企业及机构的实时动态数据&#xff0c;涵盖工商、股权、司法、知识产权等多维度信息&#xff0c;推出了“司法大数据”功能。 随着大数据、人工智能技术的发展&#xff0c;律师行业已转型为开…

怎么写文献综述

怎么写文献综述 写文献综述是对已有文献资料进行系统性和批判性的评述和总结&#xff0c;以了解当前研究领域的研究成果和发展动态。 以下是撰写文献综述的一般步骤&#xff1a; 选择主题和目标&#xff1a; 确定你要综述的主题领域&#xff0c;并明确综述的目标和范围。这有…

蓝牙网关和蓝牙MESH总结

可参考&#xff1a; https://zhuanlan.zhihu.com/p/695144946 蓝牙网关 参考&#xff1a; https://www.bilibili.com/read/cv28872282/ 蓝牙网关是一种特殊的网络设备&#xff0c;它能够实现蓝牙设备与互联网或其他类型网络之间的数据传输和通信。通过蓝牙网关&#xff0c;用户…

Leetcode238. 除自身以外数组的乘积(java实现)

今天分享的题目是letcode238. 除自身以外数组的乘积 先来看题目描述&#xff1a; 本道题我最先想到的是先乘积所有的元素&#xff0c;然后除以所有元素&#xff0c;但是本题无法使用除法。 本题的解题思路是使用前缀积。 拿nums[]{1,2,3,4}; 先遍历前缀积&#xff0c;num[0]的…