`

基于AbstractDataSource实现主从数据库切换

阅读更多
基于AbstractDataSource实现主从数据库切换


项目背景:

1.DBA通知某一个SQL运行严重超时,告知将读取源头从主库改为从库,减轻主库压力

2.数据库配置上有两个数据源,主从两个配置;
主库:允许读写;从库:只允许读;
主从库数据同步

3.功能已存在,分析运行流程如下

项目流程:

一、使用自定义注释

    @RequestMapping(value="/getBrandHisProjectsForM",method=RequestMethod.POST)
    @ResponseBody
    @DbReadonly
    public Response<BrandHisProjectRes> getBrandHisProjectsForM(@RequestBody BrandHisProjectReq brandHisProjectReq){
    	return getBrandHisProjects(brandHisProjectReq.getBrandId(), brandHisProjectReq.getCpage(), brandHisProjectReq.getPageSize(), ConstantAction.PLATFORM.M);
    }



1.在Service层或调用Service层方法的上一层方法上添加 @DbReadonly 注释

2.通过此注释标识下面的读SQL的数据源将连接从数据库

二、自定义注释

// 程序运行时起作用
@Retention(RetentionPolicy.RUNTIME)
// 使用位置放在方法定义的上面
@Target(ElementType.METHOD)
// 文档注释
@Documented
public @interface DbReadonly {
        // 默认值:readonly ,后续的拦截器、数据同步类需要获取此时定义的数据源	
	String value() default "readonly";	
}


三、Spring 切面注入

@Aspect
@Component
public class DataSourceAspect {
	
        // 对应的切面位置
	@Pointcut("@annotation(com.xxx.lang.annotation.DbReadonly)")
	public void dbAspect() {
	}
	
        // 在方法执行前将数据源切换到从库
        @Before("dbAspect()")    
        public void before(JoinPoint joinPoint) {
		DbContextHolder.setReadonly();
        }

        // 在方法执行后将数据源切换到主库
	@After("dbAspect()")
	public void after(JoinPoint joinPoint) {
		DbContextHolder.setMaster();
	}
}





四、读取当前的数据源配置

public class DbContextHolder {
	
    /**
     * 线程级参数
     */
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    
    /**
     * 动态数据库信息设定
     * 
     * @param dbType
     */
    public static void setDbType(String dbType) {
        contextHolder.set(dbType);
    }
    
    /**
     * 动态数据库信息取得
     * 
     * @return
     */
    public static String getDbType() {
        return ((String) contextHolder.get());
    }
    
    /**
     * 动态数据库信息清空
     * 
     * @return
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
    
    /**
     * 设定主库
     */
	public static void setMaster() {
		clearDbType();
	}
	
	/**
     * 设定主库
     */
	public static void setReadonly() {
		setDbType("readonly");
	}
    
}



五、Spring-mybatis.xml 配置动态获取数据源

    <bean id="dynDataSource" class="com.xxx.db.DynamicDataSource">
        <!-- DynamicDataSource 继承 AbstractDataSource ,此处为targetDataSources赋值  --> 
        <property name="targetDataSources">
        <map key-type="java.lang.String">
        <!-- 告知目前已有的数据源及对应的key -->
            <entry value-ref="dataSource" key="master"></entry>
            <entry value-ref="readonlyDataSource" key="readonly"></entry>
        </map>
        </property>
        <property name="defaultTargetDataSource" ref="dataSource" />
    </bean>





六、动态读取当前数据源配置


public class DynamicDataSource extends AbstractRoutingDataSource {
	
    /**
     * 分配动态数据库
     */
    @Override
    protected Object determineCurrentLookupKey() {
        String obj = DbContextHolder.getDbType();
        if (obj == null || obj.equalsIgnoreCase("default")) {
            return "master";
        } else {
            return obj;
        }
    }
    
}




七、数据库选择拦截器



// 默认数据源为主库,避免出现空值
public class DbSelectFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        DbContextHolder.setDbType("defalut");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}



八、Spring-mybatis.xml 加载

	<!-- sqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
        <!-- 配置数据源,为动态获取,动态获取中配置两个设置好的数据源配置 -->
		p:dataSource-ref="dynDataSource" p:typeAliasesPackage="com.xxx.core.model,"
		p:mapperLocations="classpath*:com/**/mapping/*Mapper.xml">
		<property name="configLocation" value="classpath:conf/mybatis-config.xml" /> 
		</bean>




项目运行:

1.每一个请求都经过拦截器处理,默认处理成读取主库

2.当在service 中的  method上有使用 @DbReadonly  注释时,Spring 面向切面的标识

在方法执行前将  数据源切换到从库,在方法执行后切换到主库


项目备注:

1.不可多次套用此标签,即在调用 Service 处(对外提供的调用接口,用于对于某一具体需求进行处理,同时调用多个Service 接口)使用,同时在Service 中使用,会导致切换失败

分析:

A 调用 B

A 上使用了此标签,切换到 从库

B 上使用了此标签,切换到 从库,B 方法执行完毕,切换到主库

A 接收B 方法的返回值

A 中其他方法,运行,若此时其他方法上未加此注释,则数据源此时已被切换到了主库上

A 调用完毕,切换到主库
分享到:
评论

相关推荐

    SQL Server 2008 R2 主从数据库同步

    SQL Server 2008 R2 主从数据库同步是高可用性技术之一,通过配置数据库属性和事务日志传送,实现主从数据库之间的数据同步。本文将详细介绍 SQL Server 2008 R2 主从数据库同步的配置步骤和实现原理。 基本原理 ...

    主从数据库的配置和使用案例(可以直接运行)

    在高并发、大数据量的场景下,为了提高系统的稳定性和性能,通常会采用主从数据库架构来实现读写分离。本案例中,我们将详细探讨如何配置和使用主从数据库,以及如何在实际环境中运行。 **一、主从数据库架构** ...

    springboot2.0+mybatis主从数据库双数据源。

    本项目基于SpringBoot 2.0框架和MyBatis持久层技术,实现了主从数据库双数据源的配置,确保在高并发环境下既能保证数据的一致性,又能提升读取效率。 SpringBoot 2.0是Spring框架的一个轻量级版本,它简化了Spring...

    mysql主从数据库配置

    mysql主从数据库配置详细步骤,自己实验后得出的步骤文档

    linux下主从数据库的安装详细操作步骤

    Linux 下主从数据库的安装详细操作步骤 本文档将详细描述 Linux 环境下 MySQL 主从数据库的安装操作步骤。通过本文档,读者可以了解如何在 Linux 环境下安装配置 MySQL 主从数据库。 一、主从数据库配置 在 Linux...

    mysql主从数据库的优势

    下面我们将深入探讨MySQL主从数据库配置的两大核心优势——实现服务器负载均衡和通过复制实现数据的异地备份。 **一、实现服务器负载均衡** 在MySQL主从架构中,负载均衡是通过在主服务器和从服务器之间分配工作...

    springboot 配置主从数据库涉及的各类细节 对初次解除主从数据库的开发

    在本篇文章中,我们将深入探讨如何在Spring Boot项目中配置并实现主从数据库,以便为初次接触该领域的开发者提供详尽的指导。主从数据库配置是数据库管理中的一个高级主题,它通过设置一个主数据库(Master)和一个...

    linux,Centos主从数据库

    在IT领域,数据库主从复制是一种常见的高可用性和负载均衡策略,特别是在Linux系统,如CentOS上。这种配置允许一个数据库(主库)处理写入操作,而其他数据库(从库)则同步主库的数据,确保数据的一致性和冗余。...

    ORACLE主从搭建和切换操作手册

    ### ORACLE主从搭建与切换操作手册:知识点详解 #### 一、ORACLE高可用方案概览 在ORACLE数据库的高可用性解决方案中,主要包括RAC(Real Application Clusters)、Data Guard以及GoldenGate三种技术手段。每种...

    SQLServer2008R2主从数据库同步

    在实现SQL Server 2008 R2的主从数据库同步之前,首先需要确保主从服务器的基本环境配置一致,并创建必要的用户及权限。 **主数据库服务器:** - 操作系统:Windows Server 2008 R2 - 数据库版本:SQL Server 2008 ...

    SQL Serve数据库发布和订阅(主从数据库同步)

    ### SQL Server 数据库发布和订阅(主从数据库同步) #### 概述 SQL Server 的发布与订阅机制是一种实现...通过以上步骤,您可以成功地在SQL Server 2008 R2中设置和配置数据库的发布与订阅,实现数据的主从同步。

    基于docker部署主从MYSQL数据库.pdf

    本资源摘要信息主要介绍了基于docker部署主从MYSQL数据库的技术实现和使用场景,以及其在实际应用中的优点和缺陷。 首先,作者介绍了当前时代的科学技术和网络的发展,导致人们对未知的信息产生许多的兴趣,网站...

    MYSQL主从数据库介绍__主库__从库.docx

    MYSQL主从数据库介绍__主库__从库.docxMYSQL主从数据库介绍__主库__从库.docxMYSQL主从数据库介绍__主库__从库.docxMYSQL主从数据库介绍__主库__从库.docxMYSQL主从数据库介绍__主库__从库.docxMYSQL主从数据库介绍_...

    ANDROID9.0 蓝牙主从切换方案.rar

    3. **一键切换机制**:该方案的核心在于提供一种用户友好的界面,允许用户通过简单的操作(如点击按钮)实现蓝牙主从角色的切换。这通常涉及到监听用户输入事件,然后调用相应的API来改变设备的角色。例如,通过`...

    sqlserver2012主从数据库配置

    在SQL Server 2012中,主从数据库配置是一种常见的高可用性和灾难恢复解决方案,它通常被称为数据库镜像或复制。在这个配置中,一个数据库(主库)会在另一个数据库(从库)上实时或近实时地同步数据,确保即使主...

    mysql 主从数据库服务器的设置.doc

    MySQL 主从数据库服务器设置指南 MySQL 主从数据库服务器(Replication)的设置是指将一个 MySQL 服务器的数据实时同步到另一个 MySQL 服务器上,這種方式可以提高数据库的可用性和读取性能。下面是 MySQL 主从...

Global site tag (gtag.js) - Google Analytics