博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java程序员干货学习笔记—Spring结合MyBatis实现数据库读写分离
阅读量:6837 次
发布时间:2019-06-26

本文共 2498 字,大约阅读时间需要 8 分钟。

随着系统用户访问量的不断增加,数据库的频繁访问将成为我们系统的一大瓶颈之一。由于项目前期用户量不大,我们实现单一的数据库就能完成。但是后期单一的数据库根本无法支撑庞大的项目去访问数据库,那么如何解决这个问题呢?

实际的应用中,数据库都是读多写少(读取数据的频率高,更新数据的频率相对较少),而读取数据通常耗时比较长,占用数据库服务器的CPU较多,从而影响用户体验。我们通常的做法就是把查询从主库中抽取出来,采用多个从库,使用负载均衡,减轻每个从库的查询压力。

采用读写分离技术的目标:有效减轻Master库的压力,又可以把用户查询数据的请求分发到不同的Slave库,从而保证系统的健壮性。我们看下采用读写分离的背景。

我们在项目开发初期的时候就设计了一个简单的读写分离,现在我把demo分享给大家。

**采用技术Spring + mybatis

首先定义一个annotation**

import java.lang.annotation.ElementType;import java.lang.annotation.Target;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface DataSource { public String value();}

再定义一个HandleDataSource

public class HandleDataSource { public static final ThreadLocal holder = new ThreadLocal(); public static void putDataSource(String datasource) { holder.set(datasource); } public static String getDataSource() { return holder.get(); }}

定义一个切面

import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.reflect.MethodSignature;public class DataSourceAspect { public void pointCut() { }; public void before(JoinPoint point) { Object target = point.getTarget();// 拦截的实体类 String method = point.getSignature().getName();// 拦截的方法名称 Class[] classz = target.getClass().getInterfaces(); Class[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();// 拦截的方法参数类型 try { Method m = classz[0].getMethod(method, parameterTypes); if (m != null && m.isAnnotationPresent(DataSource.class)) { DataSource data = m.getAnnotation(DataSource.class); HandleDataSource.putDataSource(data.value()); } } catch (Exception e) { e.printStackTrace(); } }}

获取数据源

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class ChooseDataSource extends AbstractRoutingDataSource {  protected Object determineCurrentLookupKey() { return HandleDataSource.getDataSource(); } }

配置XMl

classpath*:mysql.propertiescom.mysql.jdbc.Driver${jdbc.url}${jdbc.user}${jdbc.password}SELECT 1 FROM DUAL32510010000true60com.mysql.jdbc.Driver${jdbc.url.read}${jdbc.user.read}${jdbc.password.read}SELECT 1 FROM DUAL32510010000true60

注解到service接口上面

源码地址:

数据库表就一张 根据mybatisxml大家自己建一下

另外这里还有一个瑕疵就是,当你使用注解事务的时候系统只能读取默认的数据源,这个问题主要是因为spring的事务和自定义的aop存在一个先后顺序的问题

Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字.

我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来定义order的顺序,order 的值越小,说明越先被执行。

转载地址:http://azhkl.baihongyu.com/

你可能感兴趣的文章
资源盗链困扰站长 安全狗内置盗链保护功能
查看>>
服务器安全股v4.0正式版发布 防火墙效能更强
查看>>
百度地图-解决新版百度定位失败问题
查看>>
Android Jetpack架构组件之 Room(使用、源码篇)
查看>>
Android WebView 支持H5图片上传<input type="file">
查看>>
PHP-FPM,Nginx,FastCGI 三者之间的关系
查看>>
这才是我想要的云盘工具
查看>>
iOS6.0下获取通讯录用户列表
查看>>
8个实用的响应式设计框架
查看>>
Objective-C中的内存管理
查看>>
Docker监控方案(TIG)的研究与实践之Grafana
查看>>
php 通过stomp协议连接ActiveMQ
查看>>
epoll 或者 kqueue 的原理是什么?
查看>>
JNDI数据库连接池的配置
查看>>
How Does Maven Work
查看>>
设计模式六大原则(6):开闭原则
查看>>
《Netty In Action》第二章:第一个Netty程序
查看>>
为什么不需要对独立的jre进行环境变量配置
查看>>
策略模式
查看>>
通过tomcat实现多域名配置
查看>>