Copy#事务组 重点关注

service.vgroupMapping.my_test_tx_group=default

#服务段分组地址

service.default.grouplist=127.0.0.1:8091

#保持默认

service.enableDegrade=false

#保持默认

service.disableGlobalTransaction=false

#存储方式选择 db模式则数据库

store.mode=db

#需修改

store.lock.mode=db

#需修改

store.session.mode=db

store.publicKey=

#需修改

store.db.datasource=druid

#需修改

store.db.dbType=mysql

#需修改

store.db.driverClassName=com.mysql.jdbc.Driver

#需修改

store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true

#需修改

store.db.user=root

#需修改

store.db.password=123456

store.db.minConn=5

store.db.maxConn=30

store.db.globalTable=global_table

store.db.branchTable=branch_table

store.db.distributedLockTable=distributed_lock

store.db.queryLimit=100

store.db.lockTable=lock_table

store.db.maxWait=5000

client.undo.dataValidation=true

#需修改

#jackson改为kryo 解决数据库Datetime类型问题

client.undo.logSerialization=kryo

client.undo.onlyCareUpdateColumns=true

server.undo.logSaveDays=7

server.undo.logDeletePeriod=86400000

client.undo.logTable=undo_log

client.undo.compress.enable=true

client.undo.compress.type=zip

client.undo.compress.threshold=64k

log.exceptionRate=100

transport.serialization=seata

transport.compressor=none

其中该配置需要重点关注service.vgroupMapping.my_test_tx_group=default这里的配置与微服务应用中的配置必须要一致后面会描述到。

由于有时间类型是Seata回滚反序列化Date类型无法成功反序列化,需要修改序列化方式解决该问题: client.undo.logSerialization=kryo

修改完所有配置运行从官网下载的nacos-config.sh文件将文本内容上次到nacos配置中心中:

Copy# -h ip -p 端口 -t 命名空间 -g 分组

sh nacos-config.sh -h localhost -p 8848 -t 7e3699fa-09eb-4d47-8967-60f6c98da94a -g EXAMPLE-GROUP

部署好配置文件之后在Nacos命名空间为7e3699fa-09eb-4d47-8967-60f6c98da94a(dev)的配置管理界面可以看到文本中的内容。

Spring Cloud Alibaba使用Seata解决分布式事务全过程解析

Seata数据库

========

按照config.txt中对应的数据库连接信息创建Seata数据库并且创建以下几张表

CopyCREATE TABLE IF NOT EXISTS global_table

(

xid VARCHAR(128) NOT NULL,

transaction_id BIGINT,

status TINYINT NOT NULL,

application_id VARCHAR(32),

transaction_service_group VARCHAR(32),

transaction_name VARCHAR(128),

timeout INT,

begin_time BIGINT,

application_data VARCHAR(2000),

gmt_create DATETIME,

gmt_modified DATETIME,

PRIMARY KEY (xid),

KEY idx_gmt_modified_status (gmt_modified, status),

KEY idx_transaction_id (transaction_id)

) ENGINE = InnoDB

DEFAULT CHARSET = utf8;

– the table to store BranchSession data

CREATE TABLE IF NOT EXISTS branch_table

(

branch_id BIGINT NOT NULL,

xid VARCHAR(128) NOT NULL,

transaction_id BIGINT,

resource_group_id VARCHAR(32),

resource_id VARCHAR(256),

branch_type VARCHAR(8),

status TINYINT,

client_id VARCHAR(64),

application_data VARCHAR(2000),

gmt_create DATETIME(6),

gmt_modified DATETIME(6),

PRIMARY KEY (branch_id),

KEY idx_xid (xid)

) ENGINE = InnoDB

DEFAULT CHARSET = utf8;

– the table to store lock data

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;

部署Seata Server

==============

以上工作准备就绪,进入bin目录运行seata-server.bat(windows用户)/seata-server.sh(linux用户)即可。

Seata应用场景模拟#

============

这里做一个用户服务用户登录成功后调用会员服务增加会员积分场景案例。

父工程改造

=====

工程名称:spring-cloud-alibaba-version-parent,增加mybatis,seata序列化等依赖版本管理。

Copy

<mybatis.plus.version>3.4.2</mybatis.plus.version>

<mybatis.plus.ds.version>2.5.4</mybatis.plus.ds.version>

<seata.serializer.kryo.version>1.3.0</seata.serializer.kryo.version>

com.baomidou

mybatis-plus-boot-starter

${mybatis.plus.version}

io.seata

seata-serializer-kryo

${seata.serializer.kryo.version}

会员服务工程改造

========

工程名称:spring-cloud-alibaba-service-member,增加数据库与Seata依赖,增加用户会员积分接口。

pom.xml

Copy

com.alibaba.cloud

spring-cloud-starter-alibaba-seata

io.seata

seata-serializer-kryo

com.baomidou

mybatis-plus-boot-starter

mysql

mysql-connector-java

bootstrap.yaml

