Spring Boot 实现读写分离,还有谁不会?

【GameFramework框架工具链】5-1、DataTable数据表 类自动生成工具 这个是跟【GameFramework框架内置模块】3、数据表(Data Table)模块配合使用的工具链。在使用数据表的时候,我们需要先准备数据表,每个数据表对应一个C#,C#对应表里面的字段,然后使用里面的信息,比如Music数据表ID int类型 IDAssetName string类型 资源名然后,根据数据表生成C#实体类,这一块有一个StarForce的工具链,我们来看一下如何使用。 阅读详情

第一步:配置多数据源

Spring Boot 基础就不介绍了,推荐下这个实战教程:https://github.com/javastacks/spring-boot-best-practice

首先,我们在 SpringBoot 中配置两个数据源,其中第二个数据源是ro-datasource:

spring:
  datasource:
    jdbc-url: jdbc:mysql://localhost/test
    username: rw
    password: rw_password
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
      pool-name: HikariCP
      auto-commit: false
      ...
  ro-datasource:
    jdbc-url: jdbc:mysql://localhost/test
    username: ro
    password: ro_password
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
      pool-name: HikariCP
      auto-commit: false
      ...

在开发环境下,没有必要配置主从数据库。只需要给数据库设置两个用户,一个rw具有读写权限,一个ro只有 SELECT 权限,这样就模拟了生产环境下对主从数据库的读写分离。

在 SpringBoot 的配置代码中,我们初始化两个数据源:

@SpringBootApplication
public class MySpringBootApplication {
    /**
     * Master data source.
     */
    @Bean("masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    DataSource masterDataSource() {
       logger.info("create master datasource...");
        return DataSourceBuilder.create().build();
    }

    /**
     * Slave (read only) data source.
     */
    @Bean("slaveDataSource")
    @ConfigurationProperties(prefix = "spring.ro-datasource")
    DataSource slaveDataSource() {
        logger.info("create slave datasource...");
        return DataSourceBuilder.create().build();
    }

    ...
}

第二步:编写 RoutingDataSource

然后,我们用 Spring 内置的 RoutingDataSource,把两个真实的数据源代理为一个动态数据源:

public class RoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return "masterDataSource";
    }
}

对这个RoutingDataSource,需要在 SpringBoot 中配置好并设置为主数据源:

@SpringBootApplication
public class MySpringBootApplication {
    @Bean
    @Primary
    DataSource primaryDataSource(
            @Autowired @Qualifier("masterDataSource") DataSource masterDataSource,
            @Autowired @Qualifier("slaveDataSource") DataSource slaveDataSource
    ) {
        logger.info("create routing datasource...");
        Map<Object, Object> map = new HashMap<>();
        map.put("masterDataSource", masterDataSource);
        map.put("slaveDataSource", slaveDataSource);
        RoutingDataSource routing = new RoutingDataSource();
        routing.setTargetDataSources(map);
        routing.setDefaultTargetDataSource(masterDataSource);
        return routing;
    }
    ...
}

现在,RoutingDataSource 配置好了,但是,路由的选择是写死的,即永远返回"masterDataSource",

现在问题来了:如何存储动态选择的 key 以及在哪设置 key?

在 Servlet 的线程模型中,使用 ThreadLocal 存储 key 最合适,因此,我们编写一个 RoutingDataSourceContext,来设置并动态存储 key:

public class RoutingDataSourceContext implements AutoCloseable {

    // holds data source key in thread local:
    static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>();

    public static String getDataSourceRoutingKey() {
        String key = threadLocalDataSourceKey.get();
        return key == null ? "masterDataSource" : key;
    }

    public RoutingDataSourceContext(String key) {
        threadLocalDataSourceKey.set(key);
    }

    public void close() {
        threadLocalDataSourceKey.remove();
    }
}

然后,修改 RoutingDataSource,获取 key 的代码如下:

public class RoutingDataSource extends AbstractRoutingDataSource {
    protected Object determineCurrentLookupKey() {
        return RoutingDataSourceContext.getDataSourceRoutingKey();
    }
}

