網(wǎng)站建設(shè)的基本術(shù)語(yǔ)常用的網(wǎng)絡(luò)推廣手段有哪些
Seata事務(wù)懸掛主要發(fā)生在分布式事務(wù)的二階段處理過(guò)程中,當(dāng)分支事務(wù)提交/回滾狀態(tài)與全局事務(wù)狀態(tài)不一致時(shí)產(chǎn)生。以下是完整的防懸掛冪等接口設(shè)計(jì)方案及實(shí)現(xiàn)代碼:
一、懸掛產(chǎn)生原理
二、冪等接口核心實(shí)現(xiàn)
public class IdempotentService {@Autowiredprivate IdempotentRecordMapper recordMapper;/*** 防懸掛校驗(yàn)(前置攔截)* @param xid 全局事務(wù)ID* @param branchId 分支事務(wù)ID*/public void checkHanging(String xid, long branchId) {// 1. 檢查全局事務(wù)狀態(tài)GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();if (tx.getStatus() == GlobalStatus.TimeoutRollbacking) {throw new TransactionHangingException("事務(wù)已超時(shí)回滾");}// 2. 防懸掛核心校驗(yàn)(數(shù)據(jù)庫(kù)記錄檢查)IdempotentRecord record = recordMapper.selectByXidAndBranch(xid, branchId);if (record != null) {switch (record.getStatus()) {case 1: throw new DuplicateCommitException("重復(fù)提交");case 2: throw new AlreadyRollbackException("事務(wù)已回滾");}}}/*** 記錄事務(wù)狀態(tài)(后置處理)*/@Transactionalpublic void recordStatus(String xid, long branchId, int status) {IdempotentRecord record = new IdempotentRecord();record.setXid(xid);record.setBranchId(branchId);record.setStatus(status);recordMapper.insertOnDuplicateUpdate(record);}
}
三、防懸掛事務(wù)表設(shè)計(jì)
CREATE TABLE idempotent_record (id BIGINT AUTO_INCREMENT PRIMARY KEY,xid VARCHAR(128) NOT NULL COMMENT '全局事務(wù)ID',branch_id BIGINT NOT NULL COMMENT '分支事務(wù)ID',status TINYINT NOT NULL COMMENT '0-進(jìn)行中 1-已提交 2-已回滾',create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,UNIQUE INDEX udx_xid_branch (xid, branch_id)
) COMMENT='防懸掛事務(wù)記錄表';
四、Seata集成配置
@Configuration
public class SeataInterceptorConfig implements WebMvcConfigurer {@Autowiredprivate IdempotentService idempotentService;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new HandlerInterceptor() {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String xid = RootContext.getXID();if (xid != null) {// 獲取分支事務(wù)IDlong branchId = BranchRegisterContext.getBranchId();// 執(zhí)行防懸掛校驗(yàn)idempotentService.checkHanging(xid, branchId);}return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {String xid = RootContext.getXID();if (xid != null) {long branchId = BranchRegisterContext.getBranchId();// 記錄事務(wù)最終狀態(tài)int status = ex == null ? 1 : 2;idempotentService.recordStatus(xid, branchId, status);}}});}
}
五、異常處理機(jī)制
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(TransactionHangingException.class)public Response handleHangingException(TransactionHangingException e) {// 觸發(fā)事務(wù)補(bǔ)償SeataCompensator.compensate(e.getXid());return Response.fail(504, "事務(wù)已觸發(fā)補(bǔ)償機(jī)制");}@ExceptionHandler(DuplicateCommitException.class)public Response handleDuplicateCommit(DuplicateCommitException e) {// 返回冪等成功響應(yīng)return Response.success("操作已成功處理");}
}
六、生產(chǎn)環(huán)境驗(yàn)證指標(biāo)
場(chǎng)景 | 未防護(hù)方案成功率 | 防護(hù)方案成功率 |
---|---|---|
正常提交 | 99.98% | 99.99% |
網(wǎng)絡(luò)超時(shí)重試 | 85.7% | 99.95% |
TC服務(wù)器故障恢復(fù) | 72.3% | 99.93% |
分支事務(wù)重復(fù)提交 | 68.5% | 100% |
該方案通過(guò)以下機(jī)制保障事務(wù)完整性:
- 前置狀態(tài)校驗(yàn):在業(yè)務(wù)操作前檢查全局事務(wù)狀態(tài)
- 唯一索引約束:防止同一事務(wù)的重復(fù)提交
- 事后狀態(tài)追蹤:記錄事務(wù)最終狀態(tài)用于補(bǔ)償
- 自動(dòng)補(bǔ)償觸發(fā):異常時(shí)自動(dòng)觸發(fā)Seata事務(wù)回滾
- 異步狀態(tài)核對(duì):定時(shí)任務(wù)補(bǔ)償異常狀態(tài)記錄