写点什么

Day193

  • 2022 年 5 月 08 日
  • 本文字数:13754 字

    阅读完需:约 45 分钟

CREATE TABLE IF NOT EXISTS lock_table


(


row_key VARCHAR(128) NOT NULL,


xid VARCHAR(96),


transaction_id BIGINT,


branch_id BIGINT NOT NULL,


resource_id VARCHAR(256),


table_name VARCHAR(32),


pk VARCHAR(36),


gmt_create DATETIME,


gmt_modified DATETIME,


PRIMARY KEY (row_key),


KEY idx_branch_id (branch_id)


) ENGINE = InnoDB


DEFAULT CHARSET = utf8;


#因为之前已经弄过了 nacos 的持久化,已建了 nacos_config 数据库了,所以这里就不再赘述。


#退出数据库


exit


#退出容器


exit


nacos1.3:


#启动 nacos


docker start nacos 容器 ID


#docker run --env MODE=standalone --name mynacos -d -p 8848:8848 -e MYSQL_SERVICE_HOST=10.211.55.26 -e MYSQL_SERVICE_PORT=3305 -e MYSQL_SERVICE_DB_NAME=nacos_config -e MYSQL_SERVICE_USER=root -e MYSQL_SERVICE_PASSWORD=123456 -e SPRING_DATASOURCE_PLATFORM=mysql -e MYSQL_DATABASE_NUM=1 nacos/nacos-server


seata:


#拉取 seata 镜像(此时最新版为 1.2)


docker pull seataio/seata-server


#运行 seata


docker run --name myseata -d -h 10.211.55.26 -p 8091:8091 seataio/seata-server


#进入 seata 容器


docker exec -it 容器 ID /bin/bash


cd resources


#因为容器没有装 vim,所以我们要先安装 vim


apt-get update


apt-get install vim


#备份文件


cp file.conf file.conf.bk


cp registry.conf registry.conf.bk


#修改 file.conf 文件(看下图)


vim file.conf


#seata1.2 的 file.conf 里没有 service 模块,store 的 mode 支持了 redis


#mysql8 的同学需要修改 file.conf 的驱动配置 store.db.driver-class-name;并 lib 目录下删除 mysql5 驱动,添加 mysql8 驱动。


#按 esc 键然后:wq!退出


#修改文件(看下图)


vim registry.conf


#按 esc 键然后:wq!退出


#退出容器


exit


#重启容器


docker restart seata 容器 ID


file.conf


#service {

vgroupMapping.my_test_tx_group = "fsp_tx_group"

default.grouplist = "10.211.55.26:8091"

enableDegrade = false

disableGlobalTransaction = false

#}





jdbc:mysql://10.211.55.26:3305/seata_order?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8


registry.conf



http://localhost:8848/nacos,到 nacos 后台看 seata 是否成功注册进 nacos。