Copy#注意,此处省略之前配置的信息…

#注意,此处省略之前配置的信息…

#注意,此处省略之前配置的信息…

#注意,此处省略之前配置的信息…

#数据库信息配置

spring:

datasource:

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

url: jdbc:mysql://localhost:3306/member_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true

username: root

password: 123456

#Seata配置

seata:

enabled: true

application-id: ${spring.application.name}

#对应nacos配置 service.vgroupMapping.my_test_tx_group

tx-service-group: ‘my_test_tx_group’

service:

vgroup-mapping:

#对应nacos配置 service.vgroupMapping.my_test_tx_group 的值 default

my_test_tx_group: ‘default’

registry:

type: nacos

nacos:

server-addr: ${spring.cloud.nacos.discovery.server-addr}

namespace: ${spring.cloud.nacos.discovery.namespace}

group: ${spring.cloud.nacos.discovery.group}

#cluster: ${spring.cloud.nacos.discovery.cluster}

config:

type: nacos

nacos:

server-addr: ${spring.cloud.nacos.discovery.server-addr}

namespace: ${spring.cloud.nacos.discovery.namespace}

group: ${spring.cloud.nacos.discovery.group}

注意事项:

  1. bootstrap.yaml中seata.tx-service-group 配置项一定要配置nacos配置中心中service.vgroupMapping对应的my_test_tx_group。也就是说一定要保持一致。

  2. bootstrap.yaml中seata.service.vgroup-mapping.my_test_tx_group配置项一定要配置nacos配置中心对应service.vgroupMapping.my_test_tx_group配置祥的值。

如果没有注意上方两点将会导致启动时报:no available service ‘default’ found, please make sure registry config correct。

创建member_db数据库

其中undo_log表为Seata回滚日志表,需要在每个使用到Seata的业务服务数据库中都需要创建。

CopySET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;


– Table structure for t_member_integral


DROP TABLE IF EXISTS t_member_integral;

