[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"chapter-book:yj6y7X92":3,"chapter:1VXn98qP":86},{"id":4,"created_at":5,"updated_at":5,"code":6,"author_id":7,"title":8,"slug":9,"cover_theme_key":10,"visibility":11,"status":12,"sort_order":4,"favorite_count":13,"view_count":14,"author":15,"chapter_count":26,"word_count":27,"free_count":13,"is_favorite":24,"book_status":12,"unparted":28},2,"2023-12-30T11:23:15.697+08:00","yj6y7X92",1,"分布式事务Seata","分布式事务seata-2","default","public","published",0,3,{"id":7,"created_at":16,"updated_at":17,"code":18,"username":19,"display_name":20,"role":21,"avatar_url":22,"is_active":23,"is_banned":24,"follower_count":13,"following_count":14,"last_login_at":25},"2023-11-30T23:53:12.952+08:00","2026-10-20T16:16:54.352+08:00","Mg87g8Gk","1701359592888","大苹果","verified_author","\u002Fcuts\u002F17021220625513129.png",true,false,"2026-10-20T16:12:35+08:00",7,34684,[29,37,45,53,61,70,78],{"id":30,"created_at":31,"updated_at":31,"code":32,"author_id":7,"book_id":4,"slug":33,"article_id":34,"title":35,"sort_order":30,"content":36,"status":12},14,"2023-12-30T11:28:01.091+08:00","7WKl3Xmz","分布式事务简介-14",164,"分布式事务简介","### 分布式事务简介\n\n#### 基础概念\n\n基本概念：事务ACID\n\n事务：要么全部执行全部成功，要么全部失败\n\n分布式事务的概念\n\n分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上，且属于不同的应用，分布式事务需要保证这些操作要么全部成功，要么全部失败，本质上说，分布式事务就是为了保证不同数据库的数据一致性。\n\n### 分布式解决方案\n\n2PC即两阶段提交协议，是将整个事务流程分为两个阶段，P是指准备阶段，C是指提交阶段\n\n准备阶段：老板要求男方付款，男方付款，老板要求女方付款，女方付款\n\n提交阶段：老板出餐，两人纷纷落座。\n\n### seata是什么\n\nseata是一款开源分布式事务解决方案，致力于提高性能和简单易用的分布式事务服务，seata将为用户提供AT、TCC、SAGA和XA事务模式，为用户打造一站式的分布式解决方案。\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1703938238935_image.png)\n",{"id":38,"created_at":39,"updated_at":39,"code":40,"author_id":7,"book_id":4,"slug":41,"article_id":42,"title":43,"sort_order":38,"content":44,"status":12},19,"2024-01-16T05:41:46.22+08:00","1VXn98qP","分布式服务案例-19",167,"分布式服务案例","![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705383712699_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705384443704_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705388402982_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705415979856_image.png)\n",{"id":46,"created_at":47,"updated_at":47,"code":48,"author_id":7,"book_id":4,"slug":49,"article_id":50,"title":51,"sort_order":46,"content":52,"status":12},20,"2024-01-16T14:41:04.944+08:00","bM80zKAV","cap定理-20",168,"CAP定理","### CAP定理\n\n1998年，加州大学的计算机科学家Eric Brewer提出，分布式系统有三个指标：\n\n- Consistency（一致性）\n- Availability（可用性）\n- Partition toerance（分区容错性）\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416178892_image.png)\n\nEric Brewer说，分布式系统无法同时满足这三个指标。这个结论就叫做CAP定理\n\n### CAP定理-Partition tolerance\n\nConsistency（一致性）：用户访问分布式系统中的任意节点，得到的数据必须一致\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416370029_image.png)\n\nAvailability （可用性）：用户访问集群中的任意健康节点，必须能得到响应，而不是超时或拒绝\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416400308_image.png)\n\nPartition（分区）：因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接，形成独立分区。\nTolerance（容错）：在集群出现分区时，整个系统也要持续对外提供服务\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416325564_image.png)\n\n### 简述CAP定理内容\n\n- 分布式系统节点通过网络连接，一定会出现分区问题（P）\n\n- 当分区出现时，系统的一致性（C）和可用性（A）就无法同时满足\n\n- 思考：elasticsearch集群是CP还是AP？\n\n- ES集群出现分区时，故障节点会被剔除集群，数据分片会重新分配到其它节点，保证数据一致。因此是低可用性，高一致性，属于CP\n",{"id":54,"created_at":55,"updated_at":55,"code":56,"author_id":7,"book_id":4,"slug":57,"article_id":58,"title":59,"sort_order":54,"content":60,"status":12},21,"2024-01-16T14:50:04.88+08:00","A2KQj637","base理论-21",169,"Base理论","### BASE理论\n\n\nBASE理论是对CAP的一种解决思路，包含三个思想：\n\n- Basically Available （基本可用）：分布式系统在出现故障时，允许损失部分可用性，即保证核心可用。\n\n- Soft State（软状态）：在一定时间内，允许出现中间状态，比如临时的不一致状态。\n\n- Eventually Consistent（最终一致性）：虽然无法保证强一致性，但是在软状态结束后，最终达到数据一致。\n\n而分布式事务最大的问题是各个子事务的一致性问题，因此可以借鉴CAP定理和BASE理论：\n\n- AP模式：各子事务分别执行和提交，允许出现结果不一致，然后采用弥补措施恢复数据即可，实现最终一致。\n\n- CP模式：各个子事务执行后互相等待，同时提交，同时回滚，达成强一致。但事务等待过程中，处于弱可用状态。\n\n### 分布式事务模型\n\n解决分布式事务，各个子系统之间必须能感知到彼此的事务状态，才能保证状态一致，因此需要一个事务协调者来协调每一个事务的参与者（子系统事务）。\n这里的子系统事务，称为分支事务；有关联的各个分支事务在一起称为全局事务\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416711917_image.png)\n\n#### 简述BASE理论三个思想：\n\n- 基本可用\n\n- 软状态\n- 最终一致\n\n#### 解决分布式事务的思想和模型：\n\n- 全局事务：整个分布式事务\n\n- 分支事务：分布式事务中包含的每个子系统的事务\n\n- 最终一致思想：各分支事务分别执行并提交，如果有不一致的情况，再想办法恢复数据\n\n- 强一致思想：各分支事务执行完业务不要提交，等待彼此结果。而后统一提交或回滚\n",{"id":62,"created_at":63,"updated_at":64,"code":65,"author_id":7,"book_id":4,"slug":66,"article_id":67,"title":68,"sort_order":62,"content":69,"status":12},22,"2024-01-16T14:53:44.549+08:00","2024-01-16T15:14:08.996+08:00","5E65m6zm","seata架构部署微服务集成-22",170,"Seata架构、部署、微服务集成","# Seata的架构\n\n## Seata\n\nSeata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务，为用户打造一站式的分布式解决方案。\n官网地址：http:\u002F\u002Fseata.io\u002F，其中的文档、播客中提供了大量的使用说明、源码分析。\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705416912923_image.png)\n\n## Seata事务管理中有三个重要的角色：\n\n- TC (Transaction Coordinator) - 事务协调者：维护全局和分支事务的状态，协调全局事务提交或回滚。\n- TM (Transaction Manager) - 事务管理器：定义全局事务的范围、开始全局事务、提交或回滚全局事务。\n- RM (Resource Manager) - 资源管理器：管理分支事务处理的资源，与TC交谈以注册分支事务和报告分支事务的状态，并驱动分支事务提交或回滚。\n\n  ![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417099098_image.png)\n\n## Seata提供了四种不同的分布式事务解决方案：\n\n- XA模式：强一致性分阶段事务模式，牺牲了一定的可用性，无业务侵入\n- TCC模式：最终一致的分阶段事务模式，有业务侵入\n- AT模式：最终一致的分阶段事务模式，无业务侵入，也是Seata的默认模式\n- SAGA模式：长事务模式，有业务侵入\n\n# 部署TC服务\n\n## seata的部署和集成\n\n### 一、部署Seata的tc-server\n\n#### 1.下载\n\n首先我们要下载seata-server包，地址在[http](http:\u002F\u002Fseata.io\u002Fzh-cn\u002Fblog\u002Fdownload.html)[:\u002F\u002Fseata.io\u002Fzh-cn\u002Fblog\u002Fdownload](http:\u002F\u002Fseata.io\u002Fzh-cn\u002Fblog\u002Fdownload.html)[.](http:\u002F\u002Fseata.io\u002Fzh-cn\u002Fblog\u002Fdownload.html)[html](http:\u002F\u002Fseata.io\u002Fzh-cn\u002Fblog\u002Fdownload.html)\n\n#### 2.解压\n\n在非中文目录解压缩这个zip包，其目录结构如下：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417360200_image.png)\n\n#### 3.修改配置\n\n修改conf目录下的registry.conf文件：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417376132_image.png)\n\n内容如下：\n\n```properties\nregistry {\n  # tc服务的注册中心类，这里选择nacos，也可以是eureka、zookeeper等\n  type = \"nacos\"\n\n  nacos {\n    # seata tc 服务注册到 nacos的服务名称，可以自定义\n    application = \"seata-tc-server\"\n    serverAddr = \"127.0.0.1:8848\"\n    group = \"DEFAULT_GROUP\"\n    namespace = \"\"\n    cluster = \"SH\"\n    username = \"nacos\"\n    password = \"nacos\"\n  }\n}\n\nconfig {\n  # 读取tc服务端的配置文件的方式，这里是从nacos配置中心读取，这样如果tc是集群，可以共享配置\n  type = \"nacos\"\n  # 配置nacos地址等信息\n  nacos {\n    serverAddr = \"127.0.0.1:8848\"\n    namespace = \"\"\n    group = \"SEATA_GROUP\"\n    username = \"nacos\"\n    password = \"nacos\"\n    dataId = \"seataServer.properties\"\n  }\n}\n```\n\n#### 4.在nacos添加配置\n\n特别注意，为了让tc服务的集群可以共享配置，我们选择了nacos作为统一配置中心。因此服务端配置文件seataServer.properties文件需要在nacos中配好。\n\n格式如下：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417403633_image.png)\n\n配置内容如下：\n\n```properties\n# 数据存储方式，db代表数据库\nstore.mode=db\nstore.db.datasource=druid\nstore.db.dbType=mysql\nstore.db.driverClassName=com.mysql.jdbc.Driver\nstore.db.url=jdbc:mysql:\u002F\u002F127.0.0.1:3306\u002Fseata?useUnicode=true&rewriteBatchedStatements=true\nstore.db.user=root\nstore.db.password=123\nstore.db.minConn=5\nstore.db.maxConn=30\nstore.db.globalTable=global_table\nstore.db.branchTable=branch_table\nstore.db.queryLimit=100\nstore.db.lockTable=lock_table\nstore.db.maxWait=5000\n# 事务、日志等配置\nserver.recovery.committingRetryPeriod=1000\nserver.recovery.asynCommittingRetryPeriod=1000\nserver.recovery.rollbackingRetryPeriod=1000\nserver.recovery.timeoutRetryPeriod=1000\nserver.maxCommitRetryTimeout=-1\nserver.maxRollbackRetryTimeout=-1\nserver.rollbackRetryTimeoutUnlockEnable=false\nserver.undo.logSaveDays=7\nserver.undo.logDeletePeriod=86400000\n\n# 客户端与服务端传输方式\ntransport.serialization=seata\ntransport.compressor=none\n# 关闭metrics功能，提高性能\nmetrics.enabled=false\nmetrics.registryType=compact\nmetrics.exporterList=prometheus\nmetrics.exporterPrometheusPort=9898\n```\n\n**其中的数据库地址、用户名、密码都需要修改成你自己的数据库信息。**\n\n#### 5.创建数据库表\n\n特别注意：tc服务在管理分布式事务时，需要记录事务相关数据到数据库中，你需要提前创建好这些表。\n\n新建一个名为seata的数据库：\n\n```sql\ncreate database seata CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;\n```\n\n这些表主要记录全局事务、分支事务、全局锁信息：\n\n```sql\nSET NAMES utf8mb4;\nSET FOREIGN_KEY_CHECKS = 0;\n\n-- ----------------------------\n-- 分支事务表\n-- ----------------------------\nDROP TABLE IF EXISTS `branch_table`;\nCREATE TABLE `branch_table`  (\n  `branch_id` bigint(20) NOT NULL,\n  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `transaction_id` bigint(20) NULL DEFAULT NULL,\n  `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `status` tinyint(4) NULL DEFAULT NULL,\n  `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `gmt_create` datetime(6) NULL DEFAULT NULL,\n  `gmt_modified` datetime(6) NULL DEFAULT NULL,\n  PRIMARY KEY (`branch_id`) USING BTREE,\n  INDEX `idx_xid`(`xid`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- 全局事务表\n-- ----------------------------\nDROP TABLE IF EXISTS `global_table`;\nCREATE TABLE `global_table`  (\n  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `transaction_id` bigint(20) NULL DEFAULT NULL,\n  `status` tinyint(4) NOT NULL,\n  `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `timeout` int(11) NULL DEFAULT NULL,\n  `begin_time` bigint(20) NULL DEFAULT NULL,\n  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `gmt_create` datetime NULL DEFAULT NULL,\n  `gmt_modified` datetime NULL DEFAULT NULL,\n  PRIMARY KEY (`xid`) USING BTREE,\n  INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,\n  INDEX `idx_transaction_id`(`transaction_id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\nSET FOREIGN_KEY_CHECKS = 1;\n```\n\n#### 6.启动TC服务\n\n进入bin目录，运行其中的seata-server.bat即可：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417743488_image.png)\n\n启动成功后，seata-server应该已经注册到nacos注册中心了。\n\n打开浏览器，访问nacos地址：http:\u002F\u002Flocalhost:8848，然后进入服务列表页面，可以看到seata-tc-server的信息：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417754715_image.png)\n\n### 二、微服务集成seata\n\n#### 1.引入依赖\n\n首先，我们需要在微服务中引入seata依赖：\n\n```xml\n\u003Cdependency>\n    \u003CgroupId>com.alibaba.cloud\u003C\u002FgroupId>\n    \u003CartifactId>spring-cloud-starter-alibaba-seata\u003C\u002FartifactId>\n    \u003Cexclusions>\n        \u003C!--版本较低，1.3.0，因此排除-->\n        \u003Cexclusion>\n            \u003CartifactId>seata-spring-boot-starter\u003C\u002FartifactId>\n            \u003CgroupId>io.seata\u003C\u002FgroupId>\n        \u003C\u002Fexclusion>\n    \u003C\u002Fexclusions>\n\u003C\u002Fdependency>\n\u003C!--seata starter 采用1.4.2版本-->\n\u003Cdependency>\n    \u003CgroupId>io.seata\u003C\u002FgroupId>\n    \u003CartifactId>seata-spring-boot-starter\u003C\u002FartifactId>\n    \u003Cversion>${seata.version}\u003C\u002Fversion>\n\u003C\u002Fdependency>\n```\n\n#### 2.修改配置文件\n\n需要修改application.yml文件，添加一些配置：\n\n```yaml\nseata:\n  registry: # TC服务注册中心的配置，微服务根据这些信息去注册中心获取tc服务地址\n    # 参考tc服务自己的registry.conf中的配置\n    type: nacos\n    nacos: # tc\n      server-addr: 127.0.0.1:8848\n      namespace: \"\"\n      group: DEFAULT_GROUP\n      application: seata-tc-server # tc服务在nacos中的服务名称\n      cluster: SH\n  tx-service-group: seata-demo # 事务组，根据这个获取tc服务的cluster名称\n  service:\n    vgroup-mapping: # 事务组与TC服务cluster的映射关系\n      seata-demo: SH\n```\n\n### 三、TC服务的高可用和异地容灾\n\n#### 1.模拟异地容灾的TC集群\n\n计划启动两台seata的tc服务节点：\n\n\n| 节点名称 | ip地址    | 端口号 | 集群名称 |\n| -------- | --------- | ------ | -------- |\n| seata    | 127.0.0.1 | 8091   | SH       |\n| seata2   | 127.0.0.1 | 8092   | HZ       |\n\n之前我们已经启动了一台seata服务，端口是8091，集群名为SH。\n\n现在，将seata目录复制一份，起名为seata2\n\n修改seata2\u002Fconf\u002Fregistry.conf内容如下：\n\n```nginx\nregistry {\n  # tc服务的注册中心类，这里选择nacos，也可以是eureka、zookeeper等\n  type = \"nacos\"\n\n  nacos {\n    # seata tc 服务注册到 nacos的服务名称，可以自定义\n    application = \"seata-tc-server\"\n    serverAddr = \"127.0.0.1:8848\"\n    group = \"DEFAULT_GROUP\"\n    namespace = \"\"\n    cluster = \"HZ\"\n    username = \"nacos\"\n    password = \"nacos\"\n  }\n}\n\nconfig {\n  # 读取tc服务端的配置文件的方式，这里是从nacos配置中心读取，这样如果tc是集群，可以共享配置\n  type = \"nacos\"\n  # 配置nacos地址等信息\n  nacos {\n    serverAddr = \"127.0.0.1:8848\"\n    namespace = \"\"\n    group = \"SEATA_GROUP\"\n    username = \"nacos\"\n    password = \"nacos\"\n    dataId = \"seataServer.properties\"\n  }\n}\n```\n\n进入seata2\u002Fbin目录，然后运行命令：\n\n```powershell\nseata-server.bat -p 8092\n```\n\n打开nacos控制台，查看服务列表：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417779043_image.png)\n\n点进详情查看：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417791672_image.png)\n\n#### 2.将事务组映射配置到nacos\n\n[nacos安装与配置](https:\u002F\u002Fnacos.io\u002Fdocs\u002Flatest\u002Fwhat-is-nacos\u002F)\n\n接下来，我们需要将tx-service-group与cluster的映射关系都配置到nacos配置中心。\n\n新建一个配置：\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705417799747_image.png)\n\n配置的内容如下：\n\n```properties\n# 事务组映射关系\nservice.vgroupMapping.seata-demo=SH\n\nservice.enableDegrade=false\nservice.disableGlobalTransaction=false\n# 与TC服务的通信配置\ntransport.type=TCP\ntransport.server=NIO\ntransport.heartbeat=true\ntransport.enableClientBatchSendRequest=false\ntransport.threadFactory.bossThreadPrefix=NettyBoss\ntransport.threadFactory.workerThreadPrefix=NettyServerNIOWorker\ntransport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler\ntransport.threadFactory.shareBossWorker=false\ntransport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector\ntransport.threadFactory.clientSelectorThreadSize=1\ntransport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread\ntransport.threadFactory.bossThreadSize=1\ntransport.threadFactory.workerThreadSize=default\ntransport.shutdown.wait=3\n# RM配置\nclient.rm.asyncCommitBufferLimit=10000\nclient.rm.lock.retryInterval=10\nclient.rm.lock.retryTimes=30\nclient.rm.lock.retryPolicyBranchRollbackOnConflict=true\nclient.rm.reportRetryCount=5\nclient.rm.tableMetaCheckEnable=false\nclient.rm.tableMetaCheckerInterval=60000\nclient.rm.sqlParserType=druid\nclient.rm.reportSuccessEnable=false\nclient.rm.sagaBranchRegisterEnable=false\n# TM配置\nclient.tm.commitRetryCount=5\nclient.tm.rollbackRetryCount=5\nclient.tm.defaultGlobalTransactionTimeout=60000\nclient.tm.degradeCheck=false\nclient.tm.degradeCheckAllowTimes=10\nclient.tm.degradeCheckPeriod=2000\n\n# undo日志配置\nclient.undo.dataValidation=true\nclient.undo.logSerialization=jackson\nclient.undo.onlyCareUpdateColumns=true\nclient.undo.logTable=undo_log\nclient.undo.compress.enable=true\nclient.undo.compress.type=zip\nclient.undo.compress.threshold=64k\nclient.log.exceptionRate=100\n```\n\n#### 3.微服务读取nacos配置\n\n接下来，需要修改每一个微服务的application.yml文件，让微服务读取nacos中的client.properties文件：\n\n```yaml\nseata:\n  config:\n    type: nacos\n    nacos:\n      server-addr: 127.0.0.1:8848\n      username: nacos\n      password: nacos\n      group: SEATA_GROUP\n      data-id: client.properties\n```\n\n重启微服务，现在微服务到底是连接tc的SH集群，还是tc的HZ集群，都统一由nacos的client.properties来决定了。\n\n### nacos服务名称组成包括？\n\nnamespace + group + serviceName + cluster\n\n### seata客户端获取tc的cluster名称方式？\n\n以tx-group-service的值为key到vgroupMapping中查找\n",{"id":71,"created_at":72,"updated_at":72,"code":73,"author_id":7,"book_id":4,"slug":74,"article_id":75,"title":76,"sort_order":71,"content":77,"status":12},23,"2024-01-17T12:52:37.318+08:00","vPKwa8qR","docker部署seata-23",171,"Docker部署seata","### 下载seata-server\n\n[seata-server](https:\u002F\u002Fgithub.com\u002Fapache\u002Fincubator-seata\u002Freleases\u002Fdownload\u002Fv2.0.0\u002Fseata-server-2.0.0.tar.gz)\n\n### 解压部署\n\n目录结构\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705498607177_image.png)\n\n修改配置文件（conf\u002Fapplication.yml）\n\n```yaml\nserver:\n  port: 7091\n\nspring:\n  application:\n    name: seata-server\n  cloud:\n    nacos:\n      discovery:\n        server-addr: nocas-ip:8848\n        ip: ${HOST:192.168.40.167}\n        port: 8081\nlogging:\n  config: classpath:logback-spring.xml\n  file:\n    path: ${log.home:${user.home}\u002Flogs\u002Fseata}\n  extend:\n    logstash-appender:\n      destination: 127.0.0.1:4560\n    kafka-appender:\n      bootstrap-servers: 127.0.0.1:9092\n      topic: logback_to_logstash\n\nconsole:\n  user:\n    username: seata\n    password: seata\nseata:\n  config:\n    # support: nacos, consul, apollo, zk, etcd3\n    type: file\n  registry:\n    # support: nacos, eureka, redis, zk, consul, etcd3, sofa\n    type: nacos\n    nacos: # tc\n      server-addr: nocas-ip:8848\n      namespace: \"\"\n      group: DEFAULT_GROUP\n      application: seata-tc-server # tc服务在nacos中的服务名称\n      cluster: SH\n  store:\n    # support: file 、 db 、 redis 、 raft\n    mode: file\n  #  server:\n  #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'\n  security:\n    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017\n    tokenValidityInMilliseconds: 1800000\n    ignore:\n      urls: \u002F,\u002F**\u002F*.css,\u002F**\u002F*.js,\u002F**\u002F*.html,\u002F**\u002F*.map,\u002F**\u002F*.svg,\u002F**\u002F*.png,\u002F**\u002F*.jpeg,\u002F**\u002F*.ico,\u002Fapi\u002Fv1\u002Fauth\u002Flogin,\u002Fmetadata\u002Fv1\u002F**\n\n```\n\n```\ntar -zxvf seata-server-2.0.0.tar.gz\ncd seata\ndocker build . --tag seata:v1.0\n# 指定与nacos 同网络\n# SEATA_IP 指定公网ip\ndocker run -d --network example_default --add-host=nocas-ip:192.168.40.167 --name seata-server -p 8091:8091 -p 7091:7091 -e SEATA_IP=192.168.40.167 seata:v1.0\n# 查看日志\ndocker logs -f seata-server\n```\n\n客户端数据库创建undo_log表\n\n````sql\n\nCREATE TABLE `undo_log` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `branch_id` bigint(20) NOT NULL,\n  `xid` varchar(100) NOT NULL,\n  `context` varchar(128) NOT NULL,\n  `rollback_info` longblob NOT NULL,\n  `log_status` int(11) NOT NULL,\n  `log_created` datetime NOT NULL,\n  `log_modified` datetime NOT NULL,\n  `ext` varchar(100) DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;\n````\n\n### docker-compose部署seata\n\n- docker-compose.yml\n\n```yaml\nversion: \"3.1\"\nservices:\n  seata-server:\n     # 镜像\n    image: seataio\u002Fseata-server:1.5.2\n    ports:\n\t# 宿主端口：容器端口\n      - \"7092:7091\"\n      - \"8092:8092\"\n     # 环境变量\n    environment:\n      - STORE_MODE=db\n      # 以SEATA_IP作为host注册seata server\n      - SEATA_IP=192.168.40.167\n      - SEATA_PORT=8092\n      - STORE_MODE=file\n    # 目录挂载\n    volumes:\n      - \"\u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FShanghai:\u002Fetc\u002Flocaltime\"        #设置系统时区\n      - \"\u002Fusr\u002Fshare\u002Fzoneinfo\u002FAsia\u002FShanghai:\u002Fetc\u002Ftimezone\"  #设置时区\n      # 假设我们通过docker cp命令把资源文件拷贝到相对路径`.\u002Fseata-server\u002Fresources`中\n      # 如有问题，请阅读上面的[注意事项]以及[使用自定义配置文件]\n      #- \".\u002Fseata-server\u002Fresources:\u002Fseata-server\u002Fresources\"\n      - \".\u002Fseata-server\u002Fresources:\u002Fseata-server\u002Fconfig\"\n    # 指定网络\n    networks: \n      - example_default\n# 指定已有网络\nnetworks:\n  example_default:\n    external: true\n```\n\n- application.yml\n\n```yaml\nserver:\n  port: 7091\ndebug: false\nspring:\n  application:\n    name: seata-server\n  cloud:\n    nacos:\n      server-addr: 172.22.0.2:8848\nseata:\n  config:\n    # support: nacos, consul, apollo, zk, etcd3\n    type: file\n    # nacos:\n    #   server-addr: 172.22.0.2:8848\n    #   namespace: \n    #   group: DEFAULT_GROUP\n    #   username: nacos\n    #   password: nacos\n    #   data-id: seataServer.properties\n  store:\n    # support: file 、 db 、 redis 、 raft\n    mode: file\n  security:\n    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017\n    tokenValidityInMilliseconds: 1800000\n    ignore:\n      urls: \u002F,\u002F**\u002F*.css,\u002F**\u002F*.js,\u002F**\u002F*.html,\u002F**\u002F*.map,\u002F**\u002F*.svg,\u002F**\u002F*.png,\u002F**\u002F*.jpeg,\u002F**\u002F*.ico,\u002Fapi\u002Fv1\u002Fauth\u002Flogin,\u002Fmetadata\u002Fv1\u002F**\n  registry: # TC服务注册中心的配置，微服务根据这些信息去注册中心获取tc服务地址\n    # 参考tc服务自己的registry.conf中的配置\n    type: nacos\n    nacos: # tc\n      server-addr: 172.22.0.2:8848\n      namespace: \"\"\n      group: DEFAULT_GROUP\n      application: seata-tc-server # tc服务在nacos中的服务名称\n      cluster: HZ\n```\n\n- 部署\n\n```bash\ndocker compose up -d\n```\n",{"id":79,"created_at":80,"updated_at":80,"code":81,"author_id":7,"book_id":4,"slug":82,"article_id":83,"title":84,"sort_order":79,"content":85,"status":12},24,"2024-01-18T01:09:42.83+08:00","zBKVp849","事务模式-24",172,"事务模式","## XA模式\n\n### XA模式原理\n\nXA 规范 是 X\u002FOpen 组织定义的分布式事务处理（DTP，Distributed Transaction Processing）标准，XA 规范 描述了全局的TM与局部的RM之间的接口，几乎所有主流的数据库都对 XA 规范 提供了支持。\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705540383601_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705540403926_image.png)\n\n### seata的XA模式\n\nseata的XA模式做了一些调整，但大体相似：\n\nRM一阶段的工作：\n\n① 注册分支事务到TC\n\n② 执行分支业务sql但不提交\n\n③ 报告执行状态到TC\n\nTC二阶段的工作：\n\n- TC检测各分支事务执行状态\n\n  a. 如果都成功，通知所有RM提交事务\n\n  b. 如果有失败，通知所有RM回滚事务\n\nRM二阶段的工作：\n\n- 接收TC指令，提交或回滚事务\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705540592966_image.png)\n\n### XA模式的优点是什么？\n\n- 事务的强一致性，满足ACID原则。\n- 常用数据库都支持，实现简单，并且没有代码侵入\n\n### XA模式的缺点是什么？\n\n- 因为一阶段需要锁定数据库资源，等待二阶段结束才释放，性能较差\n- 依赖关系型数据库实现事务\n\n### 实现XA模式\n\nSeata的starter已经完成了XA模式的自动装配，实现非常简单，步骤如下：\n\n1. 修改application.yml文件（每个参与事务的微服务），开启XA模式：\n   ```yml\n   seata:\n     data-source-proxy-mode: XA # 开启数据源代理的XA模式\n\n   ```\n2. 给发起全局事务的入口方法添加@GlobalTransactional注解，本例中是OrderServiceImpl中的create方法：\n   ```\n   @Override\n   @GlobalTransactional\n   public Long create(Order order) {\n       \u002F\u002F 创建订单\n       orderMapper.insert(order);\n       \u002F\u002F 扣余额 ...略 \n       \u002F\u002F 扣减库存 ...略\n       return order.getId();\n   }\n\n   ```\n3. 重启服务并测试\n\n## AT模式\n\n### AT模式原理\n\nAT模式同样是分阶段提交的事务模型，不过缺弥补了XA模型中资源锁定周期过长的缺陷。\n\n阶段一RM的工作：\n\n- 注册分支事务\n\n- 记录undo-log（数据快照）\n\n- 执行业务sql并提交\n\n- 报告事务状态\n\n阶段二提交时RM的工作：\n\n- 删除undo-log即可\n\n阶段二回滚时RM的工作：\n\n- 根据undo-log恢复数据到更新前\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705541101364_image.png)\n\n例如，一个分支业务的SQL是这样的：update tb\\_account set money = money - 10 where id = 1\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705541335495_image.png)\n\n### 简述AT模式与XA模式最大的区别是什么？\n\n- XA模式一阶段不提交事务，锁定资源；AT模式一阶段直接提交，不锁定资源。\n\n- XA模式依赖数据库机制实现回滚；AT模式利用数据快照实现数据回滚。\n- XA模式强一致；AT模式最终一致\n\n### AT模式的脏写问题\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705541672885_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705542762870_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705542799014_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705542854856_image.png)\n\n\n### AT模式的优点：\n\n- 一阶段完成直接提交事务，释放数据库资源，性能比较好\n\n- 利用全局锁实现读写隔离\n\n- 没有代码侵入，框架自动完成回滚和提交\n\n### AT模式的缺点：\n\n- 两阶段之间属于软状态，属于最终一致\n- 框架的快照功能会影响性能，但比XA模式要好很多\n\n### 实现AT模式\n\n\nAT模式中的快照生成、回滚等动作都是由框架自动完成，没有任何代码侵入，因此实现非常简单。\n\n1. 导入课前资料提供的Sql文件：seata-at.sql，其中lock\\_table导入到TC服务关联的数据库，undo\\_log表导入到微服务关联的数据库：\n\n```sql\nSET NAMES utf8mb4;\nSET FOREIGN_KEY_CHECKS = 0;\n\n-- ----------------------------\n-- Table structure for undo_log\n-- ----------------------------\nDROP TABLE IF EXISTS `undo_log`;\nCREATE TABLE `undo_log`  (\n  `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',\n  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',\n  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',\n  `rollback_info` longblob NOT NULL COMMENT 'rollback info',\n  `log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',\n  `log_created` datetime(6) NOT NULL COMMENT 'create datetime',\n  `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',\n  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- Records of undo_log\n-- ----------------------------\n\n\n\n-- ----------------------------\n-- Table structure for lock_table\n-- ----------------------------\nDROP TABLE IF EXISTS `lock_table`;\nCREATE TABLE `lock_table`  (\n  `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `transaction_id` bigint(20) NULL DEFAULT NULL,\n  `branch_id` bigint(20) NOT NULL,\n  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `gmt_create` datetime NULL DEFAULT NULL,\n  `gmt_modified` datetime NULL DEFAULT NULL,\n  PRIMARY KEY (`row_key`) USING BTREE,\n  INDEX `idx_branch_id`(`branch_id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n\nSET FOREIGN_KEY_CHECKS = 1;\n```\n\n2. 修改application.yml文件，将事务模式修改为AT模式即可：\n\n```yaml\nseata:\n  data-source-proxy-mode: AT # 开启数据源代理的AT模式\n\n```\n\n3. 重启服务并测试\n\n## TCC模式\n\n### TCC模式原理\n\nTCC模式与AT模式非常相似，每阶段都是独立事务，不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法：\n\n- Try：资源的检测和预留；\n- Confirm：完成资源操作业务；要求 Try 成功 Confirm 一定要能成功。\n- Cancel：预留资源释放，可以理解为try的反向操作。\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543242565_image.png)\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543285924_image.png)\n\n\n### TCC模式的每个阶段是做什么的？\n\n- Try：资源检查和预留\n\n- Confirm：业务执行和提交\n\n- Cancel：预留资源的释放\n\n### TCC的优点是什么？\n\n- 一阶段完成直接提交事务，释放数据库资源，性能好\n\n- 相比AT模型，无需生成快照，无需使用全局锁，性能最强\n\n- 不依赖数据库事务，而是依赖补偿操作，可以用于非事务型数据库\n\n### TCC的缺点是什么？\n\n- 有代码侵入，需要人为编写try、Confirm和Cancel接口，太麻烦\n\n- 软状态，事务是最终一致\n- 需要考虑Confirm和Cancel的失败情况，做好幂等处理\n\n### TCC的空回滚和业务悬挂\n\n当某分支事务的try阶段阻塞时，可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作，这时cancel不能做回滚，就是空回滚。\n\n对于已经空回滚的业务，如果以后继续执行try，就永远不可能confirm或cancel，这就是业务悬挂。应当阻止执行空回滚后的try操作，避免悬挂\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543402458_image.png)\n\n### 业务分析\n\n为了实现空回滚、防止业务悬挂，以及幂等性要求。我们必须在数据库记录冻结金额的同时，记录当前事务id和执行状态，为此我们设计了一张表\n\n```sql\nCREATE TABLE `account_freeze_tbl` (\n  `xid` varchar(128) NOT NULL,\n  `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',\n  `freeze_money` int(11) unsigned DEFAULT '0' COMMENT '冻结金额',\n  `state` int(1) DEFAULT NULL COMMENT '事务状态，0:try，1:confirm，2:cancel',\n  PRIMARY KEY (`xid`) USING BTREE\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;\n\n```\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543499688_image.png)\n\n### 声明TCC接口\n\nTCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明，语法如下：\n\n```java\n@LocalTCC\npublic interface TCCService {\n    \u002F**\n     * Try逻辑，@TwoPhaseBusinessAction中的name属性要与当前方法名一致，用于指定Try逻辑对应的方法\n     *\u002F\n    @TwoPhaseBusinessAction(name = \"prepare\", commitMethod = \"confirm\", rollbackMethod = \"cancel\")\n    void prepare(@BusinessActionContextParameter(paramName = \"param\") String param);\n    \u002F**\n     * 二阶段confirm确认方法、可以另命名，但要保证与commitMethod一致 \n     *\n     * @param context 上下文,可以传递try方法的参数\n     * @return boolean 执行是否成功\n     *\u002F\n    boolean confirm (BusinessActionContext context);\n    \u002F**\n     * 二阶段回滚方法，要保证与rollbackMethod一致\n     *\u002F\n    boolean cancel (BusinessActionContext context);\n}\n\n```\n\n## SAGA模式\n\nSaga模式是SEATA提供的长事务解决方案。也分为两个阶段：\n\n- 一阶段：直接提交本地事务\n\n- 二阶段：成功则什么都不做；失败则通过编写补偿业务来回滚\n\nSaga模式优点：\n\n- 事务参与者可以基于事件驱动实现异步调用，吞吐高\n\n- 一阶段直接提交事务，无锁，性能好\n\n- 不用编写TCC中的三个阶段，实现简单\n\n缺点：\n\n- 软状态持续时间不确定，时效性差\n- 没有锁，没有事务隔离，会有脏写\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543679810_image.png)\n\n### 四种模式\n\n![image.png](http:\u002F\u002Fe.cdn.go90.cn\u002Fokgoes\u002Fblog\u002Feditor1705543705165_image.png)\n\n\n|          | XA                             | AT                                           | TCC                                                       | SAGA                                                                                       |\n| -------- | ------------------------------ | -------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------ |\n| 一致性   | 强一致                         | 弱一致                                       | 弱一致                                                    | 最终一致                                                                                   |\n| 隔离性   | 完全隔离                       | 基于全局锁隔离                               | 基于资源预留隔离                                          | 无隔离                                                                                     |\n| 代码侵入 | 无                             | 无                                           | 有，要编写三个接口                                        | 有，要编写状态机和补偿业务                                                                 |\n| 性能     | 差                             | 好                                           | 非常好                                                    | 非常好                                                                                     |\n| 场景     | 对一致性、隔离性有高要求的业务 | 基于关系型数据库的大多数分布式事务场景都可以 | •对性能要求较高的事务。 •有非关系型数据库要参与的事务。 | •业务流程长、业务流程多 •参与者包含其它公司或遗留系统服务，无法提供TCC模式要求的三个接口 |\n",{"id":38,"created_at":39,"updated_at":39,"code":40,"author_id":7,"book_id":4,"slug":41,"article_id":42,"title":43,"sort_order":38,"content":44,"status":12}]