由于目前互联网企业的兴起,越来越多的企业开始采用微服务架构模式。微服务架构模式的确提升后台服务的性能,保证服务的高可用等优点,但是同时也带来了一个问题,即如何保证数据的一致性、操作原子性,即分布式事务。目前,互联网主要有2PC,3PC,TCC,事务性事务方式。 今天就主要介绍阿里旗下的分布式事务中间件Seata
1.Seata地址:https://github.com/seata/seata/issues ,下载seata-server
2.将Seata放到相应的文件目录解压,并修改conf文件夹下,修改registry.conf以及file.conf
3.修改registry.conf,以文件格式注册
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
file {
name = "file.conf"
}
}
4.修改file.conf,以文件形式时,需要通过netty通信
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = true
#thread factory for netty
threadFactory {
bossThreadPrefix = "NettyBoss"
workerThreadPrefix = "NettyServerNIOWorker"
serverExecutorThreadPrefix = "NettyServerBizHandler"
shareBossWorker = false
clientSelectorThreadPrefix = "NettyClientSelector"
clientSelectorThreadSize = 1
clientWorkerThreadPrefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
bossThreadSize = 1
#auto default pin or 8
workerThreadSize = "8"
}
serialization = "seata"
compressor = "none"
}
## transaction log store, only used in server side
store {
## store mode: file、db
mode = "file"
## file store property
file {
## store location dir
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
maxBranchSessionSize = 16384
# globe session size , if exceeded throws exceptions
maxGlobalSessionSize = 512
# file buffer size , if exceeded allocate new buffer
fileWriteBufferCacheSize = 16384
# when recover batch read size
sessionReloadReadSize = 100
# async, sync
flushDiskMode = async
}
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://192.168.2.172:3306/seata"
user = "root"
password = "root"
global.table = "global_table"
branch.table="branch_table"
query-limit = 100
}
}
5.java代码,首先启动Eureka,然后,在Account服务中,写服务
package com.example.account.controller;
import com.example.account.service.ISeataAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
/**
* <p>
* 账户信息表 前端控制器
* </p>
*
* @author yz
* @since 2020-04-28
*/
@RestController
@RequestMapping("/account")
public class SeataAccountController {
@Autowired
private ISeataAccountService accountService;
@RequestMapping("/deduction")
public void deduction(@RequestParam("id") Integer accountId,@RequestParam("price") BigDecimal money) {
accountService.deduction(accountId, money);
// throw new RuntimeException("错误");
}
}
6.在Order服务中远程调用
package com.example.orderservice.service;
import com.example.orderservice.service.impl.AccountService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.math.BigDecimal;
@FeignClient(name="account-service",fallback = AccountService.class)
public interface IAccountService {
@RequestMapping(value = "/account/deduction",method = RequestMethod.GET)
void deduction(@RequestParam("id") Integer accountId,@RequestParam("price") BigDecimal money);
}
package com.example.orderservice.controller;
import com.example.orderservice.entity.SeataOrder;
import com.example.orderservice.service.IAccountService;
import com.example.orderservice.service.ISeataOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.Random;
/**
* <p>
* 前端控制器
* </p>
*
* @author yz
* @since 2020-04-28
*/
@RestController
@RequestMapping("/order")
public class SeataOrderController {
@Autowired
IAccountService accountService;
@Autowired
ISeataOrderService orderService;
@RequestMapping("/submit")
@GlobalTransactional
public void submitOrder(@RequestParam("id") Integer accountId,@RequestParam("price") BigDecimal orderPrice) {
accountService.deduction(accountId, orderPrice);
SeataOrder order = new SeataOrder();
order.setOAccountId(accountId);
order.setOGoodId(RandomUtils.nextInt());
order.setOPrice(orderPrice.intValue());
orderService.save(order);
// throw new RuntimeException("错误");
System.out.println("成功");
}
}
7.需要在Order和Account服务端中的resources中添加file.conf
service {
vgroupMapping.minbox-seata = "seata-server"
seata-server.grouplist = "192.168.2.172:8091"
enableDegrade = false
disable = false
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
}
以上操作就可以实现分布式事务
另外 ,也可以将seata-server注入到eureka中,来使用
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka"
eureka {
serviceUrl = "http://192.168.2.242:8090/eureka/"
application = "seata-server"
weight = "1"
}
}
file.conf
store {
## store mode: file、db
mode = "file"
## file store property
file {
## store location dir
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
maxBranchSessionSize = 16384
# globe session size , if exceeded throws exceptions
maxGlobalSessionSize = 512
# file buffer size , if exceeded allocate new buffer
fileWriteBufferCacheSize = 16384
# when recover batch read size
sessionReloadReadSize = 100
# async, sync
flushDiskMode = async
}
}
就可以实现分布式事务了
启动Seata-server:./seata-server.sh
浙公网安备 33010602011771号