我相信很多朋友都尝试写过读写分离插件,或者项目中用到过。首先读写分离的职责应该属于数据访问层而不是业务层,其次读写分离不应该侵入我们代码层中。因此在 service—dao—orm— 数据库驱动调用链中,要想插件不侵入我们的代码中,只能写在 orm 层和数据库驱动层,写在 orm 层就和具体 orm 框架耦合,写在数据库驱动层,就和具体数据库耦合。
在 orm 层实现读写分离还是在数据库驱动实现读写分离,主要看更换 orm 框架和数据库那个成本更高和实现难易程度。在此处不讨论那个更优,今天介绍的读写分离插件是基于 mybatis 框架实现的一写多读。基于 springboot 配置,因此在现有项目中集成非常方便,下载源码打成 jar 包引入到项目中,在 springboot 的配置文件中添加如下配置即可开启读写分离。
此插件一共做了三件事:数据源代理,数据源路由,分布式事务。
此插件对现有代码零侵入,要达到零侵入得益于代理模式。
首先数据源代理,读写分离在一个业务里面至少有两个数据源,读数据源,写数据源,但是在一个事务里面所有 sql 执行都是在同一个数据库连接下操作,因此需要实现 DataSorce 接口代理读写数据源: DataSourceProxy。DataSourceProxy 类写操作时,返回写数据源的 Connection,读操作时,返回读数据源的 Connection。然而读写操作,要在真正执行数据库操作时才能确定,然而在真正在执行 sql 语句之前,就已经获取 Connection 操作,因此获取 Connection 操作时,应该返回一个代理的Connection,再实际执行 sql 语句时根据当前环境获取真实的 Connetion。
因此 DataSourceProxy 返回的 Connection 是一个代理类, 依赖一个 DataSourceRout 接口,在未执行sql语句之前都是由 Connection 代理类完成操作。再执行 sql 语句时,由 DataSourceRout 接口返回具体 Connection 执行 sql 语句,DataSourceRout 接口只有一个 getTargetDataSource 方法,由具体实现类根据当前环境确定目标数据源,可能是读写数据源,也可能是分表后的具体目标数据源。
DataSourceRout 接口目前有两个实现类,AbstractRWDataSourceRout 实现读写分离,UserDataSourceRout 实现根据不同的用户路由到不同的数据库组上。UserDataSourceRout 这个类依赖一组 AbstractRWDataSourceRout,实现读写分离。
具体类结构如下:
将 DataSourceProxy 注入到 org.mybatis.spring.SqlSessionTemplate 里面。Mybatis 便实现读写分离。此时对现有代码完全透明。当然也可以注入到 hibernate 框架中,只不过需要自己实现 DataSourceRout 接口,DataSourceRout 接口的实现类AbstractRWDataSourceRout 是基于 mybatis 的。
通过 org.mybatis.spring.SqlSessionTemplate 这个类的源码查询,org.apache.ibatis.mapping.MappedStatement 这个类里面的 org.apache.ibatis.mapping.SqlCommandType 这个域定义了 mybatis 执行 sql 语句类型,可以通过这个类确定当前操作是读操作还是写操作。
写一个 mybatis 的插件,在 sql 执行过程中通 SqlCommandType 这个类确定当前上下文是读操作还是写操作。把读写标记存入上下文中,在 AbstractRWDataSourceRout 这个类中拿取上下文中的读写标记返回对应的数据源,为了事务简单,保证当前上下文最多只有一个写连接和一个读连接,检查当前上下文是否有对应的数据库连接,如果没有相应的连接,获取连接,保存在当前上下文中,方便下次 sql 语句执行和事务执行。
数据源由原来单一数据源变成了一个读数据源和一个写数据源,事务也就变成了两个事务。Mybatis 集成 spring 后,mybatis 的事务交由 spring 管理,具体实现类是 org.mybatis.spring.transaction.SpringManagedTransaction,为了和 myabtis-spring 无缝集成,采用代理模式,RWManagedTransaction 继承 SpringManagedTransaction,把事务分别委托给读写事务,整个线程只有一个读事务和一个写事务,读事务比较弱。因此分布式事务采用 Best Efforts 1PC 模式。
public void commit() throws SQLException {
Map<String, Connection> connectionMap = ConnectionHold.CONNECTION_CONTEXT.get();
Connection writeCon = connectionMap.remove(ConnectionHold.WRITE);
if(writeCon != null){
writeCon.commit();
}
Connection readCon = connectionMap.remove(ConnectionHold.READ);
if(readCon != null){
try {
readCon.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}
第一个事务成功后,第二个事务有可能因为网络原因或者服务器宕机,不能执行成功,这个网络通讯的危险期虽然概率很小,但是也是个不可靠因素之一。由于整个会话中,只有一个写数据连接和一个读数据连接,读的事务性比较弱,只要写事务成功了,读事务失败影响不大,当然也可以不考虑读事务。因此先处理写事务,再处理读事务。
作为一个初级程序员,想要扩展现有的开源框架,其实不是那么困难,只要实现相应的接口,参考现有实现类实现接口,如果现有的实现类太复杂看不懂逻辑,其实也很好实现接口,就是把自己的实现委托给现有实现类,自己在委托前后做一些自己的业务逻辑。
引用:http://mp.weixin.qq.com/s/O8DfUjIw18WehILOWsR8ug
此插件代码托管在
https://github.com/chenlei2/spring-boot-mybatis-rw
欢迎大家 fork。
相关推荐
Mybatis读写分离,支持n多的从库,简单的负载均衡。数据库是mysql,采用druid连接池。 读写分离采用插件的形式实现的,优点是不需要写源注解,不需要写分开的Mapper.xml。 如果只有主库的话,那么会创建两个地址相同...
通过以上步骤,我们成功地在Spring Boot项目中实现了基于AOP的读写分离。这种方式不需要额外的插件,代码简洁,易于理解和维护。在高并发场景下,这种方案能够有效地减轻数据库压力,提高系统响应速度,是优化数据库...
本文将深入探讨如何使用SpringMVC和MyBatis框架来实现读写分离,尤其是“一写多读”的模式。我们将讨论以下几个方面: 1. **读写分离的概念**:读写分离是数据库架构设计中的一个关键策略,它将数据库分为主库和多...
### MyBatis 实现读写分离 #### 一、读写分离的概念与优势 在数据库设计与应用领域,“读写分离”是一种常见的架构模式,它通过将数据读取操作和写入操作分配到不同的数据库服务器上来提高系统的整体性能。这种...
基于mybatis,springboot开箱即用的读写分离插件 此插件由以下2部分组成 datasource:读写数据源的代理,支持一写多读,用户只需实现 ...
spring-boot-mybatis-rw基于mybatis,springboot开箱即用的读写分离插件Quick StartMaven dependency<dependency> <groupId>...介绍此插件由以下2部分组成datasource:读写数据源的代理,支持一写多读,用户只需实现 ...
【标题】"基于mybatis,springboot开箱即用的读写分离插件.zip" 提供了一个集成mybatis和springboot的解决方案,旨在简化数据库读写分离的实现过程。这个插件使得开发者能够快速地在自己的应用中部署读写分离功能,...
总结来说,基于MyBatis的数据库拆分和读写分离实现,涉及到对MyBatis框架的深入理解和扩展,包括对SqlSessionTemplate的改造、数据库拆分策略的设计(如垂直拆分和水平拆分的一致性哈希)、以及读写分离的路由机制。...
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,...
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。... 【项目质量】:所有源码都经过严格测试,可以...
【Spring+MyBatis实现数据读写分离】 数据读写分离是数据库优化的重要策略,它将高并发的读操作和低频的写操作分配到不同的数据源上,以提高系统的性能和可用性。Spring和MyBatis框架结合,可以通过AOP(面向切面...
项目使用了最新的Springboot技术,以及mybatis作为jdbc框架,pageHepler作为分页插件,实现了读写分离和自定义注解分页以及自定义注解读写分离。同时实现了默认的读写分离机制和默认的分页机制。
由SpringMVC+MyBatis为主要框架,mysql8.0配置主从复制实现读写分离,主机丛机分别为腾讯云的服务器,而项目部署在阿里云上。前端主要由bootstrap完成,背景用particles.js插件。数据库交互查询用到pagehelper分页。...
本项目“基于Springboot结合aop实现读写分离实例工程系统”旨在提供一个实际的应用示例,帮助开发者理解和实施这一技术。以下是关于这个项目的详细知识点介绍: 1. **Spring Boot**: Spring Boot是Spring框架的一个...
工具性方面,Mybatis-Sharding通常与其他数据库中间件配合使用,如ShardingSphere、MyCat等,这些中间件提供了更全面的数据库分片解决方案,包括路由、分片、读写分离、分布式事务等功能。Mybatis-Sharding作为轻量...
此工程是基于aop实现的读写分离 mybatis-aop插件 此工程是基于mybatis的拦截器拦截器实现的解读分离 Mybatis交易 此工程是基于DataSourceTransactionManager的事务isReadOnly()实现的读写分离,对于未开启事务的,...
缓存策略可配置,支持读写分离和清空操作。 9. **插件支持** - MyBatis 允许开发者自定义插件,拦截特定的方法调用,如:PageHelper 分页插件、Druid 监控插件等,方便扩展功能。 10. **事务管理** - MyBatis ...
读写分离 springmvc+mybatis+mybatis插件+ spring + abstractDatasourceRouting
4. **ShardingSphere与MyBatis集成**:ShardingSphere提供了MyBatis的插件,使得MyBatis可以直接使用ShardingSphere的功能,如数据分片、读写分离等。开发者只需要在MyBatis的配置中添加ShardingSphere的相关规则...