查看注册进 nacos 的 seata 信息是否正确。![在这里插入图片描述](https://img-blog.csdnimg.cn/20210215171042 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 367.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjg0NDY5,size_16,color_FFFFFF,t_70)




[](()订单/库存/账户业务数据库准备










一般流程


  • 创建数据库


create database seata_order;


create database seata_storage;


create database seata_account;


  • 创建对应的表【订单表、库存表、账户业务表】


seata_order:订单表


CREATE TABLE t_order(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,


user_id BIGINT(11) DEFAULT NULL COMMENT '用户 id',


product_id BIGINT(11)DEFAULT NULL COMMENT '产品 id',


count INT(11) DEFAULT NULL COMMENT '数量',


money DECIMAL(11,0) DEFAULT NULL COMMENT '金额',


status INT(1) DEFAULT NULL COMMENT '订单状态: 0:创建中; 1:已完结'


)ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;


select * from t_order;


seata_storage:库存表


CREATE TABLE t_storage(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,


product_id BIGINT(11) DEFAULT NULL COMMENT '产品 id',


total INT(11) DEFAULT NULL COMMENT '总库存',


used INT(11) DEFAULT NULL COMMENT '已用库存',


residue INT(11) DEFAULT NULL COMMENT '剩余库存'


)ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


INSERT INTO t_storage(id,product_id,total,used,residue)VALUES('1','1','100','0','100');


SELECT * FROM t_storage;


seata_account:账户业务表


CREATE TABLE t_account(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',


user_id BIGINT(11) DEFAULT NULL COMMENT '用户 id',


total DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',


used DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额',


residue DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度'


)ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


INSERT INTO t_account(id,user_id,total,used,residue)VALUES('1','1','1000','0','1000');


SELECT * FROM t_account;


  • 创建对应的回滚日志表undo_log


seata_account:seata_storage、seata_order:


CREATE TABLE IF NOT EXISTS undo_log


(


branch_id BIGINT(20) NOT NULL COMMENT 'branch transaction id',


xid VARCHAR(100) NOT NULL COMMENT 'global transaction id',


context VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',


rollback_info LONGBLOB NOT NULL COMMENT 'rollback info',


log_status INT(11) NOT NULL COMMENT '0:normal status,1:defense status',


log_created DATETIME(6) NOT NULL COMMENT 'create datetime',


log_modified DATETIME(6) NOT NULL COMMENT 'modify datetime',


UNIQUE KEY ux_undo_log (xid, branch_id)


) ENGINE = InnoDB


AUTO_INCREMENT = 1


DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';





docker 流程


#进入 mysql5.6 容器


docker exec -it 容器 ID /bin/bash


#进入 mysql


mysql -uroot -p123456 --default-character-set=utf8


#创建业务数据库和对应的业务表


#order


create database seata_order;


use seata_order;


CREATE TABLE t_order(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,


user_id BIGINT(11) DEFAULT NULL COMMENT '用户 id',


product_id BIGINT(11)DEFAULT NULL COMMENT '产品 id',


count INT(11) DEFAULT NULL COMMENT '数量',


money DECIMAL(11,0) DEFAULT NULL COMMENT '金额',


status INT(1) DEFAULT NULL COMMENT '订单状态: 0:创建中; 1:已完结'


)ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;


select * from t_order;


CREATE TABLE IF NOT EXISTS undo_log


(


branch_id BIGINT(20) NOT NULL COMMENT 'branch transaction id',


xid VARCHAR(100) NOT NULL COMMENT 'global transaction id',


context VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',


rollback_info LONGBLOB NOT NULL COMMENT 'rollback info',


log_status INT(11) NOT NULL COMMENT '0:normal status,1:defense status',


log_created DATETIME(6) NOT NULL COMMENT 'create datetime',


log_modified DATETIME(6) NOT NULL COMMENT 'modify datetime',


UNIQUE KEY ux_undo_log (xid, branch_id)


) ENGINE = InnoDB


AUTO_INCREMENT = 1


DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';


#storage


create database seata_storage;


use seata_storage;


CREATE TABLE t_storage(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,


product_id BIGINT(11) DEFAULT NULL COMMENT '产品 id',


total INT(11) DEFAULT NULL COMMENT '总库存',


used INT(11) DEFAULT NULL COMMENT '已用库存',


residue INT(11) DEFAULT NULL COMMENT '剩余库存'


)ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


INSERT INTO t_storage(id,product_id,total,used,residue)VALUES('1','1','100','0','100');


SELECT * FROM t_storage;


CREATE TABLE IF NOT EXISTS undo_log


(


branch_id BIGINT(20) NOT NULL COMMENT 'branch transaction id',


xid VARCHAR(100) NOT NULL COMMENT 'global transaction id',


context VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',


rollback_info LONGBLOB NOT NULL COMMENT 'rollback info',


log_status INT(11) NOT NULL COMMENT '0:normal status,1:defense status',


log_created DATETIME(6) NOT NULL COMMENT 'create datetime',


log_modified DATETIME(6) NOT NULL COMMENT 'modify datetime',


UNIQUE KEY ux_undo_log (xid, branch_id)


) ENGINE = InnoDB


AUTO_INCREMENT = 1


DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';


#account


create database seata_account;


use seata_account;


CREATE TABLE t_account(


id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',


user_id BIGINT(11) DEFAULT NULL COMMENT '用户 id',


total DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',


used DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额',


residue DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度'


)ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


INSERT INTO t_account(id,user_id,total,used,residue)VALUES('1','1','1000','0','1000');


SELECT * FROM t_account;


CREATE TABLE IF NOT EXISTS undo_log


(


branch_id BIGINT(20) NOT NULL COMMENT 'branch transaction id',


xid VARCHAR(100) NOT NULL COMMENT 'global transaction id',


context VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',


rollback_info LONGBLOB NOT NULL COMMENT 'rollback info',


log_status INT(11) NOT NULL COMMENT '0:normal status,1:defense status',


log_created DATETIME(6) NOT NULL COMMENT 'create datetime',


log_modified DATETIME(6) NOT NULL COMMENT 'modify datetime',


UNIQUE KEY ux_undo_log (xid, branch_id)


) ENGINE = InnoDB


AUTO_INCREMENT = 1


DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';


#退出 mysql


exit


#退出容器


exit




[](()订单/库存/账户业务微服务准备







[](()订单模块


  1. 新建模块 seata-order-service2001

  2. pom


<dependencies>


<dependency>


<groupId>com.alibaba.cloud</groupId>


<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>


</dependency>


<dependency>


<groupId>com.alibaba.cloud</groupId>


<artifactId>spring-cloud-starter-alibaba-seata</artifactId>


<exclusions>


<exclusion>


<groupId>io.seata</groupId>


<artifactId>seata-all</artifactId>


</exclusion>


</exclusions>


</dependency>


<dependency>


<groupId>io.seata</groupId>


<artifactId>seata-all</artifactId>


<version>1.0.0</version>


</dependency>


<dependency>


<groupId>org.springframework.cloud</groupId>


<artifactId>spring-cloud-starter-openfeign</artifactId>


</dependency>


<dependency>


<groupId>org.mybatis.spring.boot</groupId>


<artifactId>mybatis-spring-boot-starter</artifactId>


</dependency>


<dependency>


<groupId>com.alibaba</groupId>


<artifactId>druid-spring-boot-starter</artifactId>


</dependency>


<dependency>


<groupId>mysql</groupId>


<artifactId>mysql-connector-java</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-jdbc</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-web</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-actuator</artifactId>


</dependency>


<dependency>


<groupId>org.projectlombok</groupId>


<artifactId>lombok</artifactId>


<optional>true</optional>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-test</artifactId>


<scope>test</scope>


</dependency>


</dependencies>


  1. yml


server:


port: 2001


spring:


application:


name: seata-order-service


cloud:


alibaba:


seata:


#自定义事务组名称需要与 seata-server 中的对应


tx-service-group: fsp_tx_group


nacos:


discovery:


server-addr: localhost:8848


datasource:


driver-class-name: com.mysql.jdbc.Driver


url: jdbc:mysql://localhost:3306/seata_order


username: "root"


password: "00000"


feign:


hystrix:


enabled: false


logging:


level:


io:


seata: info


mybatis:


mapperLocations: classpath:mapper/*.xml


  1. file.conf


transport {

tcp udt unix-domain-socket

type = "TCP"


#NIO NATIVE


server = "NIO"


#enable heartbeat


heartbeat = true


#thread factory for netty


thread-factory {


boss-thread-prefix = "NettyBoss"


worker-thread-prefix = "NettyServerNIOWorker"


server-executor-thread-prefix = "NettyServerBizHandler"


share-boss-worker = false


client-selector-thread-prefix = "NettyClientSelector"


client-selector-thread-size = 1


client-worker-thread-prefix = "NettyClientWorkerThread"

netty boss thread size,will not be used for UDT

boss-thread-size = 1


#auto default pin or 8


worker-thread-size = 8


}


shutdown {

when destroy server, wait seconds

wait = 3


}


serialization = "seata"


compressor = "none"


}


service {


vgroup_mapping.fsp_tx_group = "default" #修改自定义事务组名称


default.grouplist = "127.0.0.1:8091"


enableDegrade = false


disable = false


max.commit.retry.timeout = "-1"


max.rollback.retry.timeout = "-1"


disableGlobalTransaction = false


}


client {


async.commit.buffer.limit = 10000


lock {


retry.internal = 10


retry.times = 30


}


report.retry.count = 5


tm.commit.retry.count = 1


tm.rollback.retry.count = 1


}

transaction log store

store {

store mode: file、db

mode = "db"

file store

file {


dir = "sessionStore"

branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions

max-branch-session-size = 16384

globe session size , if exceeded throws exceptions

max-global-session-size = 512

file buffer size , if exceeded allocate new buffer

file-write-buffer-cache-size = 16384

when recover batch read size

session.reload.read_size = 100

async, sync

flush-disk-mode = async


}

database store

db {

the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.

datasource = "dbcp"

mysql/oracle/h2/oceanbase etc.

db-type = "mysql"


driver-class-name = "com.mysql.jdbc.Driver"


url = "jdbc:mysql://127.0.0.1:3306/seata"


user = "root"


password = "00000"


min-conn = 1


max-conn = 3


global.table = "global_table"


branch.table = "branch_table"


lock-table = "lock_table"


query-limit = 100


}


}


lock {

the lock store mode: local、remote

mode = "remote"


local {

store locks in user's database

}


remote {

store locks in the seata's server

}


}


recovery {


#schedule committing retry period in milliseconds


committing-retry-period = 1000


#schedule asyn committing retry period in milliseconds


asyn-committing-retry-period = 1000


#schedule rollbacking retry period in milliseconds


rollbacking-retry-period = 1000


#schedule timeout retry period in milliseconds


timeout-retry-period = 1000


}


transaction {


undo.data.validation = true


undo.log.serialization = "jackson"


undo.log.save.days = 7


#schedule delete expired undo_log in milliseconds


undo.log.delete.period = 86400000


undo.log.table = "undo_log"


}

metrics settings

metrics {


enabled = false


registry-type = "compact"

multi exporters use comma divided

exporter-list = "prometheus"


exporter-prometheus-port = 9898


}


support {

spring

spring {

auto proxy the DataSource bean

datasource.autoproxy = false


}


}


  1. registry.conf


registry {

file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

type = "nacos"


nacos {


serverAddr = "localhost:8848"


namespace = ""


cluster = "default"


}


eureka {


serviceUrl = "http://localhost:8761/eureka"


application = "default"


weight = "1"


}


redis {


serverAddr = "localhost:6379"


db = "0"


}


zk {


cluster = "default"


serverAddr = "127.0.0.1:2181"


session.timeout = 6000


connect.timeout = 2000


}


consul {


cluster = "default"


serverAddr = "127.0.0.1:8500"


}


etcd3 {


cluster = "default"


serverAddr = "http://localhost:2379"


}


sofa {


serverAddr = "127.0.0.1:9603"


application = "default"


region = "DEFAULT_ZONE"


datacenter = "DefaultDataCenter"


cluster = "default"


group = "SEATA_GROUP"


addressWaitTime = "3000"


}


file {


name = "file.conf"


}


}


config {

file、nacos 、apollo、zk、consul、etcd3

type = "file"


nacos {


serverAddr = "localhost"


namespace = ""


}


consul {


serverAddr = "127.0.0.1:8500"


}


apollo {


app.id = "seata-server"


apollo.meta = "http://192.168.1.204:8801"


}


zk {


serverAddr = "127.0.0.1:2181"


session.timeout = 6000


connect.timeout = 2000


}


etcd3 {


serverAddr = "http://localhost:2379"


}


file {


name = "file.conf"


}


}


  1. domain


CommonResult


@Data


@AllArgsConstructor


@NoArgsConstructor


public class CommonResult<T> {


private Integer code;


private String message;


private T data;


public CommonResult(Integer code, String message) {


this(code, message, null);


}


}


Order


@Data


@AllArgsConstructor


@NoArgsConstructor


public class Order {


private Long id;


private Long userId;


private Long productId;


private Integer count;


private BigDecimal money;


private Integer status; // 订单状态 0:创建中 1:已完结


}


  1. Dao


@Mapper


public interface OrderDao {


//1 新建订单


void create(Order order);


//2 修改订单状态,从 0 改为 1


void update(@Param("userId") Long userId, @Param("status") Integer status);


}


  1. mapper


OrderMapper.xml


<?xml version="1.0" encoding="UTF-8" ?>


<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.achang.springcloud.dao.OrderDao">


<resultMap id="BaseResultMap" type="com.achang.springcloud.domain.Order">


<id column="id" property="id" jdbcType="BIGINT"/>


<result column="user_id" property="userId" jdbcType="BIGINT"/>


<result column="product_id" property="productId" jdbcType="BIGINT"/>


<result column="count" property="count" jdbcType="INTEGER"/>


<result column="money" property="money" jdbcType="DECIMAL"/>


<result column="status" property="status" jdbcType="INTEGER"/>


</resultMap>


<insert id="create" parameterType="com.achang.springcloud.domain.Order"


useGeneratedKeys="true" keyProperty="id">


insert into t_order(user_id,product_id,count,money,status)


VALUES (#{userId}, #{productId}, #{count}, #{money}, 0)


</insert>


<update id="update" parameterType="com.achang.springcloud.domain.Order">


update t_order set status=1


where user_id=#{userId} and status=#{status}


</update>


</mapper>


  1. service


StorageService


@FeignClient(value = "seata-storage-service")


public interface StorageService {


@PostMapping(value = "/storage/decrease")


CommonResult decrease(@RequestParam("productId")Long productId,@RequestParam("count")Integer count);


}


AccountService


@FeignClient(value = "seata-account-service")


public interface AccountService {


@PostMapping(value = "/account/decrease")


CommonResult decrease(@RequestParam("userId")Long userId,@RequestParam("money") BigDecimal money);


OrderService


public interface OrderService {


public void create(Order order);


}


  1. impl


OderServiceImpl


@Service


@Slf4j


public class OrderServiceImpl implements OrderService {


@Resource


private OrderDao orderDao;


@Resource


private StorageService storageService;


@Resource


private AccountService accountService;


@Override


/**


  • 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态

  • 简单说:下订单->扣库存->减余额->改状态


*/


public void create(Order order) {


log.info("--------开始【新建订单】");


//1、新建订单


orderDao.create(order);


log.info("--------订单微服务开始调用【库存】,开始扣减库存数量");


//2、扣减库存


storageService.decrease(order.getProductId(),order.getCount());


log.info("--------订单微服务开始调用【库存】,结束扣减库存数量");


log.info("--------订单微服务开始调用【账户余额】,开始扣减钱");


//3、扣减账户余额


accountService.decrease(order.getUserId(),order.getMoney());


log.info("--------订单微服务开始调用【账户余额】,结束扣减钱");


//4、修改订单状态,从 0 到 1,1 代表已经完成


log.info("--------修改订单状态开始");


orderDao.update(order.getUserId(),0);


log.info("--------修改订单状态完成");


log.info("下订单结束了-----------------");


}


}


  1. controller


OrderController


@RestController


public class OrderController {


@Autowired


private OrderService orderService;


@GetMapping("/order/create")


public CommonResult create(Order order){


orderService.create(order);


return new CommonResult(200,"订单创建完成");


}


}


  1. config


MybatisConfig


@MapperScan("com.achang.springcloud.dao")


@Configuration


public class MybatisConfig {


}


DataSourceProxyConfig


package com.achang.springcloud.config;


import com.alibaba.druid.pool.DruidDataSource;


import io.seata.rm.datasource.DataSourceProxy;


import org.apache.ibatis.session.SqlSessionFactory;


import org.mybatis.spring.SqlSessionFactoryBean;


import org.mybatis.spring.transaction.SpringManagedTransactionFactory;


import org.springframework.beans.factory.annotation.Value;


import org.springframework.boot.context.properties.ConfigurationProperties;


import org.springframework.context.annotation.Bean;


import org.springframework.context.annotation.Configuration;


import org.springframework.core.io.support.PathMatchingResourcePatternResolver;


import javax.sql.DataSource;


//使用 Seata 对数据源进行代理


@Configuration


public class DataSourceProxyConfig {


@Value("${mybatis.mapperLocations}")


private String mapperLocations;


@Bean


@ConfigurationProperties(prefix = "spring.datasource")


public DataSource druidDataSource() {


return new DruidDataSource();


}


@Bean


public DataSourceProxy dataSourceProxy(DataSource dataSource) {


return new DataSourceProxy(dataSource);


}


@Bean


public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {


SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();


sqlSessionFactoryBean.setDataSource(dataSourceProxy);


sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));


sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());


return sqlSessionFactoryBean.getObject();


}


}


  1. 主启动类


