一种一主多从的数据源调度、管理装置的制作方法

文档序号:32128094发布日期:2022-11-09 08:50阅读:45来源:国知局
一种一主多从的数据源调度、管理装置的制作方法

1.本发明涉及互联网访问数据调度的技术领域,具体的说,尤其是一种一主多从的数据源调度、管理装置。


背景技术:

2.当一个互联网企业用户越来越多时,访问量会越来越大。并发处理业务请求的能力就会显得越来越重要。其中的一个关键点就是数据库。不管业务代码如何高效,数据库的处理能力是有限的。因此,在业务量达到一定级别后,对数据库里的数据进行读写分离的规划势在必行。一般是将在使用的数据库作为主库,然后同步一个或多个从库。然后将一部分的读写分流到从数据库,以减轻主库的压力。这就要求代码里的数据源能支持连接多个数据库;然而即使用了主从库的架构,将读写分流,在遇到大量有慢查询的请求时,依然会遇web应用线程耗尽的问题,这是因为当大量有慢查询的请求时,数据源的可用连接被用尽,拿不到连接的请求只能阻塞当前线程直到拿到可用连接为止。这样当拿不到连接的请求越多,则被阻塞的线程也越多,一起到所有可用线程耗尽,最终将导致web应用无法接收后续的请求,造成线上生产事故。


技术实现要素:

