麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
657
2023-05-27
一个支持监听SQL、感知事务状态、回溯数据源的动态数据源框架
项目更名
在easymulti-datasource-spring-boot-starter之后笔者又开发了hotkit-r2dbc,这两个项目都支持动态数据源切换,前者支持mybatis框架,后者支持响应式编程spring-data-r2dbc框架,既然都是ORM框架,不如合并到一个项目中维护。
GitHub上原easymulti-datasource-spring-boot-starter项目已更名为easymulti-datasource,而原easymulti-datasource-spring-boot-starter模块已经更名为easymulti-datasource-mybatis,版本号从3.0.1开始。新版本增加了easymulti-datasource-r2dbc(也就是原hotkit-r2dbc)。
项目背景
多数据源动态切换似乎已经成了微服务的标配,做过那么多项目发现每个项目都要配一个动态数据源,都要写一个切面去实现动态切换,因此,我将这些繁琐的配置封装为starter,拿来即用。
easymulti-datasource两个模块:
easymulti-datasource-mybatis(原easymulti-datasource-spring-boot-starter)easymulti-datasource-r2dbc(原hotkit-r2dbc)
easymulti-datasource-mybatis
easymulti-datasource-mybatis自动整合了mybatis-plus,提供两种动态多数据源模式,分别是主从数据源模式、非主从的多数据源模式,每个数据源使用独立的连接池配置,可针对每个数据源单独配置连接池。
支持多数据源动态切换并不是easymulti-datasource-mybatis框架的最大亮点,easymulti-datasource-mybatis区别于其它动态数据源切换框架的主要特色如下:
支持监听SQL,监听修改某个表的某些字段的sql,用于实现埋点事件;
支持事务状态监听、注册事务***,用于在事务回滚/提交时再完成一些后台操作;
详细使用可参见wiki。
依赖配置
maven中使用:
旧版本为:
版本选择注意事项说明如下图所示。
动态切换数据源
使用注解切换数据源:@EasyMutiDataSource;使用API切换数据源:DataSourceContextHolder#setDataSource。
AOP中注册事务***
在application配置文件中打开追踪事务方法调用链路的开关,配置如下。
## 监控事务方法调用链路 easymuti: transaction: open-chain: true
定义切面,拦截Mapper方法,在环绕方法中实现更新缓存的逻辑,代码如下。
TransactionInvokeContext.currentExistTransaction:判断当前调用链路上是否存在事务;TransactionInvokeContext.addCurrentTransactionMethodPopListener:给当前事务绑定一个***(PopTransactionListener),当事务提交或者回滚时***被调用。
如上代码所示,首先是判断当前调用链路上是否存在事务,如果存在,则给当前事务注入一个***,由***完成缓存更新逻辑,如果不存在事务,在目标方法执行完成后且无异常抛出时执行更新缓存逻辑。
监听SQL
easymulti-datasource-mybatis支持sql埋点监听功能,并且支持监听事务状态,如果当前sql执行存在事务中,则会在事务提交后才会回调sql监听者。
第一步:启用sql埋点监听功能,并且启用事务调用链路追踪功能。
easymuti: transaction: open-chain: true sql-watcher: enable: true
第二步:编写观察者,可以有n多个,并且多个观察者也可观察同一个表、甚至相同字段。
observe方法在监听到sql时被同步调用,该方法返回的AsyncConsumer则在事务提交后被回调调用,如果事务回滚了则不会被调用。
如果调用链路上出现多个事务,那么根据事务的传播机制,只在当前方法所在事务提交时才会回调注册在该事务上的所有AsyncConsumer。
easymulti-datasource-r2dbc
spring-data-r2dbc版多数据源组件,用于响应式编程。
添加依赖与配置数据源
使用easymulti-datasource-r2dbc后,无需再在项目中添加spring-boot-starter-data-r2dbc的依赖,也不需要添加spring-data-r2dbc的依赖。
easymulti-datasource-r2dbc版本号对应spring-data-r2dbc的版本号:
easymulti-datasource-r2dbcspring-data-r2dbc
3.0.1-RELEASE 1.1.0.RELEASE
在项目中添加easymulti-datasource-r2dbc的依赖,如下。
此时,只需要额外添加用到的数据库类型对应的驱动依赖即可,例如,添加mysql的r2dbc驱动。
如果使用主从模式,则使用如下配置。
easymuti: database: r2dbc: master-slave-mode: master: url: r2dbc:mysql://127.0.0.1:3306/r2dbc_stu username: root password: pool: max-size: 5 idel-timeout: 60 slave: url: r2dbc:mysql://127.0.0.1:3306/r2dbc_stu username: root password: pool: max-size: 5 idel-timeout: 60
master会被设置为默认使用的数据源,slave有则配置,没有也可以为空。虽然slave允许为空,但如果真的不需要多数据源,也是没有必要使用easymulti-datasource-r2dbc的。
如果使用Cluster模式,则使用如下配置。
easymuti: database: r2dbc: cluster-mode: first: url: r2dbc:mysql://127.0.0.1:3306/r2dbc_stu username: root password: pool: max-size: 5 idel-timeout: 60 second: url: r2dbc:mysql://127.0.0.1:3306/r2dbc_stu username: root password: pool: max-size: 5 idel-timeout: 60 third: url: r2dbc:mysql://127.0.0.1:3306/r2dbc_stu username: root password: pool: max-size: 5 idel-timeout: 60
其中first会被设置为默认使用的数据源,second与third可以为空。
示例代码如下。
@Service public class PersonService { @Resource private PersonRepository personRepository; // 方法返回值类型为Mono测试 @R2dbcDataBase(MasterSlaveMode.Master) @Transactional(rollbackFor = Throwable.class) public Mono
编程式动态切换数据源
只需要调用EasyMutiR2dbcRoutingConnectionFactory提供的静态方法putDataSource为Context写入使用的数据源,代码如下。
public class RoutingTest extends SupporSpringBootTest { @Resource private DatabaseClient client; @Resource private ReactiveTransactionManager reactiveTransactionManager; @Test public void test() throws InterruptedException { TransactionalOperator operator = TransactionalOperator.create(reactiveTransactionManager); Mono
需要注意,如果需要使用事务,必须先调用TransactionalOperator对象的transactional方法,再调用EasyMutiR2dbcRoutingConnectionFactory的putDataSource方法。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。