dede网站百度统计怎么做,潍坊网站的公司电话,建设部执业考试网站,河南seo和网络推广来都来了点个赞收藏一下在走呗~~#x1f339;#x1f339;玫瑰 一、Seata是什么 Seata#xff08;Simple Extensible Autonomous Transaction Architecture#xff0c;简单可扩展自治事务框架#xff09;是一种分布式事务解决方案#xff0c;旨在解决分布式系统中的事务… 来都来了点个赞收藏一下在走呗~~玫瑰 一、Seata是什么 SeataSimple Extensible Autonomous Transaction Architecture简单可扩展自治事务框架是一种分布式事务解决方案旨在解决分布式系统中的事务一致性问题。它为开发者提供了一种简单而可扩展的方式来管理和协调分布式事务。 1.1 为什么需要Seata
我们知道在数据库中是可以保证事务的ACID四大特性的但是我们现在做的项目如果是微服务项目微服务的项目可能会涉及到多个服务涉及到多个数据库那我们这个时候就要想一下我们是否还可以直接的使用Spring中提供给我们的Transactional只可以保证到单体项目的情况下是可以运行成功的但是在微服务的项目下你也不可能在本地就知道别的服务下的是否运行成功所以这个时候就需要一个中间件来帮我们做这个事情告诉我们其他服务下是否执行成功这只是一种策略所以这也就是Seata帮我们做的事情。 仓储服务对给定的商品扣除仓储数量。订单服务根据采购需求创建订单。帐户服务从用户帐户中扣除余额。 就比如我有上面这三个服务我现在需要创建订单发现用户余额是够的我就先把用户的余额扣掉了但是到仓储服务中去扣件库存的时候发现其实库存不够但是这个时候余额已经扣掉了我们也不可以让用户余额再回滚回去。 1.2 Seata核心组件
Seata 的架构中包含三个主要角色 Transaction Coordinator (TC) - 事务协调者负责全局事务的协调和管理协调各个参与者的事务操作并最终决定全局事务的提交或回滚。Transaction Manager (TM) - 事务管理器负责全局事务的启动、提交和回滚定义全局事务的范围。Resource Manager (RM) - 资源管理器负责管理本地事务的资源如数据库、消息队列等与 TC 进行通信并执行 TC 指令来保证本地事务的一致性 1.3 Seata事务模式
1.3.1 XA 模式
XA 模式是 Seata 中的一种事务模式基于 X/Open XA 协议实现。它采用两阶段提交2PC的机制来保证分布式事务的一致性。
第一阶段准备阶段Prepare Phase
RM 注册分支事务到 TC资源管理器RM将本地事务注册到事务协调者TC。RM 执行分支业务的 SQL 但不提交RM 执行相关的业务操作但不提交事务。RM 报告执行状态到 TCRM 将执行结果报告给 TC。
第二阶段提交/回滚阶段Commit/Rollback Phase
TC 检测各分支事务状态TC 检查所有分支事务的状态判断是否所有事务都已准备好提交。TC 发送提交或回滚指令根据检测结果TC 向所有 RM 发送提交或回滚的指令。RM 执行提交或回滚操作RM 根据 TC 的指令执行相应的提交或回滚操作。 1.3.2 AT 模式
AT 模式自动事务模式是一种无侵入的分布式事务解决方案基于 XA 协议演进而来。
第一阶段业务执行阶段
TM 开启全局事务事务管理器TM向 TC 注册全局事务记录。RM 执行业务操作资源管理器RM执行业务操作生成 undo log用于回滚。RM 提交本地事务RM 提交本地事务但不释放资源。
第二阶段全局提交/回滚阶段
TM 提交全局事务TM 向 TC 发送全局事务提交请求。TC 确认全局事务状态TC 确认所有分支事务的状态决定是否提交全局事务。TC 发送提交或回滚指令TC 向所有 RM 发送提交或回滚的指令。RM 执行最终的提交或回滚操作RM 根据 TC 的指令执行最终的提交或回滚操作并释放资源。 当然我们也可以想到这个地方可能会出现一个问题那就是如果当我们提交提交sql之后这个时候又来了一个sql语句去修改数据库中的数据那不是会导致一个问题就是可能会出现脏读的问题对于这个问题Seata也给我们解决的方法。
写隔离机制
一阶段本地事务提交前需要确保先拿到 全局锁 。拿不到 全局锁 不能提交本地事务。拿 全局锁 的尝试被限制在一定范围内超出范围将放弃并回滚本地事务释放本地锁。
以一个示例来说明 两个全局事务 tx1 和 tx2分别对 a 表的 m 字段进行更新操作m 的初始值 1000。 tx1 先开始开启本地事务拿到本地锁更新操作 m 1000 - 100 900。本地事务提交前先拿到该记录的 全局锁 本地提交释放本地锁。 tx2 后开始开启本地事务拿到本地锁更新操作 m 900 - 100 800。本地事务提交前尝试拿该记录的 全局锁 tx1 全局提交前该记录的全局锁被 tx1 持有tx2 需要重试等待 全局锁 。 tx1 二阶段全局提交释放 全局锁 。tx2 拿到 全局锁 提交本地事务。 如果 tx1 的二阶段全局回滚则 tx1 需要重新获取该数据的本地锁进行反向补偿的更新操作实现分支的回滚。
此时如果 tx2 仍在等待该数据的 全局锁同时持有本地锁则 tx1 的分支回滚会失败。分支的回滚会一直重试直到 tx2 的 全局锁 等锁超时放弃 全局锁 并回滚本地事务释放本地锁tx1 的分支回滚最终成功。
因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的所以不会发生 脏写 的问题。
1.3.3 TCC 模式
TCC 模式Try-Confirm-Cancel 模式是一种基于补偿机制的分布式事务解决方案。
第一阶段Try 阶段 TM 开启全局事务TM 向 TC 注册全局事务记录。 RM 执行 Try 操作资源管理器RM执行 Try 操作尝试预留资源并返回操作结果。
第二阶段Confirm 阶段 TM 确认全局事务TM 根据 Try 阶段的结果决定是否继续执行 Confirm 操作。 RM 执行 Confirm 操作如果 Try 操作成功RM 执行 Confirm 操作正式提交事务。
第三阶段Cancel 阶段 TM 取消全局事务如果 Try 操作失败TM 向 TC 发送取消请求。 RM 执行 Cancel 操作RM 执行 Cancel 操作回滚 Try 阶段的操作释放预留的资源。 1.3.4. SAGA 模式
SAGA 模式是一种基于补偿机制的分布式事务解决方案将分布式事务拆分为一系列的本地事务。
第一阶段执行正向操作 TM 开启全局事务TM 向 TC 注册全局事务记录。 RM 执行正向操作资源管理器RM依次执行各个本地事务的正向操作。
第二阶段提交或回滚 TM 提交全局事务如果所有正向操作均成功TM 向 TC 发送提交请求。 RM 执行提交操作RM 根据 TC 的指令执行提交操作。 TM 回滚全局事务如果任何一个正向操作失败TM 向 TC 发送回滚请求。 RM 执行补偿操作RM 执行对应的补偿操作回滚已提交的本地事务使全局事务回到初始状态。 二、Seata的配置和启动 2.1 Seata下载
关于Seata我们需要现在Seata-serve github地址https://github.com/seata/seata/releases 链接: https://pan.baidu.com/s/1PBI2i3su6uzz_mHVilavJA?pwdtbwh 提取码: tbwh 2.2 Seata配置 conf目录下有一个application.example.yml这是模板配置文件还有一个application.yml这是真正的配置文件修改此文件增加nacos的config和registry配置当然只要你是使用nacos作为配置中心并且端口地址是8848的话你可以直接拷贝我的配置
server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seatapassword: seataseata:config:# 配置中心类型 support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 127.0.0.1:8848namespace: group: DEFAULT_GROUPusername: nacospassword: nacosdata-id: seataServer.propertiesregistry:# 注册中心类型 support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: DEFAULT_GROUPnamespace: cluster: defaultusername: nacospassword: nacosstore:# support: file 、 db 、 redismode: file
# server:
# service-port: 8091 #If not configured, the default is ${server.port} 1000security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login 2..3 配置Nacos
创建一个新的配置名字叫seataServer.properties 下面的内容需要你自己修改你自己的mysql数据库的配置
5.x版本请使用 com.mysql.jdbc.Driver
8.x版本请使用 com.mysql.cj.jdbc.Driver
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.typeTCP
transport.serverNIO
transport.heartbeattrue
transport.enableTmClientBatchSendRequestfalse
transport.enableRmClientBatchSendRequesttrue
transport.enableTcServerBatchSendResponsefalse
transport.rpcRmRequestTimeout30000
transport.rpcTmRequestTimeout30000
transport.rpcTcRequestTimeout30000
transport.threadFactory.bossThreadPrefixNettyBoss
transport.threadFactory.workerThreadPrefixNettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefixNettyServerBizHandler
transport.threadFactory.shareBossWorkerfalse
transport.threadFactory.clientSelectorThreadPrefixNettyClientSelector
transport.threadFactory.clientSelectorThreadSize1
transport.threadFactory.clientWorkerThreadPrefixNettyClientWorkerThread
transport.threadFactory.bossThreadSize1
transport.threadFactory.workerThreadSizedefault
transport.shutdown.wait3
transport.serializationseata
transport.compressornone#Transaction routing rules configuration, only for the client
# 此处的mygroup名字可以自定义只修改这个值即可
service.vgroup_mapping.stock-service-groupdefault
service.vgroup_mapping.order-service-groupdefault
#If you use a registry, you can ignore it
service.default.grouplist127.0.0.1:8091
service.enableDegradefalse
service.disableGlobalTransactionfalse#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit10000
client.rm.lock.retryInterval10
client.rm.lock.retryTimes30
client.rm.lock.retryPolicyBranchRollbackOnConflicttrue
client.rm.reportRetryCount5
client.rm.tableMetaCheckEnabletrue
client.rm.tableMetaCheckerInterval60000
client.rm.sqlParserTypedruid
client.rm.reportSuccessEnablefalse
client.rm.sagaBranchRegisterEnablefalse
client.rm.sagaJsonParserfastjson
client.rm.tccActionInterceptorOrder-2147482648
client.tm.commitRetryCount5
client.tm.rollbackRetryCount5
client.tm.defaultGlobalTransactionTimeout60000
client.tm.degradeCheckfalse
client.tm.degradeCheckAllowTimes10
client.tm.degradeCheckPeriod2000
client.tm.interceptorOrder-2147482648
client.undo.dataValidationtrue
client.undo.logSerializationjackson
client.undo.onlyCareUpdateColumnstrue
server.undo.logSaveDays7
server.undo.logDeletePeriod86400000
client.undo.logTableundo_log
client.undo.compress.enabletrue
client.undo.compress.typezip
client.undo.compress.threshold64k
#For TCC transaction mode
tcc.fence.logTableNametcc_fence_log
tcc.fence.cleanPeriod1h#Log rule configuration, for client and server
log.exceptionRate100#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
# 默认为file一定要改为db我们自己的服务启动会连接不到seata
store.modedb
store.lock.modedb
store.session.modedb
#Used for password encryption#These configurations are required if the store mode is db. If store.mode,store.lock.mode,store.session.mode are not equal to db, you can remove the configuration block.
# 修改mysql的配置
store.db.datasourcedruid
store.db.dbTypemysql
store.db.driverClassNamecom.mysql.cj.jdbc.Driver
# 指定seata的数据库下面会提
store.db.urljdbc:mysql://127.0.0.1:3306/seata?useUnicodetruerewriteBatchedStatementstrue
store.db.userroot
store.db.passwordroot
store.db.minConn5
store.db.maxConn30
store.db.globalTableglobal_table
store.db.branchTablebranch_table
store.db.distributedLockTabledistributed_lock
store.db.queryLimit100
store.db.lockTablelock_table
store.db.maxWait5000#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod1000
server.recovery.asynCommittingRetryPeriod1000
server.recovery.rollbackingRetryPeriod1000
server.recovery.timeoutRetryPeriod1000
server.maxCommitRetryTimeout-1
server.maxRollbackRetryTimeout-1
server.rollbackRetryTimeoutUnlockEnablefalse
server.distributedLockExpireTime10000
server.xaerNotaRetryTimeout60000
server.session.branchAsyncQueueSize5000
server.session.enableBranchAsyncRemovefalse
server.enableParallelRequestHandlefalse#Metrics configuration, only for the server
metrics.enabledfalse
metrics.registryTypecompact
metrics.exporterListprometheus
metrics.exporterPrometheusPort98982.4 配置Mysql
新建配置表
在seata数据库中新建查询执行如下sqlsql文件存放在seata/script/server/db/mysql.sql中数据库名称需要和你刚刚Nacos中配置的数据库名一致
-- -------------------------------- The script used when storeMode is db --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS global_table
(xid VARCHAR(128) NOT NULL,transaction_id BIGINT,status TINYINT NOT NULL,application_id VARCHAR(32),transaction_service_group VARCHAR(32),transaction_name VARCHAR(128),timeout INT,begin_time BIGINT,application_data VARCHAR(2000),gmt_create DATETIME,gmt_modified DATETIME,PRIMARY KEY (xid),KEY idx_status_gmt_modified (status , gmt_modified),KEY idx_transaction_id (transaction_id)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS branch_table
(branch_id BIGINT NOT NULL,xid VARCHAR(128) NOT NULL,transaction_id BIGINT,resource_group_id VARCHAR(32),resource_id VARCHAR(256),branch_type VARCHAR(8),status TINYINT,client_id VARCHAR(64),application_data VARCHAR(2000),gmt_create DATETIME(6),gmt_modified DATETIME(6),PRIMARY KEY (branch_id),KEY idx_xid (xid)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS lock_table
(row_key VARCHAR(128) NOT NULL,xid VARCHAR(128),transaction_id BIGINT,branch_id BIGINT NOT NULL,resource_id VARCHAR(256),table_name VARCHAR(32),pk VARCHAR(36),status TINYINT NOT NULL DEFAULT 0 COMMENT 0:locked ,1:rollbacking,gmt_create DATETIME,gmt_modified DATETIME,PRIMARY KEY (row_key),KEY idx_status (status),KEY idx_branch_id (branch_id),KEY idx_xid (xid)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;CREATE TABLE IF NOT EXISTS distributed_lock
(lock_key CHAR(20) NOT NULL,lock_value VARCHAR(20) NOT NULL,expire BIGINT,primary key (lock_key)
) ENGINE InnoDBDEFAULT CHARSET utf8mb4;INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (AsyncCommitting, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (RetryCommitting, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (RetryRollbacking, , 0);
INSERT INTO distributed_lock (lock_key, lock_value, expire) VALUES (TxTimeoutCheck, , 0);2.5 启动Seata
双击seata-server.bat 启动服务
查看Nacos控制台结果有服务注册进入了 访问访问http://127.0.0.1:7091/#/login 能否进入seata的可视化控制台用户名与密码默认为seata 三、SpringcloudAlibaba整合使用
首先编写业务数据库数据库名seata_test
create table order
(id int null,user_id int null,commodity_code int null comment 商品代码,count int null comment 数量,money int null
)comment 订单表;create table storage
(id int null,commodity_code int null,count int null comment 商品数量
)comment 库存表; seata测试学习的springboot项目我也给出百度网盘链接链接: https://pan.baidu.com/s/1H-uoFM2-2_ghzVRADc_c3g?pwdqu6v 提取码: qu6v 注意的是你可以需要自己配置一下配置文件中的mysql用户名密码并且在启动项目之前需要启动nacos项目启动完毕从nacos控制台可以看到有两个服务注册成功。 3.1 历史遗留问题 我们在最早的时候不是已经说过了在微服务项目中是不可用保证ACID的所以我们先来通过一个test看一下是不是真的会出数据不一致的问题。
下面我使用到的工具是apifox进行调用当然也可以使用postman啦.
首先看数据库中的数据
首先是order表 其次是storage 现在我们执行一下创建订单的方法这个地方我故意的让库存不足我们看一下订单是否会被创建 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2.2.10-RC1/version/dependency
我们可以看到在我们的apifox中报了500错误现在我们去看一下订单表是否被创建。 所以我们可以看出来在微服务的情况下不可用保证数据的一致性所以我们就需要用到分布式事务。
引入SpringcloudAlibabaSeata依赖 dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2.2.10-RC1/version/dependency 在方法上使用注解GlobalTransactional开启分布式事务这样子简单的XA模式就完成了