Seata是由阿里中间件团队发起的开源项目 Fescar,后更名为Seata,它是一个是开源的分布式事务框架。
传统2PC的问题在Seata中得到了解决,它通过对本地关系数据库的分支事务的协调来驱动完成全局事务。
是工作在应用层的中间件。主要优点是性能较好,且不长时间占用连接资源,它以高效并且对业务0侵入的方式解决微服 务场景下面临的分布式事务问题,它目前提供AT模式(即2PC)及TCC模式的分布式事务解决方案。
seata 采用的是大量运用在数据库软件的 Write Ahead Log 思想,即把事务的信息以事务日志的方式记录下来。这种处理方式,实际上是对传统两阶段提交的一种改进和优化。主要有几个关键点:
传统两阶段提交协议是阻塞协议,性能差
传统两阶段提交协议高可用性不好
传统两阶段提交协议的全局事务隔离机制不支持
根据八二原则,80% 的涉及到全局事务的业务是能正常完成并提交的。
因此,seata 采取的做法是,一个事务分支的数据库操作执行完后,马上进行本地事务的提交,从而释放相关的数据库 资源。
分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。·
同时,随着本地事务结束,连接 也得以释放。·
分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全 局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。
在进行本地提交的前提是,seata 会解析 SQL,获取数据库表的元数据,根绝 SQL 类型,选择性地生成数据的前置镜像和后置镜像, 保存在 undolog 表中,并且要求与保存 undolog 与业务 SQL 在同一个本地事务内。
这就保证了:
如果一个本地事务被提交,那么必定对应着相应的 undo_log
如果保存 undo_log 保存失败,那么业务 SQL 也会失败
因为每个分支事务的本地事务都已经被提交,所以如果全局事务能够顺利进行到“提交“这一阶段,那么意味着所有事务分支的本地事 务都已经被提交了,数据的一致性已经得到了保证。
这个时候全局事务的提交就变得十分轻量级,就是把 undo_log 对应的记录删掉即可,即使是当时删除失败了,也已经不会影响全局事 务的最终结果,这次删不了,那就待会再删,程序删不了,没事,顶多人工删。
如果全局事务的任何一个事务分支失败了,那么全局事务就进入“回滚“流程,回滚时依据先前保存好数据镜像,将原来的数据回放回去。
如果全局回放成功,那么数据的一致性也就得到了保证,如果回放不成功,那么事务就进入异常。应对异常,可能需要重试,可能需要人工介入。
在需要增加分布式事务的模块加上相关依赖
1. ``
2. `io.seata `
3. `seata-spring-boot-starter `
4. `1.1.0 `
5. ` `
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`
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注解
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. `}`