当前位置: 首页 > news >正文

建立网站项目做网站不花钱

建立网站项目,做网站不花钱,网络推广就是做网站吗,沧州做网站哪家好1. 多数据源应用场景剖析 1.1 业务驱动的多数据源需求 数据量与业务复杂度引发的分库分表#xff1a;在现代企业级应用中#xff0c;随着业务的不断拓展和用户量的持续增长#xff0c;数据量呈爆炸式增长。例如#xff0c;在大型电商平台中#xff0c;用户数据、订单数据…1. 多数据源应用场景剖析 1.1 业务驱动的多数据源需求 数据量与业务复杂度引发的分库分表在现代企业级应用中随着业务的不断拓展和用户量的持续增长数据量呈爆炸式增长。例如在大型电商平台中用户数据、订单数据、商品数据等各类数据海量积累。若将所有数据存储于单一数据库查询和管理效率将急剧下降。以用户相关数据为例用户的基本信息、购物偏好、历史订单等数据繁多若与商品库存、评论等数据混合存储每次查询用户信息时都需遍历大量无关数据严重影响性能。因此将与用户相关的数据如用户信息、购物车、订单历史等存储在专门的用户库中而与商品相关的数据如商品信息、库存、评论等存放在商品库这种按业务领域划分数据库的方式能极大提高数据管理的效率和系统的可扩展性。 数据分布在不同的数据库中数据库拆了应用没拆。一个公司多个子项目各用各的数据库涉及数据共享这种情况也可以使用OpenFeign进行服务间调用但是存在http调用网络损耗分库分表根据业务来划分不同的库比如与用户相关的表在db_user库与订单相关的表在db_order库。 读写分离优化数据库性能数据库的读写操作在性能和资源占用上存在显著差异。写操作通常需要对数据进行加锁以确保数据的一致性和完整性这在高并发场景下可能导致读操作被阻塞严重影响系统的整体读性能。例如在电商促销活动期间大量用户同时下单写操作若读写不分离查询商品信息读操作的用户可能会遇到长时间的延迟。为解决此问题许多数据库采用主从架构。主库负责处理所有的写操作如用户下单、更新库存等从库则专门用于处理读操作如查询商品信息、用户订单列表等。通过这种方式能有效提高系统的整体性能满足高并发场景下的读写需求提升用户体验。 master和slave模式master库只用来写入数据slave库只用来读取数据。为了解决数据库的读性能瓶颈读比写性能更高写锁会影响读阻塞从而影响读的性能。很多数据库拥有主从架构。也就是一台主数据库服务器是对外提供增删改业务的生产服务器另一多台从数据库服务器主要进行读的操作。可以通过中间件ShardingSphere、mycat、mysql-proxy、TDDL…但是有一些规模较小的公司没有专门的中间件团队搭建读写分离基础设施因此需要业务开发人员自行实现读写分离。 1.2 技术视角下的多数据源场景 高性能主从架构在追求高性能的场景中主从架构是一种经典且有效的解决方案。主库作为数据的主要写入点承担所有的写操作确保数据的一致性和完整性。从库通过复制主库的数据实现数据的冗余备份同时分担读操作的负载。一主一从或一主多从的配置可根据实际业务需求灵活调整。例如在一个内容管理系统中主库负责更新文章内容、用户评论等写操作多个从库可用于处理用户浏览文章、搜索等读操作根据读操作的流量大小合理分配从库数量以平衡系统的性能和成本。高可用主备模式对于对数据库高可用性要求极高的场景主备模式提供了可靠的保障。主数据库正常情况下对外提供服务而备用数据库时刻处于待命状态。当主数据库出现故障如硬件故障、网络问题等时备用数据库能迅速接管服务确保业务的连续性。多主多备的配置进一步提高了系统的容错能力和可靠性。例如在金融交易系统中一旦主数据库发生故障备用数据库能立即切换避免交易中断保障金融业务的稳定运行。同构与异构数据处理在实际应用中企业可能因历史遗留问题、业务并购或技术选型等原因需要处理存储在不同类型数据库中的数据。同构数据处理涉及到多个相同类型数据库如多个 MySQL 数据库之间的数据交互这种情况相对较为简单主要挑战在于数据的同步和一致性维护。而异构数据处理则需要在不同数据库系统如 MySQL 与 Oracle 或 PostgreSQL之间进行数据整合和操作这要求系统具备强大的跨数据库兼容性和数据转换能力。例如企业在升级数据库系统时可能需要将旧数据库中的数据迁移到新系统中同时确保新老系统在一段时间内的数据同步。 1.3 实际项目中的多数据源案例 多库连接的服务需求在企业级应用开发中一个服务往往需要与多个数据库进行交互以满足复杂的业务需求。以一个企业内部的综合管理系统为例其中的 basic 服务既要连接菜单库获取用户操作菜单信息又要连接用户库进行用户权限验证和用户个性化信息获取。若菜单库和用户库未分离随着菜单数量和用户数据的增加查询和管理的复杂性将呈指数级增长影响系统整体性能和可维护性。风控系统的多库校验风控系统在保障企业业务安全方面起着至关重要的作用它需要对业务进行全方位的校验这通常涉及到多个业务库。在金融领域的信贷业务中风控系统在业务流程的不同阶段如事前、事中、事后从相应的业务库中获取数据进行风险评估和控制。例如事前校验可能需要从用户信用库中获取用户信用评分、信用记录等信息以评估用户的信用风险事中校验可能需要查询交易流水库实时监控交易行为是否异常事后校验可能涉及账户状态库确保交易完成后账户状态的正确性。通过对多个业务库的综合校验有效降低风险保障金融业务的稳健运行。批量数据查询与直连数据库在某些特定业务场景下虽然接口提供了数据查询功能但对于批量查询操作直接连接数据库可能更为高效。例如在就业业务中社保数据查询可能涉及大量人员信息。若通过接口循环调用由于网络传输的延迟和开销性能将受到严重影响。在获得客户同意的情况下直接连接对方的备份库进行查询可以大大提高效率但需要谨慎操作避免对生产库造成过大的负载。如在批量查询企业员工社保缴纳记录时直连备份库能快速获取数据减少用户等待时间提升业务处理效率。新老系统数据库同步在系统升级或更替过程中新老数据库的同步是一个关键问题。以企业的人力资源管理系统为例当经办系统进行更新换代时友商的老系统数据库可能仍在为大数据中心提供实时服务。为了确保数据的一致性和业务的连续性需要实时将新系统中的数据写入老系统数据库或者反之。在一些情况下如果实时同步不可行也可采用数据库定时同步策略但这可能会导致一定的数据延迟。例如新系统中员工的最新人事变动信息需要及时同步到老系统以保证整个企业人力资源数据的完整性和准确性。 2. 多数据源的实现策略 2.1 传统 AOP 事务拦截与数据源选择 在多数据源管理中传统的实现方式通常采用 AOP面向切面编程进行事务拦截。当开启事务时通过判断数据源的键key来决定使用哪个数据源。这种方式需要手动管理数据源的切换逻辑增加了代码的复杂性和维护成本。 例如开发人员需要编写切面类在方法执行前根据业务规则选择合适的数据源并将其绑定到当前线程的上下文中。以下是一个简单的 AOP 事务拦截实现示例 Aspect Component public class DataSourceAspect {Before(annotation(yourTransactionAnnotation))public void switchDataSource(JoinPoint joinPoint) {// 根据业务规则获取数据源键String dataSourceKey determineDataSourceKey(joinPoint);// 从数据源池中获取相应数据源并绑定到当前线程DataSource dataSource DataSourceManager.getDataSource(dataSourceKey);DataSourceContextHolder.setDataSource(dataSource);}private String determineDataSourceKey(JoinPoint joinPoint) {// 这里可以根据方法参数、类名等信息确定数据源键// 例如如果方法参数中有特定标识则选择对应的数据源Object[] args joinPoint.getArgs();for (Object arg : args) {if (arg instanceof YourDataSourceIndicator) {return ((YourDataSourceIndicator) arg).getDataSourceKey();}}// 如果无法确定则返回默认数据源键return defaultDataSource;} }2.2 MyBatis Plus的DS注解的优势 MyBatis Plus 提供的 DS 注解简化了多数据源的管理过程。该注解可以直接标记在 Mapper 接口或 Service 方法上指定要使用的数据源。其原理是基于动态数据源切换机制在运行时根据注解的配置信息自动从多个数据源中选择合适的数据源进行数据库操作。 例如在一个包含用户库和订单库的系统中通过在用户相关的 Mapper 接口上标注 DS (“user”)在订单相关的 Mapper 接口上标注 DS (“order”)可以轻松实现数据源的切换而无需编写复杂的 AOP 拦截逻辑。 2.3 ThreadLocal在数据源管理中的角色 在多数据源切换过程中ThreadLocal 起着关键作用。它用于存储当前线程的数据库键key变量确保在同一线程内的数据库操作都使用相同的数据源。当一个线程进入带有 DS 注解的方法时DS 注解会将对应的数据源键存入 ThreadLocal 中。在后续的数据库操作中通过获取 ThreadLocal 中的数据源键从数据源池中获取相应的数据库连接。这种方式保证了数据源的线程安全性避免了不同数据源之间的干扰。 以下是一个简单的 ThreadLocal 使用示例 public class DataSourceContextHolder {private static final ThreadLocalString contextHolder new ThreadLocal();public static void setDataSource(String dataSourceKey) {contextHolder.set(dataSourceKey);}public static String getDataSource() {return contextHolder.get();}public static void clearDataSource() {contextHolder.remove();} }3. 多数据源下的事务问题 3.1 Transational和DS注解冲突问题 3.1.1 问题模拟 先导入pom.xml依赖 dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!-- 数据源切换依赖 --dependencygroupIdcom.baomidou/groupIdartifactIddynamic-datasource-spring-boot-starter/artifactIdversion3.5.2/version/dependency!-- MySQL依赖 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.29/version/dependency!-- Mybatis依赖 --dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.2.2/version/dependency/dependenciesyml文件配置了3个数据源主数据源是master从数据源是slave后续临时加了个数据源temp为了用于事务的测试数据库均为MySQL。 server:port: 8080spring:datasource:dynamic:primary: masterdatasource:master:username: anarkhpassword: 123456url: jdbc:mysql://localhost:3306/anarkh_master?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneUTCdriver-class-name: com.mysql.cj.jdbc.Driverslave:username: anarkhpassword: 123456url: jdbc:mysql://localhost:3306/anarkh_slave?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneUTCdriver-class-name: com.mysql.cj.jdbc.Drivertemp:username: anarkhpassword: 123456url: jdbc:mysql://localhost:3306/temp?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneUTCdriver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapping/*.xml分别编写主数据源和从数据源的Mapper层接口 Mapper DS(master) public interface MasterMapper {int insertUser(User user); }Mapper DS(slave) public interface SlaveMapper {int insertRole(Role role); }分别编写对应的XML文件 ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.demo.mapper.MasterMapperinsert idinsertUser parameterTypecom.example.demo.bean.UserINSERT INTO user (username, password)VALUES(#{username}, #{password})/insert /mapper?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.demo.mapper.SlaveMapperinsert idinsertRole parameterTypecom.example.demo.bean.RoleINSERT INTO role (role)VALUES(#{role})/insert /mapper编写Service方法 Service public class UserService {Resourceprivate MasterMapper masterMapper;Resourceprivate SlaveMapper slaveMapper;Transactionalpublic void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);} }测试运行报错如下 ### Error updating database. Cause: java.sql.SQLSyntaxErrorException: Table master.role doesnt exist ### The error may exist in file [D:\JavaProjects\Java\demo\target\classes\mapping\SlaveMapper.xml] ### The error may involve com.example.demo.mapper.SlaveMapper.insertRole-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO role (role) VALUES(?) ### Cause: java.sql.SQLSyntaxErrorException: Table master.role doesnt exist ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table master.role doesnt exist从报错的表面上来看是因为在主数据库当中不存在role这个表可是我们已经切换了数据源呀可为什么还是报错呢 3.1.2 原因分析 在 Spring 框架中Transactional 注解用于开启事务管理。当一个方法被标注为 Transactional 时Spring 会在方法执行前从数据库连接池获取数据库连接并将该事务与当前线程绑定。在事务执行过程中数据库连接通过 ThreadLocal 与当前线程绑定。一旦事务开始所有的数据库操作都将使用该绑定的连接。当 DS 注解尝试切换数据源时如果事务已经开始并且连接已经绑定新的数据源切换请求可能会被忽略导致实际执行数据库操作时仍然使用了错误的数据源。例如在一个同时涉及主库写操作和从库读操作的事务方法中如果主库事务已经开始并绑定了连接后续的从库操作可能因为无法切换数据源而失败。 说回到上面的例子Transactional开启事务的时候会先从数据库连接池获取是数据库的连接基于Spring的AOP切面我们UserService方法上面没有打上DS注解所以Spring默认采用的是主数据源而且在这之后这个事务会通过ThreadLocal跟当前线程绑定并也报错了connection连接通俗的来讲在进入UserService方法的时候当前事务已经绑定了数据源Master在运行到SlaveMapper接口时因为当前事务的connection连接已经存在所以拿到的数据源还是默认的Master于是想找到Slave当中的role表当然是不可能的所以只能报错了。 3.1.3 解决方案 3.1.3.1 采用分布式事务 分布式事务是解决多数据源事务一致性问题的一种方法。在分布式系统中多个数据源可能分布在不同的节点或服务中传统的本地事务无法满足跨数据源事务的需求。分布式事务管理框架如 Seata、Atomikos 等提供了强大的事务协调能力确保在多个数据源之间的操作要么全部成功提交要么全部回滚。例如在一个微服务架构中订单服务可能涉及用户库、商品库和库存库等多个数据源的操作。通过分布式事务框架可以协调这些数据源的事务保证数据的一致性。然而分布式事务的实现相对复杂需要额外的配置和基础设施支持并且可能会对系统性能产生一定的影响。以下是一个使用 Seata 实现分布式事务的简单示例 引入 Seata 相关依赖 dependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.2/version /dependency配置 Seata 相关参数如注册中心地址、事务分组等 seata.registry.typeeureka seata.registry.eureka.application seata-server seata.registry.eureka.service-url http://localhost:8761/eureka seata.tx-service-groupmy_tx_group在服务中使用 GlobalTransactional 注解开启分布式事务 Service public class UnitServiceImpl implements UnitService {Autowiredprivate UserService userService;Autowiredprivate RoleService roleService;GlobalTransactionalOverridepublic void Add() {User user new User();user.setUsername(anarkh);user.setPassword(666666);userService.insertUser(user);Role role new Role();role.setRole(管理员);roleService.insertRole(role);} }3.1.3.2 更改事务的传播机制有问题 Propagation.REQUIRES_NEW 机制原理 更改事务的传播机制为 Propagation.REQUIRES_NEW 是解决 Transactional 与 DS 冲突的一种方法。这种机制会挂起当前事务并创建一个新的事务为新事务分配新的数据库连接。新事务与原事务相互独立各自的提交和回滚操作不会相互影响。在多数据源操作中这可以确保每个数据源操作都在正确的事务和连接下执行。例如在主从数据源操作中将从库操作的事务传播机制设置为 Propagation.REQUIRES_NEW可以使从库操作在独立的事务中执行不受主库事务的影响。 事务传播机制的注意事项与潜在问题 虽然 Propagation.REQUIRES_NEW 可以解决数据源切换问题但也带来了一些潜在问题。在同一个方法中如果存在多个具有不同事务传播机制的子方法事务的一致性管理会变得复杂。例如当一个方法 A 中调用了一个具有 Propagation.REQUIRES_NEW 的方法 B然后方法 B 中又调用了一个方法 C。如果方法 C 出现异常并回滚方法 B 根据其事务机制可能已经提交而方法 A 可能会因为异常而回滚这就导致了事务的不一致性。因此在使用这种机制时需要仔细考虑事务的边界和异常处理逻辑确保整个业务流程的事务一致性。 改进 其实我们只要更改一下事务的传播机制将它设置为Propagation.REQUIRES_NEW即可意思就是将原有的Spring事务挂起并创建一个新的事务并分配的一个新的connection两者不影响具体操作如下 修改原有的UserService代码 不用通过DS指定数据源因为默认是Master将slave业务操作分离出来封装到一个Service服务类当中再通过Resource注解注入进来最后还是指定一下回滚策略遇到异常就回滚。 Service public class UserService {Resourceprivate MasterMapper masterMapper;Resourceprivate SlaveService slaveService;Transactional(rollbackFor Exception.class)public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);slaveService.slave();}}编写SlaveService服务代码 必须通过DS指定一下数据源为slave在slave方法上面重新修改一下事务的传播机制即可 Service DS(slave) public class SlaveService {Resourceprivate SlaveMapper slaveMapper;Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class)public void slave(){Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);} }其他的保持不变最后我们再测试一下看一下输出结果成功了 注意 因为Propagation.REQUIRES_NEW是开启一个新的事务并重新分配一个新的数据库连接在同一个方法中有A方法和一个开启新的传播事务的B方法如果B方法中出现了异常发生了回滚那么A方法也会随之回滚但是但是但是如果B方法后面有一个新方法C当C方法中出现了异常C方法回滚了但是B方法根据它事务机制并且已经提交了事务那么就会出现A事务回滚了B事务提交了C事务回滚了这样ABC三个方法出出现了事务不一致的问题在下面的事务回滚机制的第五条有演示。 3.1.3.3 DSTransational注解代替Transactional DSTransactional 注解功能概述 DSTransactional 注解是专门为解决多数据源事务问题而设计的。它可以直接替代 Transactional 注解在不改变原有代码结构的基础上实现多数据源事务的正确管理。该注解内部实现了对数据源切换和事务管理的优化确保在多数据源操作中事务的一致性和正确性。 使用 DSTransactional 注解非常简单。只需在原来使用 Transactional 的地方替换为 DSTransactional并确保项目中引入了相应的依赖。例如在一个包含主从数据源操作的 Service 方法中标注 DSTransactional 后该方法中的所有数据库操作涉及不同数据源将在一个事务中正确执行并且在出现异常时能够自动回滚所有相关数据源的操作。 我们可以使用DSTransactional注解代替Transactional即可其他什么都不用动也是最简单的方法。 导入pom.xml依赖 dependencygroupIdcom.baomidou/groupIdartifactIddynamic-datasource-spring-boot-starter/artifactIdversion3.5.0/version/dependency修改UserService代码 Service public class UserService {Resourceprivate MasterMapper masterMapper;Resourceprivate SlaveMapper slaveMapper;DSTransactionalpublic void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);} }运行测试查看输出结果成功 4. 事务回滚机制的详细解析 在多数据源事务中事务回滚机制的行为取决于异常抛出的位置和事务传播机制的设置。以下是几种常见异常场景下的事务回滚行为分析 4.1 在Master和Slave事务执行前抛出异常 UserService类 Transactional(rollbackFor Exception.class) public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);int a 1/0;masterMapper.insertUser(user);slaveService.slave(); }结果数据保持一致 原因事务还未开始执行数据库操作异常直接导致方法终止事务不会被提交。 4.2、当master事务和slave事务中间抛出异常 UserService类 Transactional(rollbackFor Exception.class) public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);int a 1/0;slaveService.slave(); }结果回滚master事务slave事务无影响 原因在事务执行过程中当出现异常时事务会根据异常情况决定是否回滚已经执行的操作。在这种情况下master 事务已经执行了部分操作由于异常发生在中间根据事务的原子性已执行的 master 事务操作将被回滚。 4.3、在slave方法中抛出异常 SlaveService类 Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class) public void slave(){Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);int a 1/0; }结果master和slave事务都会进行回滚 原因slave 事务设置了 Propagation.REQUIRES_NEW它会在独立的事务中执行当 slave 事务中出现异常时它会自行回滚同时由于外层的 UserService 方法也在一个事务中由 Transactional 注解管理并且 slave 事务的异常会传播到外层事务导致外层事务也回滚从而实现了 master 和 slave 事务的一致性回滚。 4.4、在master和slave事务之后 UserService类 Transactional(rollbackFor Exception.class) public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);slaveService.slave();int a 1/0; }结果master事务回滚slave已经提交事务入库 原因在事务执行过程中master 事务和 slave 事务在异常抛出前已经完成了提交操作而事务的回滚通常是基于异常的捕获和处理机制。在这种情况下异常发生在事务提交之后master 事务由于受到 Transactional 注解的管理会根据异常情况进行回滚但 slave 事务已经完成了提交无法再进行回滚操作。 4.5、临时添加一个temp数据库进行插入操作并抛出异常 UserService类 Transactional(rollbackFor Exception.class) public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);slaveService.slave();tempService.temp(); }TempService类 Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class) public void temp(){Car car new Car();car.setCar(Benz);tempMapper.insertCar(car);int a 1/0; }结果master回滚slave事务提交temp回滚 原因 temp 事务设置了 Propagation.REQUIRES_NEW它在独立的事务中执行当 temp 事务中出现异常时它会自行回滚而 master 事务由于受到 Transactional 注解的管理会根据异常情况进行回滚slave 事务由于已经提交不受影响。 4.6、嵌套 UserService类 Transactional(rollbackFor Exception.class) public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);slaveService.slave(); }SlaveService类 Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class) public void slave(){Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);tempService.temp(); }TempService类 Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class) public void temp(){Car car new Car();car.setCar(Benz);tempMapper.insertCar(car);int a 1/0; }结果master回滚slave回滚temp回滚 原因在嵌套事务中内层事务TempService 中的事务的异常会传播到外层事务SlaveService 中的事务导致 SlaveService 中的事务回滚而 SlaveService 中的事务回滚又会传播到最外层的 UserService 中的事务导致整个事务链中的所有事务都回滚从而保证了数据的一致性。 4.7、使用DSTransactional注解在slave和temp之间抛出异常 UserService类 DSTransactional public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);int a1/0;Car car new Car();car.setCar(Benz);tempMapper.insertCar(car); }结果master回滚slave回滚、temp回滚 4.8、使用DSTransactional注解在最后抛出异常 DSTransactional public void Add(){User user new User();user.setUsername(anarkh);user.setPassword(666666);masterMapper.insertUser(user);Role role new Role();role.setRole(管理员);slaveMapper.insertRole(role);Car car new Car();car.setCar(Benz);tempMapper.insertCar(car);int a1/0; }结果master回滚slave回滚、temp回滚 5. 适用场景总结与技术选型建议 5.1 不同解决方案的适用场景总结 DSTransactional 注解适用于单个服务内的多数据源事务管理简单易用能够有效地保证事务的一致性和数据源的正确切换。在开发过程中如果系统架构相对简单且多数据源操作主要集中在一个服务内DSTransactional 是一个不错的选择。例如在一个小型电商系统中订单服务可能需要同时操作订单库和用户库使用 DSTransactional 注解可以方便地管理这两个数据源的事务确保数据的完整性。分布式事务框架如 Seata、Atomikos当系统采用微服务架构涉及多个服务之间的多数据源事务协作时分布式事务框架是必要的选择。它能够提供强大的事务协调能力确保跨服务、跨数据源的事务一致性但需要投入更多的资源进行配置和维护。例如在一个大型电商平台中订单服务、库存服务、支付服务等多个服务可能涉及不同的数据源此时使用分布式事务框架可以保证整个业务流程的事务正确性避免数据不一致的情况发生。事务传播机制调整Propagation.REQUIRES_NEW在一些特定场景下如需要对部分数据源操作进行独立事务管理时可以使用事务传播机制调整。但需要注意其可能带来的事务不一致性问题谨慎使用并确保对事务边界和异常处理有清晰的理解。比如在一个复杂的业务逻辑中某个子操作对数据源的写操作独立性要求较高且不希望受外层事务影响时可以考虑使用 Propagation.REQUIRES_NEW 来单独管理该子操作的事务但同时要处理好与外层事务的交互和异常情况。 注 只有一个服务且用到多个数据源时用DSTransational注解比较方便可以控制多数据源进行回滚。 为什么说只有一个服务采用DSTransactional注解多服务不行吗不行。如果系统是微服务架构db1、db2、db3都源于不同的服务那么db3报错时前面两个并不会回滚因为他们都不在一个服务内DSTransactional注解此时派不上用场。此时只能采用分布式事务控制了seata、Atomikos。 5.2 技术选型决策因素与最佳实践 在选择多数据源事务管理解决方案时需要综合考虑多个因素。首先是系统架构微服务架构通常需要分布式事务框架来处理跨服务事务而单体应用或简单的多模块应用可能更适合使用 DSTransactional 注解。其次是性能要求分布式事务框架可能会带来一定的性能开销需要根据系统的实际性能需求进行评估。例如如果系统对性能要求极高且多数据源操作相对简单可能需要谨慎考虑分布式事务框架的使用避免性能下降。此外开发团队的技术能力和维护成本也是重要的考虑因素。如果团队对分布式事务框架不熟悉可能会在配置和维护过程中遇到困难增加项目风险。最佳实践是在项目初期进行充分的技术调研和架构设计根据系统的特点和需求选择最合适的事务管理方案并在开发过程中遵循相关的设计原则和规范确保事务的正确性和系统的稳定性。同时建立完善的监控和测试机制及时发现和解决事务管理中可能出现的问题。
http://www.sczhlp.com/news/158126/