这样,在某个地方,例如一个 Controller 的方法内部,就可以动态设置 DataSource 的 Key:

@Controller
public class MyController {
    @Get("/")
    public String index() {
        String key = "slaveDataSource";
        try (RoutingDataSourceContext ctx = new RoutingDataSourceContext(key)) {
            // TODO:
            return "html... www.liaoxuefeng.com";
        }
    }
}

到此为止,我们已经成功实现了数据库的动态路由访问。

这个方法是可行的,但是,需要读从数据库的地方,就需要加上一大段try (RoutingDataSourceContext ctx = ...) {}代码,使用起来十分不便。有没有方法可以简化呢?

有!

我们仔细想想,Spring 提供的声明式事务管理,就只需要一个@Transactional()注解,放在某个 Java 方法上,这个方法就自动具有了事务。

我们也可以编写一个类似的@RoutingWith("slaveDataSource")注解,放到某个 Controller 的方法上,这个方法内部就自动选择了对应的数据源。代码看起来应该像这样:

@Controller
public class MyController {
    @Get("/")
    @RoutingWith("slaveDataSource")
    public String index() {
        return "html... www.liaoxuefeng.com";
    }
}

这样,完全不修改应用程序的逻辑,只在必要的地方加上注解,自动实现动态数据源切换,这个方法是最简单的。

想要在应用程序中少写代码,我们就得多做一点底层工作:必须使用类似 Spring 实现声明式事务的机制,即用 AOP 实现动态数据源切换。

实现这个功能也非常简单,编写一个RoutingAspect,利用 AspectJ 实现一个Around拦截:

@Aspect
@Component
public class RoutingAspect {
    @Around("@annotation(routingWith)")
    public Object routingWithDataSource(ProceedingJoinPoint joinPoint, RoutingWith routingWith) throws Throwable {
        String key = routingWith.value();
        try (RoutingDataSourceContext ctx = new RoutingDataSourceContext(key)) {
            return joinPoint.proceed();
        }
    }
}

注意方法的第二个参数RoutingWith是 Spring 传入的注解实例,我们根据注解的value()获取配置的 key。编译前需要添加一个 Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

到此为止,我们就实现了用注解动态选择数据源的功能。最后一步重构是用字符串常量替换散落在各处的"masterDataSource"和"slaveDataSource"。

使用限制

受 Servlet 线程模型的局限,动态数据源不能在一个请求内设定后再修改,也就是@RoutingWith不能嵌套。此外,@RoutingWith和@Transactional混用时,要设定 AOP 的优先级。

本文代码需要 SpringBoot 支持,JDK 1.8 编译并打开-parameters编译参数。

 

DPABISurf使用教材 严老师的官方教程:http://rfmri.org/Course DPABISurf版本:dpabi50docker.tar.gz MATLAB版本:2018b 一、数据准备 (1)如果是数据的DICOM格式,整理成以下格式(注意文件夹的命名方式): 如果觉得不是很清楚,可以在官网下载Demo数据(http://rfmri.org/DemoData),参照里面的文件格式进行整理即可。 (2)如果数据是nii格式,整理成以下格式: 这里没有使用官网的demo数据进行学习,而是.. 阅读详情

相关推荐

LabVIEW状态机实战:用STM32+DHT11搭建温湿度监测系统(附完整VI源码)

本文详细介绍了如何利用LabVIEW状态机模式与STM32微控制器、DHT11温湿度传感器构建温湿度监测系统。通过硬件选型、状态机设计、LabVIEW程序实现及系统优化等环节,提供了一套完整的解决方案,并附有VI源码,助力开发者快速实现嵌入式温湿度监测应用。

weixin_42549723的博客 524

Spring Boot 实现读写分离

1、上流程图 2、配置多数据源 首先,我们在 SpringBoot 中配置两个数据源,其中第二个数据源是ro-datasource: 这里可以配置两个不同的数据库作为主从数据库,这里为了方便给数据库设置两个用户来实现读写分离 spring: datasource: jdbc-url: jdbc:mysql://localhost/test username: rw password: rw_password driver-class-name: com.mysql.jd

