1.Seata介绍
Seata是由阿里中间件团队发起的开源项目 Fescar,后更名为Seata,它是一个是开源的分布式事务框架。
传统2PC的问题在Seata中得到了解决,它通过对本地关系数据库的分支事务的协调来驱动完成全局事务。
是工作在应用层的中间件。主要优点是性能较好,且不长时间占用连接资源,它以高效并且对业务0侵入的方式解决微服 务场景下面临的分布式事务问题,它目前提供AT模式(即2PC)及TCC模式的分布式事务解决方案。
1.1. Seata的设计思想
seata 采用的是大量运用在数据库软件的 Write Ahead Log 思想,即把事务的信息以事务日志的方式记录下来。这种处理方式,实际上是对传统两阶段提交的一种改进和优化。主要有几个关键点:
- 传统两阶段提交协议是阻塞协议,性能差
- 传统两阶段提交协议高可用性不好
- 传统两阶段提交协议的全局事务隔离机制不支持
- 根据八二原则,80% 的涉及到全局事务的业务是能正常完成并提交的。
因此,seata 采取的做法是,一个事务分支的数据库操作执行完后,马上进行本地事务的提交,从而释放相关的数据库 资源。
- 分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。·
- 同时,随着本地事务结束,连接 也得以释放。·
- 分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全 局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。
1.2.本地事务执行流程
在进行本地提交的前提是,seata 会解析 SQL,获取数据库表的元数据,根绝 SQL 类型,选择性地生成数据的前置镜像和后置镜像, 保存在 undolog 表中,并且要求与保存 undolog 与业务 SQL 在同一个本地事务内。
这就保证了:
- 如果一个本地事务被提交,那么必定对应着相应的 undo_log
- 如果保存 undo_log 保存失败,那么业务 SQL 也会失败
1.3.全局事务提交流程
因为每个分支事务的本地事务都已经被提交,所以如果全局事务能够顺利进行到“提交“这一阶段,那么意味着所有事务分支的本地事 务都已经被提交了,数据的一致性已经得到了保证。
这个时候全局事务的提交就变得十分轻量级,就是把 undo_log 对应的记录删掉即可,即使是当时删除失败了,也已经不会影响全局事 务的最终结果,这次删不了,那就待会再删,程序删不了,没事,顶多人工删。
1.4.全局事务回滚流程
如果全局事务的任何一个事务分支失败了,那么全局事务就进入“回滚“流程,回滚时依据先前保存好数据镜像,将原来的数据回放回去。
如果全局回放成功,那么数据的一致性也就得到了保证,如果回放不成功,那么事务就进入异常。应对异常,可能需要重试,可能需要人工介入。
2.Seata在dubbo中的使用
2.1.新增mvn依赖
在需要增加分布式事务的模块加上相关依赖
1. `<dependency>`
2. `<groupId>io.seata</groupId>`
3. `<artifactId>seata-spring-boot-starter</artifactId>`
4. `<version>1.1.0</version>`
5. `</dependency>`
2.2.修改properties文件
1. `#服务名称`
2. `dubbo.application.name=service`
3. `#注册中心地址`
4. `dubbo.registry.address=127.0.0.1:2181`
5. `#注册中心类型`
6. `dubbo.registry.protocol=zookeeper`
7. `#版本号`
8. `dubbo.application.version=3`
9. `# Dubbo Protocol`
10. `#协议名称`
11. `dubbo.protocol.name=dubbo`
12. `#服务暴露端口`
13. `dubbo.protocol.port=20880`
18. `seata.enabled=true`
19. `seata.application-id=biz-service`
20. `seata.tx-service-group=my_test_tx_group`
21. `seata.client.rm.async-commit-buffer-limit=1000`
22. `seata.client.rm.report-retry-count=5`
23. `seata.client.rm.table-meta-check-enable=false`
24. `seata.client.rm.report-success-enable=false`
25. `seata.client.rm.lock.retry-interval=10`
26. `seata.client.rm.lock.retry-times=30`
27. `seata.client.rm.lock.retry-policy-branch-rollback-on-conflict=true`
28. `seata.client.tm.commit-retry-count=5`
29. `seata.client.tm.rollback-retry-count=5`
30. `seata.client.undo.data-validation=true`
31. `seata.client.undo.log-serialization=jackson`
32. `seata.client.undo.log-table=undo_log`
33. `seata.client.log.exceptionRate=100`
34. `seata.service.vgroup-mapping.my_test_tx_group=default`
35. `seata.service.grouplist.default=127.0.0.1:8091`
36. `seata.transport.shutdown.wait=3`
37. `seata.transport.thread-factory.boss-thread-prefix=NettyBoss`
38. `seata.transport.thread-factory.worker-thread-prefix=NettyServerNIOWorker`
39. `seata.transport.thread-factory.server-executor-thread-prefix=NettyServerBizHandler`
40. `seata.transport.thread-factory.share-boss-worker=false`
41. `seata.transport.thread-factory.client-selector-thread-prefix=NettyClientSelector`
42. `seata.transport.thread-factory.client-selector-thread-size=1`
43. `seata.transport.thread-factory.client-worker-thread-prefix=NettyClientWorkerThread`
44. `seata.transport.thread-factory.worker-thread-size=default`
45. `seata.transport.thread-factory.boss-thread-size=1`
46. `seata.transport.type=TCP`
47. `seata.transport.server=NIO`
48. `seata.transport.heartbeat=true`
49. `seata.transport.serialization=seata`
50. `seata.transport.compressor=none`
51. `seata.transport.enable-client-batch-send-request=true`
52. `seata.config.type=file`
53. `seata.registry.type=file`
2.3.新增配置类
1. `package cn.enjoy.mt.order.config;`
2. `import com.alibaba.druid.pool.DruidDataSource;`
3. `import org.apache.ibatis.session.SqlSessionFactory;`
4. `import org.mybatis.spring.SqlSessionFactoryBean;`
5. `import org.springframework.boot.context.properties.ConfigurationProperties;`
6. `import org.springframework.context.annotation.Bean;`
7. `import org.springframework.context.annotation.Configuration;`
8. `import org.springframework.core.io.support.PathMatchingResourcePatternResolver;`
9. `import javax.sql.DataSource;`
10. `@Configuration`
11. `public class SeataConfiguration {`
12. `@Bean`
14. `@ConfigurationProperties(prefix = "spring.datasource")`
16. `public DataSource druidDataSource() {`
18. `DruidDataSource druidDataSource = new DruidDataSource();`
20. `return druidDataSource;`
22. `}`
24. `@Bean`
25. `public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {`
27. `SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();`
29. `factoryBean.setDataSource(dataSource);`
31. `factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()`
33. `.getResources("classpath:/mapping/.xml"));`
35. `return factoryBean.getObject();`
37. `}`
38. `}`
2.4.新增undo_log日志表
1. `CREATE TABLE undo_log (`
2. `id bigint(20) NOT NULL AUTO_INCREMENT,`
3. `branch_id bigint(20) NOT NULL,`
4. `xid varchar(100) NOT NULL,`
5. `context varchar(128) NOT NULL,`
6. `rollback_info longblob NOT NULL,`
7. `log_status int(11) NOT NULL,`
8. `log_created datetime NOT NULL,`
9. `log_modified datetime NOT NULL,`
10. `ext varchar(100) DEFAULT NULL,`
11. `PRIMARY KEY (id),`
12. `UNIQUE KEY ux_undo_log (xid,branch_id)`
13. `) ENGINE=InnoDB DEFAULT CHARSET=utf8;`
2.5.SeataProperties
1. `package cn.enjoy.mt.order.config;`
2. `import org.springframework.boot.context.properties.ConfigurationProperties;`
3. `@ConfigurationProperties("spring.cloud.alibaba.seata")`
4. `public class SeataProperties {`
5. `private String txServiceGroup;`
6. `public SeataProperties() {`
7. `}`
8. `public String getTxServiceGroup() {`
9. `return this.txServiceGroup;`
10. `}`
11. `public void setTxServiceGroup(String txServiceGroup) {`
12. `this.txServiceGroup = txServiceGroup;`
13. `}`
14. `}`
2.6.修改启动类
1. `package cn.enjoy.mt.order;`
2. `import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;`
3. `import org.mybatis.spring.annotation.MapperScan;`
4. `import org.springframework.boot.SpringApplication;`
5. `import org.springframework.boot.autoconfigure.SpringBootApplication;`
6. `import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;`
7. `import org.springframework.cache.annotation.EnableCaching;`
8. `import org.springframework.context.annotation.PropertySource;`
9. `@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)`
10. `@EnableDubbo`
11. `@PropertySource("classpath:mt_db.properties")`
12. `@MapperScan("cn.enjoy.mt.dao")`
13. `@EnableCaching`
14. `public class OrderServiceApp {`
15. `public static void main(String[] args) {`
16. `SpringApplication.run(OrderServiceApp.class,args);`
17. `}`
18. `}`
2.7.增加 @GlobalTransactional注解
2.7.1.产品服务
1. `@GlobalTransactional`
2. `public void deleteById(Integer id) {`
3. `orderService.deleteByProductId(id);`
4. `int i = 10/0;`
5. `productInfoMapper.deleteByPrimaryKey(id);`
6. `}`
2.7.2.订单服务
1. `@Override`
3. `@GlobalTransactional`
5. `public void deleteByProductId(int id) {`
7. `orderInfoMapper.deleteByProductId(id);`
9. `}`
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/10171.html