相关文章:

  • 夜夜做新郎网站游戏源码买卖平台
  • 深圳网站开发公司 有哪些常用的html编辑器有哪些
  • 如何 html5 网站合肥集团网站建设哪个好
  • 建模素材免费网站重庆网站开发哪家专业
  • 网站项目功能需求清单深圳企业网站制作设计方案
  • 网站开发赚钱什么样的网站需要icp经营性备案
  • 北京网站制作的公司官网开发
  • 六安高端网站建设公司wordpress dante
  • 服务网站运营方案微信小程序好看的ui界面
  • 网站搜索不到了惠州市建设局人员备案网站
  • 做网站商城需要申请商标吗wordpress火车头接口
  • 企业门户网站费用专业商城网站建设多少钱
  • 山西专业网站建设大全上海网站建设排名公司
  • 哈尔滨做网站设计淘宝主图制作
  • 网站建设东营企业网站文案外包
  • 做网站后期续费是怎么算的九江 网站建站 设计 公司
  • 网站导航功能wordpress分块
  • 阿里巴巴网站icp编号怎么查三亚建设局网站
  • 关于网站建设的故事河南省和建设厅网站
  • FlareOn1 -- 5get_it
  • 2025 年阀门厂家 TOP 企业品牌推荐排行榜,管道阀门,气动,调节,电动执行器,生产,电磁,不锈钢,进口,耐高温阀门推荐这十家公司
  • 287. 寻找重复数
  • 福州市 2025 国庆集训 Day2 前三题题解
  • 2025 年马赛克厂家 TOP 企业品牌推荐排行榜,陶瓷,游泳池,喷墨,冰裂,拼花,防滑,复古,家装马赛克推荐这十家公司!
  • 众筹网站开发周期上海新增感染呈下降趋势
  • 建设网站需要哪个软件要压实互联网企业的什么责任
  • jsp酒店预订网站开发商标设计网软件
  • 摄影展示网站源码wordpress 软件主题
  • 淘宝 网站建设 发货网站未备案做经营被罚款
  • 用二级域名做网站网站建设文本