@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) //取消数据源的自动创建


@EnableDiscoveryClient


@EnableFeignClients


public class SeataOrderMain2001 {


public static void main(String[] args) {


SpringApplication.run(SeataOrderMain2001.class,args);


}


}


  1. 启动 2001




官方列举的常见问题:https://seata.io/zh-cn/docs/overview/faq.html



[](()库存模块


  1. 新建模块 seata-storage-service2002

  2. pom


<dependencies>


<dependency>


<groupId>com.alibaba.cloud</groupId>


<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>


</dependency>


<dependency>


<groupId>com.alibaba.cloud</groupId>


<artifactId>spring-cloud-starter-alibaba-seata</artifactId>


<exclusions>


<exclusion>


<groupId>io.seata</groupId>


<artifactId>seata-all</artifactId>


</exclusion>


</exclusions>


</dependency>


<dependency>


<groupId>io.seata</groupId>


<artifactId>seata-all</artifactId>


<version>1.0.0</version>


</dependency>


<dependency>


<groupId>org.springframework.cloud</groupId>


<artifactId>spring-cloud-starter-openfeign</artifactId>


</dependency>


<dependency>


<groupId>org.mybatis.spring.boot</groupId>


<artifactId>mybatis-spring-boot-starter</artifactId>


</dependency>


<dependency>


<groupId>com.alibaba</groupId>


<artifactId>druid-spring-boot-starter</artifactId>


</dependency>


<dependency>


<groupId>mysql</groupId>


<artifactId>mysql-connector-java</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-jdbc</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-web</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-actuator</artifactId>


</dependency>


<dependency>


<groupId>org.projectlombok</groupId>


<artifactId>lombok</artifactId>


<optional>true</optional>


</dependency>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-test</artifactId>


<scope>test</scope>


</dependency>


</dependencies>


  1. yml


server:


port: 2002


spring:


application:


name: seata-storage-service


cloud:


alibaba:


seata:


tx-service-group: fsp_tx_group


nacos:


discovery:


server-addr: localhost:8848


datasource:


driver-class-name: com.mysql.jdbc.Driver


url: jdbc:mysql://localhost:3306/seata_storage


username: "root"


password: "00000"


logging:


level:


io:


seata: info


mybatis:


mapperLocations: classpath:mapper/*.xml


  1. file.conf


transport {

tcp udt unix-domain-socket

type = "TCP"


#NIO NATIVE


server = "NIO"


#enable heartbeat


heartbeat = true


#thread factory for netty


thread-factory {


boss-thread-prefix = "NettyBoss"


worker-thread-prefix = "NettyServerNIOWorker"


server-executor-thread-prefix = "NettyServerBizHandler"


share-boss-worker = false


client-selector-thread-prefix = "NettyClientSelector"


client-selector-thread-size = 1


client-worker-thread-prefix = "NettyClientWorkerThread"

netty boss thread size,will not be used for UDT

boss-thread-size = 1


#auto default pin or 8


worker-thread-size = 8


}


shutdown {

when destroy server, wait seconds

wait = 3


}


serialization = "seata"


compressor = "none"


}


service {


vgroup_mapping.fsp_tx_group = "default" #修改自定义事务组名称


default.grouplist = "127.0.0.1:8091"


enableDegrade = false


disable = false


max.commit.retry.timeout = "-1"


max.rollback.retry.timeout = "-1"


disableGlobalTransaction = false


}


client {


async.commit.buffer.limit = 10000


lock {


retry.internal = 10


retry.times = 30


}


report.retry.count = 5


tm.commit.retry.count = 1


tm.rollback.retry.count = 1


}

transaction log store

store {

store mode: file、db

mode = "db"

file store

file {


dir = "sessionStore"

branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions

max-branch-session-size = 16384

globe session size , if exceeded throws exceptions

max-global-session-size = 512

file buffer size , if exceeded allocate new buffer

file-write-buffer-cache-size = 16384

when recover batch read size

session.reload.read_size = 100

async, sync

flush-disk-mode = async


}

database store

db {

the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.

datasource = "dbcp"

mysql/oracle/h2/oceanbase etc.

db-type = "mysql"


driver-class-name = "com.mysql.jdbc.Driver"


url = "jdbc:mysql://127.0.0.1:3306/seata"


user = "root"


password = "00000"


min-conn = 1


max-conn = 3


global.table = "global_table"


branch.table = "branch_table"


lock-table = "lock_table"


query-limit = 100


}


}


lock {

the lock store mode: local、remote

mode = "remote"


local {

store locks in user's database

}


remote {

store locks in the seata's server

}


}


recovery {


#schedule committing retry period in milliseconds


committing-retry-period = 1000


#schedule asyn committing retry period in milliseconds


asyn-committing-retry-period = 1000


#schedule rollbacking retry period in milliseconds


rollbacking-retry-period = 1000


#schedule timeout retry period in milliseconds


timeout-retry-period = 1000


}


transaction {


undo.data.validation = true


undo.log.serialization = "jackson"


undo.log.save.days = 7


#schedule delete expired undo_log in milliseconds


undo.log.delete.period = 86400000


undo.log.table = "undo_log"


}

metrics settings

metrics {


enabled = false


registry-type = "compact"

multi exporters use comma divided

exporter-list = "prometheus"


exporter-prometheus-port = 9898


}


support {

spring

spring {

auto proxy the DataSource bean

datasource.autoproxy = false


}


}


  1. registry.conf


registry {

file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

type = "nacos"


nacos {


serverAddr = "localhost:8848"


namespace = ""


cluster = "default"


}


eureka {


serviceUrl = "http://localhost:8761/eureka"


application = "default"


weight = "1"


}


redis {


serverAddr = "localhost:6379"


db = "0"


}


zk {


cluster = "default"


serverAddr = "127.0.0.1:2181"


session.timeout = 6000


connect.timeout = 2000


}


consul {


cluster = "default"


serverAddr = "127.0.0.1:8500"


}


etcd3 {


cluster = "default"


serverAddr = "http://localhost:2379"


}


sofa {


serverAddr = "127.0.0.1:9603"


application = "default"


region = "DEFAULT_ZONE"


datacenter = "DefaultDataCenter"


cluster = "default"


group = "SEATA_GROUP"


addressWaitTime = "3000"


}


file {


name = "file.conf"


}


}


config {

file、nacos 、apollo、zk、consul、etcd3

type = "file"


nacos {


serverAddr = "localhost"


namespace = ""


}


consul {


serverAddr = "127.0.0.1:8500"


}


apollo {


app.id = "seata-server"


apollo.meta = "http://192.168.1.204:8801"


}


zk {


serverAddr = "127.0.0.1:2181"


session.timeout = 6000


connect.timeout = 2000


}


etcd3 {


serverAddr = "http://localhost:2379"


}


file {


name = "file.conf"


}


}


  1. domain


CommonResult


@Data


@AllArgsConstructor


@NoArgsConstructor


public class CommonResult<T> {


private Integer code;


private String message;


private T data;


public CommonResult(Integer code, String message) {


this(code, message, null);


}


}


Storage


@Data


@AllArgsConstructor


@NoArgsConstructor


public class Storage {


private Long id;


private Long productId;


private Integer total;


private Integer used;


private Integer residue;


}


  1. dao


@Mapper


public interface StorageDao {


void decrease(@Param("productId") Long productId, @Param("count") Integer count);


}


  1. mapper


StorageMapper.xml


<?xml version="1.0" encoding="UTF-8" ?>


<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.achang.springcloud.dao.StorageDao">


<resultMap id="BaseResultMap" type="com.achang.springcloud.domain.Storage">


<id column="id" property="id" jdbcType="BIGINT"/>


<result column="product_id" property="productId" jdbcType="BIGINT"/>


<result column="total" property="total" jdbcType="INTEGER"/>


<result column="used" property="used" jdbcType="INTEGER"/>


<result column="residue" property="residue" jdbcType="INTEGER"/>


</resultMap>


<update id="decrease">


UPDATE


t_storage


SET


used = used + #{count},residue = residue - #{count}


WHERE


product_id = #{productId}


</update>


</mapper>


  1. service


StorageService


public interface StorageService {


void decrease(Long productId, Integer count);


}


  1. impl


StorageServiceImpl


@Service


@Slf4j


public class OderServiceImpl implements StorageService {


@Resource


private StorageDao storageDao;


@Override


public void decrease(Long productId, Integer count) {


log.info("----> StorageService 中扣减库存");


storageDao.decrease(productId, count);


log.info("----> StorageService 中扣减库存完成");


}


}


  1. controller


StorageController


@RestController


public class StorageController {


@Resource


private StorageService storageService;


@RequestMapping("/storage/decrease")


public CommonResult decrease(Long productId,Integer count){


storageService.decrease(productId, count);

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Day193_Java_爱好编程进阶_InfoQ写作社区