3.为了克服现有技术存在的缺陷,本发明提供一种一主多从的数据源调度、管理装置,旨在解决上述背景技术中阻塞的线程也越多,导致所有可用线程耗尽而最终导致web应用无法接收后续的请求的问题;本发明解决其技术问题所采用的技术方案是:一种一主多从的数据源调度、管理装置,包括代理数据源、dao层切面拦截器和数据源上下文,包括以下步骤:s1、获取数据源标识,查看是否有spring事务,有则挂起该事务;s2、dao层切面拦截器获取dao层接口上的标签的“数据源标识”,将“数据源标识”记录到数据源上下文,并调用dao层和调用代理数据源;s3、代理数据源由数据源上下文中获取“数据源标识”,所述代理数据源包括数据源调度器、主数据源和从数据源key-value容器,所述数据源调度器用于从数据源上下文中取出“数据源标识”,所述主数据源为直接使用的数据源,所述从数据源key-value容器内储存有代理从数据源;s4、数据源上下文返回给代理数据源“数据源标识”;s5、代理数据源根据“数据源标识”选择数据源并调用数据库;s6、数据库将调用数据源反馈到代理数据源、dao层以及dao层切面拦截器;s7、查看是否有挂起的spring事务,有则恢复该事务,将数据源标识由数据源上下文中移除,然后返回结果给service层;进一步的,所述dao层切面拦截器的处理方法包括:所述dao层切面拦截器从dao层
接口中,尝试获取“数据源标识”,若获取不到,则直接调用dao层接口;若获取得到,dao层切面拦截器会调起数据源前置处理器,该处理器会先将“数据源标识”记录到数据源上下文中,然后查看是否有spring事务,有则挂起该事务,然后调用dao层,dao层返回调用结果后,查看是否有挂起的spring事务,有则恢复该事务;具体地,所述dao层切面拦截器的配置如下:《aop:config》
ꢀꢀꢀꢀ
《aop:aspect ref="microservicedaointerceptor"》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《aop:pointcut expression="execution(* cn.qtone.zf.*.*.dao..*mapper.*(..))" id="daointerceptor"/》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《aop:around method="around" pointcut-ref="daointerceptor"/》
ꢀꢀꢀꢀ
《/aop:aspect》《/aop:config》其中,“* cn.qtone.zf.*.*.dao..*mapper.*(..)
ꢀ”
为需要拦截的接口;更具体地,所述dao层切面拦截器的处理方法还包括以下步骤:当在service层开启spring所管理的事务时,spring事务管理器提前由数据源中获取链接,当在service层的某一带事务方法中,顺序调用接口 functoina、functoinb、functoinc时,则在代理数据源表现为获取主数据源链接master,然后执行functoina的sql,然后保存链接master,获取代理从数据源链接slave,用链接slave执行functoinb的sql,然后释放链接slave,用链接master执行functoinc的sql,释放链接master;进一步的,所述代理数据源包括以下切换配置方法:a、根据name、type、isprotected、config切换代理从数据源配置;b、根据name查看从数据源key-value容器中是否有对应的代理从数据源,若否,则将任务抛异常并结束,若是,则进入下一步;c、新建一个代理从数据源然后将type、isprotected、config传并启动;若不能启动,则将任务抛异常并结束,若正常启动,则进入下一步;d、将name对应的原数据源取出并保存,将新数据源放入;e、查看原数据链接是否有活跃连接,若无,则关闭原数据源并结束,若有,则循环查看原数据链接是否有活跃连接,直至没有活跃连接后关闭原数据源并结束;进一步的,所述数据源上下文内设置有一jdk提供的threadlocal对象,该threadlocal对象可以将变量保存在当前执行的线程当中;具体地,所述数据源上下文包括以下提供方法:a、将数据源标识记录到threadlocal对象中:
ꢀꢀꢀꢀ
public static void setslavedatasource(string slavedatasource) {..};b、将从threadlocal对象获取数据源标识:
ꢀꢀꢀꢀ
public static string getslavedatasource() {..};c、将数据源标识从threadlocal对象移除:
ꢀꢀꢀꢀ
public static string removeslavedatasource() {..};本发明的有益效果是:
1、数据源规划为主/从数据源,主数据源连接主库,主数据源只有一个。从数据源连接从库,从库可以有多个;2、对于代理从数据源,支持实时切换数据库连接,不需要停机;3、对于代理从数据源,可开启保护模式:当从数据源可使用连接数耗尽时,后来sql请求作立即返回异常处理,这样作的好处是,当慢查询的请求过多时,不会因为等待可用连接而耗尽系统的可用线程,从而造成整个应用堵死。
附图说明
4.图1为本发明的数据源调度、管理装置的流程框图;图2为为本发明的数据源调度、管理装置的结构框图;图3为dao层和dao层切面拦截器的流程框图;图4为dao层和dao层切面拦截器的处理流程框图;图5为代理数据源的切换配置方法的处理流程框图。
具体实施方式
5.下面结合附图对本发明的具体实施方式作进一步说明。在此需要说明的是,对于这些实施方式的说明用于帮助理解本发明,但并不构成对本发明的限定。此外,下面所描述的本发明各个实施方式中所涉及的技术特征只要彼此之间未构成冲突就可以相互组合;结合图1和图2所示的一种一主多从的数据源调度、管理装置,包括代理数据源、dao层切面拦截器和数据源上下文,包括以下步骤:s1、获取数据源标识,查看是否有spring事务,有则挂起该事务;s2、dao层切面拦截器获取dao层接口上的标签的“数据源标识”,将“数据源标识”记录到数据源上下文,并调用dao层和调用代理数据源;其中,dao层的配置如下:public interface inserttestmapper extends mapper《inserttest》{list《inserttest》seletbyidmaster(string id);@slavedatasource(name=”slave1”)list《inserttest》seletbyidfromslave(string id)};而dao层切面拦截器的配置如下:《aop:config》
ꢀꢀꢀꢀ
《aop:aspect ref="microservicedaointerceptor"》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《aop:pointcut expression="execution(* cn.qtone.zf.*.*.dao..*mapper.*(..))" id="daointerceptor"/》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《aop:around method="around" pointcut-ref="daointerceptor"/》
ꢀꢀꢀꢀ
《/aop:aspect》《/aop:config》;其中“* cn.qtone.zf.*.*.dao..*mapper.*(..)
ꢀ”
为需要拦截的接口,"microservicedaointerceptor"为dao层切面拦截器;如图3和图4所示,本实施例的dao层切面拦截器的处理方法包括:dao层切面拦截
器从dao层的接口中,尝试获取@slavedatasource标签,如果获取不到,则直接调用dao层的接口,若获取得到,dao层切面拦截器会调起数据源前置处理器,该处理器会先将“数据源标识”记录到数据源上下文中,然后查看是否有spring事务,有则挂起该事务,然后调用dao层,dao层返回调用结果后,查看是否有挂起的spring事务,有则恢复该事务;当在service层开启spring所管理的事务时,spring事务管理器提前由数据源中获取链接,当在service层的某一带事务方法中,顺序调用接口 functoina、functoinb、functoinc时,则在代理数据源表现为获取主数据源链接master,然后执行functoina的sql,然后保存链接master,获取代理从数据源链接slave,用链接slave执行functoinb的sql,然后释放链接slave,用链接master执行functoinc的sql,释放链接master;由此可看到,执行该servicre的整个方法中,master的连接始终存在,从而保证了主数据源的事务有效性;s3、代理数据源由数据源上下文中获取“数据源标识”,所述代理数据源包括数据源调度器、主数据源和从数据源key-value容器,所述数据源调度器用于从数据源上下文中取出“数据源标识”,所述主数据源为直接使用的数据源,所述从数据源key-value容器内储存有代理从数据源;其中,代理数据源的整体配置如下:《bean id="datasource" class="cn.qtone.zf.service.datasource.multidatasource"》
ꢀꢀꢀꢀ
《property name="master" ref="master"/》
ꢀꢀꢀꢀ
《property name="slaves"》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《map key-type="java.lang.string"》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《entry key="slave1" value-ref="slavehello"/》
ꢀꢀꢀꢀꢀꢀꢀꢀꢀꢀ
《/map》
ꢀꢀꢀꢀ
《/property》《/bean》《bean id="slavehello" class="cn.qtone.zf.service.datasource.slavesource"》
ꢀꢀꢀꢀ
《property name="type" value="hikari"/》
ꢀꢀꢀꢀ
《property name="isprotected" value="true"/》
ꢀꢀꢀ
《property name="config" value=《![cdata[{"driver":"xxx","password":"123","maxidle":"100","minidle":"10","url":"jdbc:mysql://127.0.0.1:3306/hello","username":"xft"}]]》/》《/bean》;配置中的id=“datasource”为代理数据源配置,id=“slavehello”为代理数据源datasource中的其中一个代理从数据源的配置,对配置说明如下:1、对于代理数据源需要配置主数据源“master”和代理从数据源key-value容器“slaves”,容器中每一个key值就是该代理从数据源的标识,比如上面例子中的“slave1”;2、对于代理从数据源则需要配置该数据源的类型、是否开启保护模式和该数据源的配置,数据源的配置为json格式;当请求到代理数据源时,会调用数据源调度器从数据源上下文中取出数据源标
识,如果取出为空则取主数据源;如取出不为空,则从代理从数据源key-value容器中取出代理从数据源;在获取代理从数据源后,会先判断该代理是否可以被调用,如果不可被调用则抛异常,如果可以被调用则再调用代理从数据源获取数据源;最终代理数据源将取到的数据源返回给上层使用代理从数据源结构和说明如下,其中initializingbean为spring某个生命周期的接口:public class slavedatasource implements initializingbean{
ꢀꢀꢀꢀ
private string type; //数据源类型
ꢀꢀꢀꢀ
private boolean isprotected;//是否是保护模式
ꢀꢀꢀꢀ
private string config;//数据源配置
ꢀꢀꢀꢀ
private datasource datasource;// 数据源
ꢀꢀꢀꢀ
private int maximumpoolsize;//数据源最大连接数
ꢀꢀꢀꢀ
//设置数据源类型
ꢀꢀꢀꢀ
public void settype(string type) {..}
ꢀꢀꢀꢀ
//设置是否是保护模式
ꢀꢀꢀꢀ
public void setprotected(boolean isprotected){..}
ꢀꢀꢀꢀ
//设置数据源配置public void setconfig(string config) {..}//根据type、config初始化datasource和maximumpoolsize并启动数据源,如果启动不成功则抛异常
ꢀꢀꢀꢀ
public void afterpropertiesset() throws exception {..}
ꢀꢀꢀꢀ
//获取数据源
ꢀꢀꢀꢀ
public datasource getdatasource() {..}
ꢀꢀꢀꢀ
//看是否可获取连接,先看是否是保护模式,如果不是则返回true,如果是则调数据源获取活跃连接数并和maximumpoolsize作对比,小于则返回true否则返回false
ꢀꢀꢀꢀ
public boolean hasavailableconnection() {..}};代理数据源除了根据数据源标识获取数据源外,还提供了代理从数据源切换配置方法;该方法如下:public void restartslave(string name,string type,boolean isprotected,string config);该方法第一个参数是代理从数据源key-value容器中目标容器的key值,后三个参数为代理从数据源的所需参数;如图5所示,本实施例的所述代理数据源包括以下切换配置方法:a、根据name、type、isprotected、config切换代理从数据源配置;b、根据name查看从数据源key-value容器中是否有对应的代理从数据源,若否,则将任务抛异常并结束,若是,则进入下一步;c、新建一个代理从数据源然后将type、isprotected、config传并启动;若不能启动,则将任务抛异常并结束,若正常启动,则进入下一步;
d、将name对应的原数据源取出并保存,将新数据源放入;e、查看原数据链接是否有活跃连接,若无,则关闭原数据源并结束,若有,则循环查看原数据链接是否有活跃连接,直至没有活跃连接后关闭原数据源并结束;由此可知,本发明是以新的配置启动新的数据源来实现新配置的生效,而旧数据源会后续流程关闭;s4、数据源上下文返回给代理数据源“数据源标识”;s5、代理数据源根据“数据源标识”选择数据源并调用数据库;s6、数据库将调用数据源反馈到代理数据源、dao层以及dao层切面拦截器;s7、查看是否有挂起的spring事务,有则恢复该事务,将数据源标识由数据源上下文中移除,然后返回结果给service层;本实施例的数据源上下文内设置有一jdk提供的threadlocal对象,该threadlocal对象可以将变量保存在当前执行的线程当中;其中,数据源上下文包括以下提供方法:a、将数据源标识记录到threadlocal对象中:
ꢀꢀꢀꢀ
public static void setslavedatasource(string slavedatasource) {..};b、将从threadlocal对象获取数据源标识:
ꢀꢀꢀꢀ
public static string getslavedatasource() {..};c、将数据源标识从threadlocal对象移除:
ꢀꢀꢀꢀ
public static string removeslavedatasource() {..};本发明的数据源规划为主/从数据源,主数据源连接主库,主数据源只有一个,从数据源连接从库,从库可以有多个;对于代理从数据源,支持实时切换数据库连接,不需要停机;对于代理从数据源,可开启保护模式:当从数据源可使用连接数耗尽时,后来sql请求作立即返回异常处理。这样作的好处是,当慢查询的请求过多时,不会因为等待可用连接而耗尽系统的可用线程,从而造成整个应用堵死;以上结合附图对本发明的实施方式作了详细说明,但本发明不限于所描述的实施方式。对于本领域的技术人员而言,在不脱离本发明原理和精神的情况下,对这些实施方式进行多种变化、修改、替换和变型,仍落入本发明的保护范围内。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1