zouyang920的博客 7870

浙江大学Fast-Lab从0制作自主空中机器人公开课教程补充及部分注意事项(适用于ubuntu系统和ROS零基础)

浙江大学Fast-Lab从0制作自主空中机器人公开课纯萌新补充(适用于从没接触过ubuntu系统),记录了一些自己不会的地方以及踩过的坑

qq_39986834的博客 2987

SpringBoot读写分离

SpringBoot读写分离 1.引言 ​ 读写分离要做的事情就是对于一条请求执行的sql,该选择哪一个数据库进行操作,而谁去做选择,无非就是两个,一个是让中间件帮我们去做,而另一个则是让程序自己做。 2.背景 随着用户数量的增加,系统访问量增大,数据库压力增大,众所周知,系统的读请求必然非常庞大,因此且读和写在同一个库中进行会进一步加大数据库压力,造成数据库挂掉的风险,因此需要进行读写分离以减轻数据库压力。 3.解决方法 MyCat中间件进行读写分离 优点:可以横向扩展,动态增加数据库节点,无

qq_31708899的博客 3823

FitzHugh-Nagumo 模型连续-MATLAB仿真

【代码】FitzHugh-Nagumo 模型连续-MATLAB仿真。

qq_43688618的博客 885

腾讯WeKnora开源了!手把手教你用Docker+Ollama本地部署多模态知识库(附避坑指南)

本文详细介绍了腾讯开源的多模态知识库工具WeKnora的本地部署方法,通过Docker和Ollama实现完全离线运行。文章包含环境准备、核心组件配置、Ollama模型集成、系统启动验证及高级性能调优等实战内容,特别适合需要构建私有化知识库的中小团队和个人开发者。

weixin_30664051的博客 479

SpringBoot 数据库读写分离

两台虚拟机,分别安装Mysql并启动服务成功: 主库Master 192.168.0.205 从库Slave 192.168.0.206 在主机中运行(192.168.0.205) 添加配置 2.3 配置主库Master 注:上面SQL的作用是创建一个用户xiaoming,密码为Root@123456,并且给xiaoming用户授予REPLICATION SLAVE权限。常用于建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权

Star_lll的博客 1894

保姆级教程:从WOS下载文献到Citespace出图,手把手搞定科研可视化(附避坑指南)

本文提供从WOS下载文献到Citespace出图的完整科研可视化指南,涵盖数据采集、清洗、环境配置和可视化优化全流程。特别分享WOS检索技巧、数据清洗方法和Citespace参数设置,帮助科研新手高效生成专业图谱,避开常见技术陷阱。

weixin_29311017的博客 174

SpringBoot+读写分离

提示:本篇博客内容,来自于学习黑马程序员javaWeb+MySQL教程实践结果读写分离环境至少需要两台数据库服务器,因此阅读本篇文章前,需要在Liunx服务器上安装上MySQL8.0版本,并且需要一定的liunx命令基础语法,Liunx环境搭建MySQL教程,可以参考主页相关文章。读写分离,简单地来说就是把对数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效减轻单台数据库的压力。

qq_42211536的博客 3149

【精细解读】xapp585(多通道LVDS接口ADC)

xapp585的参考设计有Verilog和VHDL两种源码。

FPGA艺术家的博客 534

手把手教你学Simulink--基于Simulink的开关磁阻电机电流斩波控制仿真建模

特点:定子和转子均由普通硅钢片叠压而成,没有永磁体或绕组在转子上。工作原理:利用转子旋转时不同位置的磁阻变化产生转矩。控制挑战:由于SRM的高度非线性和磁饱和效应,需要复杂的控制算法来优化性能。利用Simscape Electrical中的模块构建SRM的物理模型,配置参数如电阻、电感等。matlab深色版本% 添加SRM电机模块根据实际需求调整电机参数。通过上述步骤,我们简要介绍了如何基于Simulink进行开关磁阻电机的电流斩波控制仿真建模。

