Table of contents
Seata provides XA mode to realize distributed transaction_transfer function realization
Seata provides XA mode to realize distributed transaction_Transfer function is realized
Seata provides XA mode to realize distributed transactions_Project introduced Seata
Seata provides XA mode to realize distributed transaction_transfer function realization
Realize the following functions
1. Increase the amount of Li Si's account.
Create cloud-seata-bank2
Pom introduces dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependency>
Write the main startup class
//添加对mapper包扫描 Mybatis-plus
@MapperScan("com.tong.mapper")
//开启OpenFiegn
@EnableFeignClients
@SpringBootApplication
@Slf4j
//开启发现注册
@EnableDiscoveryClient
public class SeataBank2Main6002 {
public static void main(String[] args) {
SpringApplication.run(SeataBank1Main6002.class,args);
log.info("**************SeataBank1Main6002 *************");
}
}
Write a YML configuration file
server:
port: 6002
spring:
application:
name: seata-bank2
cloud:
nacos:
discovery:
# Nacos server地址
server-addr: 192.168.66.101:8848
datasource:
url: jdbc:mysql://localhost:3306/bank2?
useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
Create entity class
@AllArgsConstructor
@NoArgsConstructor
@Builder
@TableName("account_info")
@Data
public class AccountInfo {
//id
@TableId
private Long id;
//户主姓名
@TableField("account_name")
private String accountName;
//银行卡号
@TableField("account_no")
private String accountNo;
//账户密码
@TableField("account_password")
private String accountPassword;
//账户余额
@TableField("account_balance")
private Double accountBalance;
}
Write the persistence layer
@Component
@Mapper
public interface AccountMapper extends
BaseMapper<AccountInfo> {}
Write transfer interface
public interface IAccountInfoService {
//李四增加金额
void updateAccountBalance(String accountNo, Double amount);
}
Write transfer interface implementation class
@Service
@Slf4j
public class AccountInfoServiceImpl implements IAccountInfoService {
@Autowired
AccountMapper accountMapper;
@Override
public void updateAccountBalance(String accountNo, Double amount) {
// 1. 获取用户信息
AccountInfo accountInfo = accountMapper.selectById(accountNo);
accountInfo.setAccountBalance(accountInfo.getAccountBalance() + amount);
accountMapper.updateById(accountInfo);
}
}
Write the control layer
@RestController
@RequestMapping("/bank2")
public class Bank2Controller {
@Autowired
IAccountInfoService accountInfoService;
//接收张三的转账
@GetMapping("/transfer")
public String transfer(Double amount){
//李四增加金额
accountInfoService.updateAccountBalance("3",amount);
return "bank2"+amount;
}
}
Seata provides XA mode to realize distributed transaction_Transfer function is realized
Realize the following functions
1. Decrease in Zhang San's account
2. Remotely call bank2 to transfer money to Li Si.
Create cloud-seata-bank1
Pom introduces dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
Write the main startup class
//添加对mapper包扫描 Mybatis-plus
@MapperScan("com.tong.mapper")
//开启OpenFiegn
@EnableFeignClients
@SpringBootApplication
@Slf4j
//开启发现注册
@EnableDiscoveryClient
public class SeataBank1Main6001 {
public static void main(String[] args) {
SpringApplication.run(SeataBank1Main6001.class,args);
log.info("**************SeataBank1Main6001 *************");
}
}
Write a YML configuration file
server:
port: 6001
spring:
application:
name: seata-bank1
cloud:
nacos:
discovery:
# Nacos server地址
server-addr: 192.168.66.101:8848
datasource:
url: jdbc:mysql://localhost:3306/bank1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
Create entity class
@AllArgsConstructor
@NoArgsConstructor
@Builder
@TableName("account_info")
@Data
public class AccountInfo {
//id
@TableId
private Long id;
//户主姓名
@TableField("account_name")
private String accountName;
//银行卡号
@TableField("account_no")
private String accountNo;
//账户密码
@TableField("account_password")
private String accountPassword;
//账户余额
@TableField("account_balance")
private Double accountBalance;
}
Write the persistence layer
@Component
@Mapper
public interface AccountMapper extends BaseMapper<AccountInfo> {
}
Write transfer interface
public interface IAccountInfoService {
//张三扣减金额
public void updateAccountBalance(String accountNo, Double amount);
}
Write a remote call interface
@Component
@FeignClient(value="seata-bank2")
public interface Bank2Client {
//远程调用李四的微服务
@GetMapping("/bank2/transfer")
String transfer(@RequestParam("amount") Double amount);
}
Write transfer interface implementation class
@Service
@Slf4j
public class AccountInfoServiceImpl implements IAccountInfoService {
@Autowired
AccountMapper accountMapper;
@Autowired
Bank2Client bank2Client;
@Override
public void updateAccountBalance(String accountNo, Double amount) {
// 1. 获取用户信息
AccountInfo accountInfo = accountMapper.selectById(2);
// 2. 判断张三账户余额是否有钱
if (accountInfo.getAccountBalance() > amount){
//扣减张三的金额
accountInfo.setAccountBalance(accountInfo.getAccountBalance()-amount);
int result = accountMapper.updateById(accountInfo);
if (result!=0){
//调用李四微服务,转账
bank2Client.transfer(amount);
}
}
}
}
Write the control layer
@RestController
public class Bank1Controller {
@Autowired
IAccountInfoService IAccountInfoService;
//张三转账
@GetMapping("/transfer")
public String transfer(Double amount){
IAccountInfoService.updateAccountBalance("1",amount);
return "bank1"+amount;
}
}
Seata provides XA mode to realize distributed transaction_no demonstration of distributed transaction problem
initial database data
normal circumstances
Send request http://localhost:6001/transfer?amount=2
Create anomalies
Create an exception in the bank2 microservice
post exception test
Send request http://localhost:6001/transfer?amount=2
Seata provides XA mode to realize distributed transactions_Project introduced Seata
Seata implements XA key points
1. Global transactions start to use the GlobalTransactional flag.
2. Each local transaction scheme still uses the @Transactional logo.
3. Each data needs to create an undo_log table, which is the key for Seata to ensure the consistency of local transactions.
Create UNDO_LOG table
SEATA XA schema requires UNDO_LOG table
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
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`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
add dependencies
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
Modify configuration file YML
seata:
# 注册中心
registry:
type: file
service:
# seata服务端的地址和端口信息,多个使用英文分号分隔
grouplist:
default: 192.168.66.100:9999
tx-service-group: my_test_tx_group
Bank1 microservices start global things
Note: Mark the @GlobalTransactional annotation on the Service implementation method initiated by the global transaction, and start the global transaction: GlobalTransactionalInterceptor will intercept the @GlobalTransactional annotation method to generate a global transaction ID (XID), and the XID will be passed throughout the distributed transaction. When calling remotely, spring-cloud-alibaba-seata will intercept the Feign call and pass the XID to the downstream service.
bank2 opens things
Test distributed things
Send request http://localhost:6001/transfer?amount=2
Summarize
Traditional 2PC (based on the database XA protocol) and Seata are two 2PC solutions for implementing 2PC. Because Seata has zero intrusion and solves the problem of traditional 2PC long-term lock resources, it is recommended to use Seata to implement 2PC.
Real-time effect feedback
1. How to enable the global thing_____ in Seata technology.
A Global logo
B GlobalTransactional logo
C Transactional logo
All of the above are wrong
2. How to enable local things____ in Seata technology.
A Global logo
B GlobalTransactional logo
C Transactional logo
All of the above are wrong