做个企业网站多少钱,wordpress添加评论框,网站如何做内链,做网页的编程语言一、分布式事务简介
1.1 概念
事务ACID#xff1a; A#xff08;Atomic#xff09;#xff1a;原子性#xff0c;构成事务的所有操作#xff0c;要么都执行完成#xff0c;要么全部不执行#xff0c;不可能出现部分成功部分失 败的情况。 C#xff08;Consistency AAtomic原子性构成事务的所有操作要么都执行完成要么全部不执行不可能出现部分成功部分失 败的情况。 CConsistency一致性在事务执行前后数据库的一致性约束没有被破坏。比如张三向李四转100元 转账前和转账后的数据是正确状态这叫一致性如果出现张三转出100元李四账户没有增加100元这就出现了数 据错误就没有达到一致性。 IIsolation隔离性数据库中的事务一般都是并发的隔离性是指并发的两个事务的执行互不干扰一个事 务不能看到其他事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题。 DDurability持久性事务完成之后该事务对数据的更改会被持久化到数据库且不会被回滚。
1.2 事务详解 本地事务同一数据库和服务器称为本地事务 在计算机系统中更多的是通过关系型数据库来控制事务这是利用数据库本身的事务特性来实现的因此叫数据库事务由于应用主要靠关系数据库来控制事务而数据库通常和应用在同一个服务器所以基于关系型数据库的事务又被称为本地事务。 分布式事务 分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上且属于不同的应用分布式事务需要保证这些操作要么全部成功要么全部失败。本质上来说分布式事务就是为了保证不同数据库的数据一致性。 举例 分布式系统会把一个应用系统拆分为可独立部署的多个服务因此需要服务与服务之间远程协作才能完成事务操 作这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务例如用户注册送积分事务、创建订单减库存事务银行转账事务等都是分布式事务。
通过以上的图中我们可以看出其实只要涉及到操作多个数据源就可能会产生事务问题当然在实际开发中我们要尽量避免这种问题的出现当然如果避免不了我们就需要进行解决在我们的微服务系统架构中目前比较好比较常用的解决方案就是Seata。
二、分布式理论
随着互联化的蔓延各种项目都逐渐向分布式服务做转换。如今微服务已经普遍存在本地事务已经无法满足分布式的要求由此分布式事务问题诞生。 分布式事务被称为世界性的难题目前分布式事务存在两大理论依据CAP定律 BASE理论。
2.1 CAP定律
这个定理的内容是指的是在一个分布式系统中、Consistency一致性、 Availability可用性、Partition tolerance分区容错性三者不可得兼。
一致性C 在分布式系统中的所有数据备份在同一时刻是否同样的值。等同于所有节点访问同一份最新的数据副本可用性A 在集群中一部分节点故障后集群整体是否还能响应客户端的读写请求。对数据更新具备高可用性分区容错性P 以实际效果而言分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性就意味着发生了分区的情况必须就当前操作在C和A之间做出选择
CAP是无法同时存在的以下通过这个例子来说明
2.2 BASE理论
BASE是Basically Available基本可用、Soft state软状态和 Eventually consistent最终一致性三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果其来源于对大规模互联网系统分布式实践的总结 是基于CAP定理逐步演化而来的。BASE理论的核心思想是即使无法做到强一致性但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性 基本可用 基本可用是指分布式系统在出现不可预知故障的时候允许损失部分可用性—-注意这绝不等价于系统不可用。比如 1响应时间上的损失。正常情况下一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果但由于出现故障查询结果的响应时间增加了1~2秒 2系统功能上的损失正常情况下在一个电子商务网站上进行购物的时候消费者几乎能够顺利完成每一笔订单但是在一些节日大促购物高峰的时候由于消费者的购物行为激增为了保护购物系统的稳定性部分消费者可能会被引导到一个降级页面 软状态 软状态指允许系统中的数据存在中间状态并认为该中间状态的存在不会影响系统的整体可用性即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时 最终一致性 最终一致性强调的是所有的数据副本在经过一段时间的同步之后最终都能够达到一个一致的状态。因此最终一致性的本质是需要系统保证最终数据能够达到一致而不需要实时保证系统数据的强一致性。
2.2.1 基本可用
基本可用**保证核心服务是可以使用的至于其他的服务可以适当的降低响应时间甚至是服务降级
2.2.2 软状态
软状态存在中间状态不影响整体系统使用数据同步存在延时
2.2.3 最终一致性
最终一致性再过了流量高峰期以后经过一段时间的同步保持各服务数据的一致
三、分布式事务解决方案
3.1 什么是2PC
2PC即两阶段提交协议是将整个事务流程分为两个阶段P是指准备阶段C是指提交阶段。 准备阶段Prepare phase 提交阶段commit phase
举例比如说相亲对象两个人去吃饭店老板要求先付钱在吃饭这是男女双方提出了AA也就是说只有男女双方都付钱才能落座吃饭但是只要两个人中有一个不统一付款就不能落座吃饭。 准备阶段老板要求男方付款男方付款。老板要求女方付款女方付款 提交阶段老板出餐两人纷纷落座
其实此例子就形成了一个事务如果男女双方有一个人拒绝付款那么老板就不会出餐并且会把已收取的钱原路退回。
真个事务过程是由事务管理器和参与者组成的店老板就是事务管管理器男女双发就是参与者事务管理器决策整个分布式事务在计算机中关系数据库支持的两阶段提交协议 准备阶段Prepare phase事务管理器给每个参与者发送Prepare消息每个数据库参与者在本地执行事务并写本地的Undo/Redo日志此时事务没有提交。 Undo日志是记录修改前的数据用于数据库回滚Redo日志是记录修改后的数据用于提交事务后写入数据文件 提交阶段commit phase如果事务管理器收到了参与者的执行失败或者超时消息时直接给每个参与者发送回滚(Rollback)消息否则发送提交(Commit)消息参与者根据事务管理器的指令执行提交或者回滚操作并释放事务处理过程中使用的资源。 四、Seata初始
官网https://seata.io/zh-cn/docs/overview/what-is-seata.html
概念Seata 是一款开源的分布式事务解决方案致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式为用户打造一站式的分布式解决方案。
在我们的微服务系统中对应业务被对应的拆分成独立模块在官方提供的架构图中我们可以看出当前是三个服务 仓储服务对给定的商品进行增删操作记录数量 订单服务根据采购者的需求创建订单 账户服务从用户账户中扣除余额、积分等
在这套架构中用户下单购买商品的业务就需要三个服务来完成每个服务内部的数据一致性由本地事务来保证但是全局的数据一致性问题就没办法保证Seata就是来进行解决这种问题的解决方案。
4.2 Seata核心概念
官网地址https://seata.io/zh-cn/docs/overview/terminology.html
要了解Seata首先我们要了解一下Seata的几个关键的概念 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态驱动全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器发起者同时也是RM的一种 定义全局事务的范围开始全局事务、提交或回滚全局事务。 RM (Resource Manager) - 资源管理器每个参与事务的微服务 管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚。 五、Seata下载配置
官方下载地址https://github.com/seata/seata/releases
下载之后解压 我下载的版本为1.8.0
5.1 Seata-Server配置文件
修改seata-server-1.8.0\seata\conf下面的application.yml文件
主要配置如下seata下面的config、registry、store
注册中心、配置中心、模式
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the License);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${log.home:${user.home}/logs/seata}
# extend:
# logstash-appender:
# destination: 127.0.0.1:4560
# kafka-appender:
# bootstrap-servers: 127.0.0.1:9092
# topic: logback_to_logstashconsole:user:username: seatapassword: seata
seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:serverAddr: 127.0.0.1:8848namespace: group: SEATA_GROUPusername: nacospassword: nacosdataId: seataServer.propertiesregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: cluster: defaultusername: nacospassword: nacosstore:# support: file 、 db 、 redismode: dbsession:mode: dblock:mode: dbdb:datasource: duriddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://rm-8vb0l231l029347gjco.mysql.zhangbei.rds.aliyuncs.com:3306/pro-2022?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8allowMultiQueriestrueuser: rootpassword: wsrbbmin-conn: 10max-conn: 100global-table: global-tablebranch-table: branch-tablelock-table: lock-tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000
# server:
# service-port: 8091 #If not configured, the default is ${server.port} 1000security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login5.2 Seata-server db创建
在seata-server-1.8.0\seata\script\server\db 下找到数据库SQL脚本根据自己数据库类型选择对应的脚本执行即可
数据库名称随意只要能找到就行。执行完成后如下
5.3 Nacos添加配置文件config.txt
#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
service.vgroupMapping.default_tx_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.
store.modedb
store.lock.modedb
store.session.modedb
#Used for password encryption
store.publicKey#If store.mode,store.lock.mode,store.session.mode are not equal to file, you can remove the configuration block.
store.file.dirfile_store/data
store.file.maxBranchSessionSize16384
store.file.maxGlobalSessionSize512
store.file.fileWriteBufferCacheSize16384
store.file.flushDiskModeasync
store.file.sessionReloadReadSize100#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.
store.db.datasourcedruid
store.db.dbTypemysql
store.db.driverClassNamecom.mysql.jdbc.Driver
store.db.urljdbc:mysql://127.0.0.1:3306/seata?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8allowMultiQueriestrue
store.db.userroot
store.db.passwordwsrbb
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#These configurations are required if the store mode is redis. If store.mode,store.lock.mode,store.session.mode are not equal to redis, you can remove the configuration block.
store.redis.modesingle
store.redis.single.host127.0.0.1
store.redis.single.port6379
store.redis.sentinel.masterName
store.redis.sentinel.sentinelHosts
store.redis.sentinel.sentinelPassword
store.redis.maxConn10
store.redis.minConn1
store.redis.maxTotal100
store.redis.database0
store.redis.password
store.redis.queryLimit100#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.exporterPrometheusPort9898
配置文件的注意事项
service.vgroupMapping.my_tx_groupdefault
数据库修改上面配置的位置
有可能提示脚本有误。只需要吧一些空值给删除即可
5.4 启动Seata
启动Seata脚本。我这里是window版本所以直接执行seata-server.bat 注意 确保Nacos服务启动成功Seata也是一个服务需要注册到Nacos中
六、AT模式
AT模式是一种无侵入的分布式事务解决方案在 AT 模式下用户只需关注自己的“业务 SQL”用户的 “业务 SQL” 作为一阶段Seata 框架会自动生成事务的二阶段提交和回滚操作。
6.1 整体概览
两阶段提交协议的演变
一阶段业务数据和回滚日志记录在同一个本地事务中提交释放本地锁和连接资源。二阶段 提交异步化非常快速地完成。回滚通过一阶段的回滚日志进行反向补偿。
一阶段
在一阶段中Seata会拦截“业务SQL“首先解析SQL语义找到要更新的业务数据在数据被更新前保存下来undo然后执行”业务SQL“更新数据更新之后再次保存数据”redo“最后生成行锁这些操作都在本地数据库事务内完成这样保证了一阶段的原子性。
二阶段
相对一阶段二阶段比较简单负责整体的回滚和提交如果之前的一阶段中有本地事务没有通过那么就执行全局回滚否在执行全局提交回滚用到的就是一阶段记录的undo Log通过回滚记录生成反向更新SQL并执行以完成分支的回滚。当然事务完成后会释放所有资源和删除所有日志。 6.2 案例讲解
创建两个服务order,stockorder服务通过openfegin远程调用stock执行业务逻辑操作
6.2.1 创建两个数据库order、stock
执行undo_logo日志回滚表
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;6.2.2 对应服务增加依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactId
/dependency
dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.25/version
/dependency
dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.1.10/version
/dependency
dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId
/dependency6.2.3 配置yml文件
注意两个服务的配置文件保持一致
server: port: 8801
spring: application: name: seata-order cloud: nacos: discovery: server-addr: localhost:8848 alibaba: seata: tx-service-group: mygroup # 事务组, 随便写 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/order?characterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghairewriteBatchedStatementstrue username: root password: wsrbb type: com.alibaba.druid.pool.DruidDataSource
management: endpoint: web: exposure: include: *
seata: tx-service-group: mygroup # 事务组名称要和服务端对应 service: vgroup-mapping: mygroup: default # key是事务组名称 value要和服务端的机房名称保持一致6.2.4 关键代码
加上全部事务GlobalTransactional
Resource
private JdbcTemplate jdbcTemplate;
Autowired
private StockApi stockApi; GlobalTransactional
public void create(){ stockApi.decrement(); int i 1/0; jdbcTemplate.update(insert into order_at (product_id, count) values (1, 10)); System.out.println(生成订单);
}6.2.5 启动order、stock服务
浏览器访问http://localhost:8801/order/order/create,此时服务肯定会抛出异常数据应该回滚。
我们通过debug模式可以看到减库存stock服务在数据库中已经减掉了。此时发生异常后数据回滚 undo_log表快照记录 如果对你有帮助可以关注博主不定期更新各种技术文档 给博主一个免费的点赞以示鼓励谢谢 ! 欢迎各位点赞评论收藏⭐️