MHD0815的博客 306

springboot多数据源

application-druid.yml # 数据源配置 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver druid: # 主库数据源 master: url: jdbc:mysql://localhost:

weixin_43298522的博客 1277

【定制功能】LVGL 页面管理

页面管理的主要针对实际复杂的UI项目的。支持多页面管理,包含页面跳转和返回(主要是方便项目功能管理)支持后台页面自动销毁、前台页面自动创建(主要是节约资源使用)支持语言切换逻辑(页面重建功能)支持主题切换逻辑支持页面切换动画效果首先,页面管理是针对act_src图层来讲的。仅在screens数组中供act_src切换的对象树才会被此页面管理功能所管理。这意味着,如果top_layer或者sys_layer图层上,有页面需要重建时,需要特殊处理(实际项目中top_layer或者。

Bigan(安)的博客 5753

Spring Boot 实现读写分离,还有谁不会

第一步:配置多数据源 Spring Boot 基础就不介绍了,推荐下这个实战教程: github.com/javastacks/… 首先,我们在 SpringBoot 中配置两个数据源,其中第二个数据源是ro-datasource: spring: datasource: jdbc-url: jdbc:mysql://localhost/test username: rw password: rw_password driver-class-name: com..

mxy2404830的博客 916

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Spring Boot 实现读写分离,不会还有人不会吧?

第一步:配置多数据源 Spring Boot 基础就不介绍了,推荐下这个实战教程: github.com/javastacks/… 首先,我们在 SpringBoot 中配置两个数据源,其中第二个数据源是ro-datasource: spring: datasource: jdbc-url: jdbc:mysql://localhost/test username: rw password: rw_password driver-class-name: c...

wdjnb的博客 649

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Spring Boot 实现读写分离,还有谁不会??

Spring Boot 基础就不介绍了,推荐下这个实战教程:首先,我们在 SpringBoot 中配置两个数据源,其中第二个数据源是: 在开发环境下,没有必要配置主从数据库。只需要给数据库设置两个用户,一个具有读写权限,一个只有 SELECT 权限,这样就模拟了生产环境下对主从数据库的读写分离。在 SpringBoot 的配置代码中,我们初始化两个数据源: 第二步:编写 RoutingDataSource 然后,我们用 Spring 内置的 RoutingDataSource,把两个真实的数据源代

wadfdhsajd的博客 134

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Spring Boot 实现读写分离,还有谁不会?(1)

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!复制代码到此为止,我们已经成功实现了数据库的动态路由访问。手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友[外链图片转存中…(img-eeCDeFoK-1714655928255)]

2401_83916283的博客 776

boot lib分离 spring_手把手教你实现MySQL读写分离+故障转移,不信你学不会!

点击上方Coding这件小事,选择星标公众号重磅资讯、干货,第一时间送达今日推荐:详记一次MySQL千万级大表优化过程!前言上一篇发了手动搭建Redis集群和MySQL主从同步(非Docker)之后,很多同学对文中主从结构提到的读写分离感兴趣,本打算在双十一期间直接把读写分离分享给大家,奈何工作一直没停下,所以这周抽空把这些分享出来。关于MySQL的读写分离的实现,有两种方式,第...

weixin_32515143的博客 153

Spring Boot项目优雅实现读写分离

读写分离是指在数据库集群中,将数据库的读操作和写操作分别分配到不同的节点上。这样可以充分利用多台服务器的资源,提高系统的并发处理能力。一般来说,写操作相对读操作更为耗时,通过读写分离,可以有效减轻主库的负担。接下来,我们需要定义一个数据源上下文类,用于在当前线程中保存和获取当前使用的数据源类型。这个上下文类应该是线程安全的,因为它会在多个线程中被访问。为了在Service层标注读操作和写操作,我们可以定义两个自定义注解@Master和@Slave,并创建一个切面。

学IT,找陈寒 1万+
上一篇: 面试官:讲下Tomcat 组成与工作原理?
下一篇: 一个“不需要”写代码 的 mock & 代理 工具
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值