CREATE TABLE t_member_integral (

ID bigint(20) NOT NULL COMMENT ‘主键’,

USERNAME varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘用户名称’,

INTEGRAL int(11) DEFAULT NULL COMMENT ‘积分’,

CREDATE datetime(0) DEFAULT NULL COMMENT ‘时间’,

PRIMARY KEY (ID) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;


– Table structure for undo_log


DROP TABLE IF EXISTS undo_log;

CREATE TABLE undo_log (

id bigint(20) NOT NULL AUTO_INCREMENT,

branch_id bigint(20) NOT NULL,

xid varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

context varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

rollback_info longblob NOT NULL,

log_status int(11) NOT NULL,

log_created datetime(0) NOT NULL,

log_modified datetime(0) NOT NULL,

ext varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,

PRIMARY KEY (id) USING BTREE,

UNIQUE INDEX ux_undo_log(xid, branch_id) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

新增会员积分CRUD

我这里新增以下类,具体内容大家都比较熟悉。

CopyMemberIntegralController.java

IMemberIntegralBiz.java

IMemberIntegralBizImpl.java

MemberIntegralMapper.java

MemberIntegral.xml

在这里所有增加会员积分的逻辑都写在同一个类中 MemberIntegralController.java

Copyimport com.baomidou.mybatisplus.core.toolkit.IdWorker;

import com.gitee.eample.member.service.biz.IMemberIntegralBiz;

import com.gitee.eample.member.service.domain.MemberIntegral;

import com.gtiee.example.common.exception.Response;

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

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**

  • 用户积分

  • @author wentao.wu

*/

@RestController

@RequestMapping(“/member/integral”)

public class MemberIntegralController {

@Autowired

private IMemberIntegralBiz memberIntegralBiz;

@PostMapping(“/login/{username}”)

public Response login(@PathVariable(“username”) String username) {

// 每天第一次登录则增加积分,我这里就不判断了,每次调用都新增一条积分记录了

MemberIntegral memberIntegral = new MemberIntegral();

memberIntegral.setId(IdWorker.getId());

memberIntegral.setIntegral(10);//固定10积分

memberIntegral.setUsername(username);

memberIntegral.setCredate(new Date());

memberIntegralBiz.save(memberIntegral);

return Response.createOk(“登录新增会员积分成功!”, true);

}

}

运行MemberServiceApplication.java启动服务,如果想知道有没有注册成功:

第一可以看Seata Server端有没有日志输出,该日志内容主要为注册的业务服务的数据库信息。

第二可以看业务服务有没有输出以下日志,有输出以下日志则Seata Server端注册成功

Copy2021-11-05 09:56:30.962 INFO 16420 — [ main] i.s.c.r.netty.NettyClientChannelManager : will connect to 2.0.4.58:8091

2021-11-05 09:56:30.962 INFO 16420 — [ main] i.s.c.rpc.netty.RmNettyRemotingClient : RM will register :jdbc:mysql://localhost:3306/member_db

2021-11-05 09:56:30.967 INFO 16420 — [ main] i.s.core.rpc.netty.NettyPoolableFactory : NettyPool create channel to transactionRole:RMROLE,address:2.0.4.58:8091,msg:< RegisterRMRequest{resourceIds=‘jdbc:mysql://localhost:3306/member_db’, applicationId=‘service-member’, transactionServiceGroup=‘my_test_tx_group’} >

用户服务工程改造

========

工程名称:spring-cloud-alibaba-service-member,增加数据库与Seata依赖,增加用户登录接口,增加调用会员服务积分接口feign。

由于内容一致此处省略pom.xml,bootstrap.xml(里面注意数据库要修改为用户服务的数据库)。

创建user_db数据库

其中undo_log表为Seata回滚日志表,需要在每个使用到Seata的业务服务数据库中都需要创建。

Copy

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;


– Table structure for t_user


DROP TABLE IF EXISTS t_user;

CREATE TABLE t_user (

ID bigint(20) NOT NULL COMMENT ‘主键’,

USERNAME varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘用户名’,

PWD varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘密码’,

ADDR varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘地址’,

LAST_LOGIN_DATE datetime(0) DEFAULT NULL COMMENT ‘最后登录时间’,

PRIMARY KEY (ID) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;


– Records of t_user


INSERT INTO t_user VALUES (1, ‘test1’, ‘123456’, ‘123’, NULL);


– Table structure for undo_log


DROP TABLE IF EXISTS undo_log;

CREATE TABLE undo_log (

id bigint(20) NOT NULL AUTO_INCREMENT,

branch_id bigint(20) NOT NULL,

xid varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

context varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

rollback_info longblob NOT NULL,

log_status int(11) NOT NULL,

log_created datetime(0) NOT NULL,

log_modified datetime(0) NOT NULL,

ext varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,

PRIMARY KEY (id) USING BTREE,

UNIQUE INDEX ux_undo_log(xid, branch_id) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

新增用户登录CRUD

我这里新增以下类,具体内容大家都比较熟悉。

CopyUserController.java

IUserBiz.java

IUserBizImpl.java

UserMapper.java

UserMapper.xml

MemberInfoControllerClient.java

MemberInfoControllerClient.java

Copy/**

  • service-member服务远程调用接口

  • @author wentao.wu

*/

@FeignClient(name = “service-member”)

public interface MemberInfoControllerClient {

/**

  • 登录送积分

  • @param username

  • @return

*/

@PostMapping(“/member/integral/login/{username}”)

Response login(@PathVariable(“username”)String username);

}

IUserBiz.java

Copypublic interface IUserBiz extends IService {

/**

  • 用户登录并且赠送第一次登录积分

  • @param command

  • @return

*/

boolean login(UserLoginCommand command);

}

IUserBizImpl.java

Copypackage com.gitee.eample.user.service.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.gitee.eample.user.service.controller.command.UserLoginCommand;

import com.gitee.eample.user.service.dao.UserMapper;

import com.gitee.eample.user.service.domain.User;

import com.gitee.eample.user.service.feign.MemberInfoControllerClient;

import com.gtiee.example.common.exception.Response;

import io.seata.spring.annotation.GlobalTransactional;

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

import org.springframework.stereotype.Service;

import org.springframework.util.ObjectUtils;

import java.util.Date;

@Service

public class IUserBizImpl extends ServiceImpl<UserMapper, User> implements IUserBiz {

@Autowired

private MemberInfoControllerClient client;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

虽然我个人也经常自嘲,十年之后要去成为外卖专员,但实际上依靠自身的努力,是能够减少三十五岁之后的焦虑的,毕竟好的架构师并不多。

架构师,是我们大部分技术人的职业目标,一名好的架构师来源于机遇(公司)、个人努力(吃得苦、肯钻研)、天分(真的热爱)的三者协作的结果,实践+机遇+努力才能助你成为优秀的架构师。

如果你也想成为一名好的架构师,那或许这份Java成长笔记你需要阅读阅读,希望能够对你的职业发展有所帮助。

image

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

…(img-d2fGGhiU-1712183610280)]
[外链图片转存中…(img-ZWcXRpEe-1712183610280)]
[外链图片转存中…(img-Obh6sC4R-1712183610281)]
[外链图片转存中…(img-8CwwNIJw-1712183610281)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-FYf0ahxk-1712183610282)]

总结

虽然我个人也经常自嘲,十年之后要去成为外卖专员,但实际上依靠自身的努力,是能够减少三十五岁之后的焦虑的,毕竟好的架构师并不多。

架构师,是我们大部分技术人的职业目标,一名好的架构师来源于机遇(公司)、个人努力(吃得苦、肯钻研)、天分(真的热爱)的三者协作的结果,实践+机遇+努力才能助你成为优秀的架构师。

如果你也想成为一名好的架构师,那或许这份Java成长笔记你需要阅读阅读,希望能够对你的职业发展有所帮助。

[外链图片转存中…(img-73kAZma2-1712183610282)]

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