文章编号:1007-757X(2021)02-0084-03
基于Spring Boot与MyBatis框架构建动态读写分离模型
张旭刚,张昕,高若寒
(国电南瑞科技股份有限公司信息系统集成分公司,江苏南京210000)
摘要:读写分离集群,是当前系统应对高并发、大吞吐量的一种方法,也是一种保障系统业务连续性的方法°现有实现读写分离集群的工具和方法,主要是一种静态部署,不适应资源横向扩展、动态伸缩的需求,不能够快速响应外部需求的变化°'用Spring Boot和MyBatis框架提供的技术优势,通过面向切面编程AOP,提供一种动态的低耦合的读写分离方法,数据源可以横向扩展,根据需求动态收缩,并对应用程序透明"
关键词:读写分离;Spring Boot;MyBatis;AOP
中图分类号:TP301文献标志码:A
A Way Realizing Separation of Reading and Writing Bad
高明的近义词是什么加油不熄火onSpringBootand MyBatis
ZHANG Xugang,ZHANG Xin,GAO Ruohan
(Information System Integration Branch!Guodian Nanrui Technology Co!Ltd!Nanjing210000!China) Abstract:The paration of reading from writing is a way in dealing with high concurrence and high throughput,also a way to enhance business continuity.The majority of main ways and tools provides a static deployment.The static deployment is lack ofscaled-outanddynamicscalability Itcannotberapidlysatisfied withouterrequirementchanges Thistopic!usingSpring Bootand MyBatisframework with AOP!providesadynamicandlow-coupling way Thedatasourcesarescaled-outanddy-namica l yscalable Anditistransparenttoapplicationprogram
Key words:paration of reading and writing;Spring Boot;MyBatis;AOP
0引言
读写分离集群,不仅提高了系统的健壮性和可靠性,以及系统的吞吐量和性能,保障了系统业务的连续性,而且也实现了资源的最大利用率&当前的实现方法主要通过静态方式配置,主要有中间件方式,如amoeba和mysql-proxy,分业务方式,对读写操作配置u O&静态方式缺乏灵活性,无法根据系统负载、用户需求等情况,实现资源的快速动态收缩,难以满足在不停机的条件下进行数据源切换,无法保证业务的连续性&
利用Spring Boot和MyBatis框架提供的优势,通过面向切面编程AOP,实现一种对应用透明、数据源可以动态收缩与切换的模型&
1Spring Boot架构
Spring Boot是由Pivotal团队提供,简化Spring开发的微服务框架&通过约定优于配置和起步依赖,简化复杂的依赖关系,大量减少XML配置文件,基本实现自动化位置,能够快速创建独立运行的Spring项目,并且集成了主流框架,如AOP和MyBatis&为实现动态读写分离模型,主要利用面向切面编程技术AOP、MyBtis映射.SpringBoot的类Ab-stractRoutingDataSource ThreadLocal程间的数据隔离(1)&
11Spring AOP
Spring AOP(Aspect-Oriented Programming,面向切面编程),是一种称为“横切”的技术,把与业务无关逻辑,但为业务模块共同调用的逻辑或功能封装起来,将其命名为"Aspect”,即方面,减少系统的重复代码,降低模块间的耦合度,便于后期的操作和维护&在论文中,主要使用AOP的前置通知,拦截MyBatis映射的SQL语句,动态选择数据源&
12MyBatis
Mybatis是一个支持普通SQL查询、存储过程和高级映射的优秀持久层框架,在持久层映射关系的开发
中,可以不用写实现类,能以代理方式自动生成实现代码,同时SQL语句写在映射XML文件中,实现了代码与SQL分离,降低耦合度&在映射XML文件中,通过id标识不同类型的SQL 语句,对查询、插入、删除和更新语句进行区分如口查询语句的id前缀为query,删除语句的id前缀为delete,通过甄别判SQL语选择的数据!的
分离&
风景散文作者简介:张旭冈IJC979-),男,硕士,助理工程师,研究方向:计算机应用技术。
张昕(1973-),男,硕士,高级工程师,研究方向:大型企业信息化规划&
高若寒(1989-),女,本科,助理工程师,研究方向:计算机应用技术。
13AbstractRoutingDataSource
Spring Boot提供了Abstract Routing Data Source根据用户定义的规则选择当前的数据源,可以在执行SQL操作
前!的数据源!由数据源的模型,它的方法determine Target Data Source#返回一个数据源,在该方法内部会调用抽象方法determine Current Lookup Key#决定使用哪个数据源‘lookup key键通常是通过Thread Local 定的上下文&
14ThreadLocal
Thread Local作用是提供线程内的局部变量,维护变量时Thread Local为每个使用该变量的线程提供独立的变量副本&
在面向切面编程AOP的前置通知中通过Thread Local 程的数据源类型,是读数据源还数据源&在返回数据源的时候,通过determine Current Lookup Key#调用Thread Local取得线程的数据源类型,从而为本次指定具体的数据源!还⑵。
2动态读写分离设计与实现
2.1总体架构
程序实现基于Spring Boot框架,通过Maven进行编译、测试和打包&Spring Boot基于Spring,减少了配置,简化了,使开发更高整体五层,客户端即程序,发起数据访问;第二DAO(数据访问对象),访问的sql语句配置在MyBatis的映射文件里,与程序的DAO映射关系,由MyBatis自动实现接口的文件,对数据行;,AOP,即面向切面编程DAO数据前,进行拦截,根据id进行动态选择数据源,如果语句则,如果是修改语句则y指向数据库,实现数据的,能有负、高、SQL、数据由等;第四层,创个数据源,每个数据源创个数据库资源池,分别指向写数据数据库;第五层,主备数据库间,通过binlog进行数据步,并进行故障切换⑷。
通过上面五层,与Spring Boot和MyBatis架构构建程
程明,无任何侵入,原程何改
简的数据5)。
构可以进行横向扩展,当性能无法满足需求时,添加数据源,添加数据库,进行负担,明,如图1所示&
2.2读写分离的实现
MySQL数据的 !的
类图如口图2所示&
由四个类!DynamicDataSource的根据数据源的值返回数据源;Data Source Context Holder圭寸装了Thread Local,取本次访问的数据源的值dynamic Data Source Aspect实现AOP的前置通知,拦截和解析SQL的id,根据id操作还操作,通过Data Source Context Holder动态设置数据源的值,然后Dynamic DataSource取的数据;MultiDataSourceCon-
ZE
持久层MyBatis
u MyBatis
映射文件
AOP
ThreadLocal.t(动态数据源)
生产库备库
图1总体结构图
图2读写分离的实现类图
fig配置多个数据源,在应用启动后有多个数据源可以选择& DynamicDataSource!取数据的数据!
如果操作,返回只读库数据源如口果删改则]写库。继承Abstract Routing Data Source并重写其中的方法determine Current Lookup Key(),该方法调用封装了ThreadLocal的DatabaContext Holder!取当前程的DatabaType。
Data Source Context Holder,用户设置数据库访问的数据源,具体设置通过切面拦截调用该类的方法t Data Source Type。该类拥有一个Thread Local的静态常量私有属性private static final Thread Local<String)CONTEXT. HOLDER=new Thread Local String)(),静态方法t DataSource Type#StringdataSource Key)getDataSource TypeO通过CONTEXT.HOLDER属性,用于标识数据源,每个数据的程的数据。
Dynamic Data Source Aspect用于定义要拦截的SQL操作,通过前置通知解析MyBatis中配置的id,根据id判断SQL操作操作还删!并DataSourceContext Holder的方当前线程的数据源类型。在进行数据源选择时.Dynamic Data Source返回设置的当前线程的数据源类型,当前线程准的数据源&它的主方如。
@Pointcut("execution(*com.sboot.dao.*. -(..)))
public void daoAspect(){
@Before#"daoAspect()”)
public void switchDataSource(JoinPoint point){
System,out.printin#"Begin to execute"+NameO);
Boolean isQueryMethod=isQueryMethod(point. NameO);
if(isQueryMethod){
DataSourceContextHolder.tDataSourceType("slave");
System,out.println("Slave DataSource begin to execute"+NameO);
-
-
Multi Data Source Config,是一个基于注解的配置,主要封装了写和读两个数据源,实现多数据源,需要取消Spring Boot的自动数据源配置,主要实现方法如下&
@BeanO"dynamicDataSource")
public DataSource dynamicDataSource(){
Map〈Object,Object>targetDataSources=new HashMap<Object,Object〉O;
targetDataSources put O"master"!masterData-Source O));
targetDataSources put O"slave"!slaveDataSource O));
散打规则DynamicDataSource dataSource=new Dynamic-DataSource O);
dataSourcetTargetDataSources O targetDataSourc-es);
dataSource tDefaultTargetDataSource O masterData-Source O));
returndataSource;
-
2.3配置多数据源
在application,yml中添加两个数据源:
pring:
datssource:
master://写数据源的配置
url"
jdbc:mysql://192.168.10.12:3306/masterdb?characterEncoding=utf8&uSSL=fal&rverTimezone= UTC rewriteBatchedStatements=true
urname:studba
password"stuDba1
sql.cj.jdbc.Driver slave://读数据源的配置
url
jdbc:mysql://192.168.10.13:3306/slavedb?characterEncoding=utf8&uSSL=fal&rverTimezone= UTC rewriteBatchedStatements=true
urname:studba
password stuDba1
腿部拉伸sql.cj.jdbc.Driver 然后在类DataSourceConfig中,利用注解的方式生成数据
©Primary
@Bean("masterDataSource")
@ConfigurationPropertiss(prefix="spring.datasource master")
public DataSource masterDataSource(){
ateO.buildO;
-
通过@ConfigurationPropertiss注解把在配置文件的配置自动的匹配配置数据源需要的值,生成数据源&备数据源的原理与上面一致&
2.4数据访问流程
数据访问流程如口图3所示&
DynamicDataSourceAspect MultiDynamicDataSource|数据库|
3、判断出是find开头的
sql语句,设置读数据源
DataSourceContextHol
1、取得映射的it技术支持
sql语句
findStudentB
yld
7、根据返回的
读数据源,访问
读数据库
i2、访问数据,被切面拦截'der.tDataSourceType
("slave")、
6、返回要访问
的数据源,本次
访问返回的是读
数据源
11
11
I1
4、在方法I
determineCurrentLook[
upKey()中返回数据源;
类型r eturn I
二DataSourceContextHol|
一-—DataSourceTypeO|
5、dctcrmi ncTargctDataS|
4一ource()根据上面|
dctcrm ncCurrcntT,ook]
upKey()B数返回的key■
值选择一个指定的数据源|
图3数据访问流程
(1)客户端访问数据库,正常流程走到DAO层?MyBa-tis进行映射接口,取得映射的sql语句,如findStudentById o
(2)取得sql语句访问数据库&
(3)通过©Before("daoAspectO")拦截访问,并检查是查询语句,设置数据源为读数据库o
判断出是fnd开头的sql语句,设置读数据源Data-SourceContextHolder.tDataSourceType("slave")&
(4)MultiDynamicDataSource
在方法determineCurrentLooYupKey()中返回数据源类型DataSourceTypeO&
(5)MultiDynamicDataSource的方法
determineTargetDataSource((根据上面determineCur-rentLooYupKey()函数返回的Yey值选择一个指定的数据源。
O)返回要访问的数据源,本次访问返回的是读数据源&
O)根据返回的读数据源,访问读数据库&
2.5应用验证
通过学生ID查询学生信息进行验证,查询操作到读库进行操作&查询学生信息的MyBatis SQL id是findStudent ById,*h t p://192.168.1.10:8080/stuInfo,
(98$
件,实现对Elevator Simulation 模型的控制过程,以此实现对 单梯控制方式的可靠性进行验证。利用TIAProtal 编写S7-
1200PLC 程序,采用TIA 来实现结构化编写的过程,用户程
序通过“块”的方式进行单独编写&
(2)进行仿真时根据高层写字楼中的实际客流信息进
行分析,选择其余交通模式来完成群控算法的仿真,利用客
流模块来自主获得不同模式的乘客数据流。采用层间交通
模式时可以降低高峰段的乘客人数,并且这两种方式都表现
为较低的平均乘梯时间。在各类交通模式下可按照实际条
件把权值赋予评价指标函数,从而达到各交通模式下都能获
得最佳电梯群性能&
参考文献
:1 * 毕晓亮,李伟,朱昌明,等.电梯群控系统多目标控
制策略[J *.上海交通大学学报,2004, 38 ( 8):
1366-1368
[2 * Utgoff P E , Connell M E . Real-time combinatorial
optimization for elevator group dispatching)J*. IEEE
Transactions on Systems , Man , and Cybernetiss — Part A : Systems and Humans , 2012, 42 (1): 130146.
:3 * 俞雯.基于多目标规划算法的智能电梯群控系统的
研究[D*.杭州:浙江工业大学,2008.
[4 * 闫冬梅,顾德英.电梯群控预约控制算法[J *.现代电
子技术,2004, 27(12):98-99.希望的
[5 * Yu L , Mabu S , Hirssawa K. Multicar elevator group
supervisory control system using genetic networY pro- gamming)〕*. IEEJ Transactions on Electrical and E
lectronic Engineering, 2010 , 6(S1) :S65-S73.
[6 * 王鹿军,吕征宇.基于LSSVM 的电梯交通模式的模
糊识别[J *.浙江大学学报(工学版),2012,46 (7):
1333-1338
1岁半宝宝食谱[7 * 张健,王笑竹.改进GA 优化BP 神经网络的电梯群
控策略[J *.陕西理工学院学报:自然科学版,2015, 31 (4) 36-39
:8 * 许玉格,罗飞,曹建忠.目的层预约的模糊神经网络
电梯群控策略[J *.华南理工大学学报(自然科学版),
2007 , 35 1 ) 13-18
[9 * Fernandez J , Cortss P , Munuzuri J , et al . Dynamic
fuzzylogicelevatorgroupcontrolsystem withrelative
waiting time consideration) J *. IEEE Transactions on IndustrialElectronics !2014 !61 (9 ):4912-4919
)10* 朱盐,刘跃敏.新型目的层预约的人工免疫电梯群控
策略)J *.电气传动,2012,42(9):5155.
)11* 于德亮,唐海燕,丁宝,等.基于粒子群优化模糊核
聚类的电梯群交通模式识别)J *.哈尔滨工业大学学
报,2012,44(10):8488.
)12 * AhmadF !FaYhirI !KhanSA !etal Petrinet-bad
modeling and controlofthe multi-elevator systems
)J * Neural Computing and Applications !2014!24 (7/8) :16011612.
(收稿日期:2020. 02. 25)
(上接第86页)
行查询,日志输出信息,如图4所示&
2020-06-12 20:37:21.452 INFO 13076 — [nio-B080-exec-l] o.s.web.rvlet.DispatcherServlet f'm Ming rliitiimiirrp" nrg 叩R 「hp|ibrtissyon.Configurationg48d20fl8b 由 to execute findStudentMdl [炯M 齣。2。20场6・12 20:37:22.192 INFO 13876|5丄眈 DBtBSourw begin to execute tindStudentByld | 諒齣
2020-06-12 20:37:21.622 INFO 13076 — [nio-8080-exec-l] con.zaxxer.hikari.HikariDataSource [ 卑—[nio-B080-exec-l] coi.zaxxer.hikari.HiksriDstaSource finish to executE find5tudentById
图4测试验证
日志打印出执行sql 语句findStudentById ,动态选择读
数据源 Slave DataSource 执行。
3
本文基于Spring Boot 和MyBatis 框架,实现了动态的 MySQL 读写分离模型,方法简单、便捷,对应用透明,低耦
合,无侵入性,安装和拆卸对现有程序无任何影响,没有额外
的成本。后续可加入多数据源,通过zooYeeper 进行状态监
控和管理,实现更智能和动态的数据库的横向扩展和收缩,
满足云计算场景需求&
参考文献
)1 *汪胜和,雷霆,黄太贵.多数据源调度报表系统的设 计与开发)J *.江苏电机工程,2008,27(1): 55-57.
) 2 *刘同.负载均衡技术在数据库集群系统中的应用与实
现[T*. 2009,2-3.
) 3 *龙中华.Spring Boot 实战派[M *.北京:电子工业出版
, 2020
) 4 *丁相民.多租户SaaS 应用中的MySQL 集群性能研究
)TP391 * 2015 ,43-61
) 5 *苏子权.基于MySQL Binlog 的数据增量同步系统的 设计与实现[TP311. 52* 2018. 07.
) 6 *
(美)克雷格•活斯(Craig Walls ). Spring Boot 实战
[M *.北京:人民邮电出版社,2016.
( 收稿 日 期 +20200702 )