千家信息网

支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么

发表于:2024-10-10 作者:千家信息网编辑
千家信息网最后更新 2024年10月10日,这篇文章主要讲解了"支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"支持监听SQL、感知事
千家信息网最后更新 2024年10月10日支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么

这篇文章主要讲解了"支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"支持监听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

mybatis版多数据源框架,提供声明式和编程式动态切换数据源功能。

easymulti-datasource-mybatis自动整合了mybatis-plus,提供两种动态多数据源模式,分别是主从数据源模式、非主从的多数据源模式,每个数据源使用独立的连接池配置,可针对每个数据源单独配置连接池。

支持多数据源动态切换并不是easymulti-datasource-mybatis框架的最大亮点,easymulti-datasource-mybatis区别于其它动态数据源切换框架的主要特色如下:

支持监听SQL,监听修改某个表的某些字段的sql,用于实现埋点事件;

支持事务状态监听、注册事务监听器,用于在事务回滚/提交时再完成一些后台操作;

详细使用可参见wiki。

依赖配置

maven中使用:

     com.github.wujiuye     easymulti-datasource-mybatis     ${version} 

旧版本为:

     com.github.wujiuye     easymulti-datasource-spring-boot-starter     ${version} 

版本选择注意事项说明如下图所示。

动态切换数据源

  • 使用注解切换数据源:@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多个,并且多个观察者也可观察同一个表、甚至相同字段。

@Component @Slf4j public class TestTableFieldObserver implements TableFieldObserver , InitializingBean {      @Override     public Set observeMetadatas() {        // 在这里注册要监听哪些表的哪些字段     }      /**      * 监听到sql时被同步调用      *      * @param commandType 事件类型      * @param matchResult 匹配的ITEM      * @return 返回异步消费者      */     @Override     public AsyncConsumer observe(CommandType commandType, MatchItem matchResult) {         // 同步消费         // 这里是sql执行之前,可在sql执行之前做一些事情,比如新旧数据的对比,这里查出旧数据          // 异步消费,再sql执行完成时,或者在事务方法执行完成时(如果存在事务),完成指:正常执行完成 or 方法异常退出         return throwable -> {             // sql执行抛出异常不处理             if (throwable != null) {                 return;             }             // 消费事件             // ....         };     }  }

observe方法在监听到sql时被同步调用,该方法返回的AsyncConsumer则在事务提交后被回调调用,如果事务回滚了则不会被调用。

如果调用链路上出现多个事务,那么根据事务的传播机制,只在当前方法所在事务提交时才会回调注册在该事务上的所有AsyncConsumer。

easymulti-datasource-r2dbc

spring-data-r2dbc版多数据源组件,用于响应式编程。

easymulti-datasource-r2dbc为spring-data-r2dbc实现动态路由接口,为反应式编程提供声明式和编程式多数据源动态切换提供支持。同样支持两种多数据源模式,覆盖常见的多数据源使用场景,分别是主从模式和Cluster模式,Cluster模式支持最多配置3个数据源,而主从模式支持一主一从。

添加依赖与配置数据源

使用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-RELEASE1.1.0.RELEASE

在项目中添加easymulti-datasource-r2dbc的依赖,如下。

     com.github.wujiuye     easymulti-datasource-r2dbc     ${version} 

此时,只需要额外添加用到的数据库类型对应的驱动依赖即可,例如,添加mysql的r2dbc驱动。

     dev.miku     r2dbc-mysql     0.8.2.RELEASE 

如果使用主从模式,则使用如下配置。

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可以为空。

声明式动态切换数据源

声明式动态切换数据源即使用注解方式动态切换数据源,只需要在spring bean的public方法或者类上添加@R2dbcDataBase注解,将注解的value属性指定为使用的数据源。

示例代码如下。

@Service public class PersonService {      @Resource     private PersonRepository personRepository;        // 方法返回值类型为Mono测试     @R2dbcDataBase(MasterSlaveMode.Master)     @Transactional(rollbackFor = Throwable.class)     public Mono addPerson(Person... persons) {         Mono txOp = null;         for (Person person : persons) {             if (txOp == null) {                 txOp = personRepository.insertPerson(person.getId(), person.getName(), person.getAge());             } else {                 txOp = txOp.then(personRepository.insertPerson(person.getId(), person.getName(), person.getAge()));             }         }         return txOp;     }      // 方法返回值类型为Flux测试     @R2dbcDataBase(MasterSlaveMode.Master)     @Transactional(rollbackFor = Throwable.class)     public Flux addPersons(Flux persons) {         return persons.flatMap(person -> personRepository.insertPerson(person.getId(), person.getName(), person.getAge()));     }  }
  • 如果是主从模式,@R2dbcDataBase注解的value属性可选值参见MasterSlaveMode接口声明的常量;

  • 如果是Cluster模式,@R2dbcDataBase注解的value属性可选值参见ClusterMode接口声明的常量;

编程式动态切换数据源

声明式切换数据源的实现是依赖编程式切换数据源实现的,因此,我们也可以直接编写代码切换数据源,而不需要将方法改为public暴露出去。

只需要调用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 atomicOperation = client.execute("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")                 .bind("id", "joe")                 .bind("name", "Joe")                 .bind("age", 34)                 .fetch().rowsUpdated()                 .then(client.execute("INSERT INTO person (id, name) VALUES(:id, :name)")                         .bind("id", "joe")                         .bind("name", "Joe")                         .fetch().rowsUpdated())                 .then();         // 包装事务         Mono txOperation = operator.transactional(atomicOperation);         // 包装切换数据源         EasyMutiR2dbcRoutingConnectionFactory.putDataSource(txOperation, MasterSlaveMode.Slave).subscribe();         TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);     }  }

需要注意,如果需要使用事务,必须先调用TransactionalOperator对象的transactional方法,再调用EasyMutiR2dbcRoutingConnectionFactory的putDataSource方法。

感谢各位的阅读,以上就是"支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么"的内容了,经过本文的学习后,相信大家对支持监听SQL、感知事务状态、回溯数据源的动态数据源框架是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

数据 数据源 事务 动态 监听 切换 方法 支持 模式 配置 框架 项目 状态 主从 注解 监听器 链路 代码 版本 功能 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 引导网络技术 不履行网络安全法规定的 金边软件开发公司 九阴真经服务器架设 数据库中如何查询触发器 甜橙音乐网数据库包括哪些数据表 湖北放心软件开发服务参考价格 网络技术岗位认知怎么写 海南壹滴水互联网科技有限公司 杭州立盛软件开发有限公司李德 服务器系统安全设计配置 sql数据库字段拼接 小学开展网络安全周信息报送 给别人软件开发费用开发票 重庆卓下软件开发学校 数据库安全性的主要技术和方法 华为网络安全进展 互联网大厦天驰科技 装备跨界能夸服务器嘛 2017国家网络安全法 机械专业做软件开发 三级分销 后台数据库 小鸟云服务器怎么添加域名视频 怎么看企业内网网络安全 网络安全龙头低估值 网络安全工程师 郑州 亚洲服务器英文没人玩的吗 医保网络安全管理要求 魅来网络技术服务 数据库默认当前日期值怎么设置
0