Seata 篇
在传统的单体架构中的事务是基于连接级别的,一个连接只能对应一个数据库,但是微服务中存在多个数据库的操作。
1、Seata的原理
涉及三个角色:
-
TC:事务协调者,维护全局和分支事务的状态
-
TM:事务管理器,开启全局事务、提交、回滚全局事务
-
RM:资源管理器,处理分支事务,与TC通讯以注册分支事务和报告分支事务的状态,驱动分支事务提交或回滚
Seata的AT模式
seate提供了多种事务模式:
-
AT模式(默认)提供无侵入自动补偿的事务模式
-
TCC模式
-
SAGA模式,适用于长事务
-
XA模式
seata采用的是二次提交方式来处理分布式事务:
2、seata部署
通过docker的方式来进行部署。在许多的网站中讲述的都是在windows下部署seata服务,这我尝试了好久才完成在linux中的docker里面部署seata,当然,云服务器可能会有更便捷的方式。
2.1、获取配置文件
# 获取配置文件
# 1、创建临时的容器
docker run -d --name temp -p 8091:8091 -p 7091:7091 seataio/seata-server
# 2、复制配置文件夹,其实复制文件也行,但是文件夹中有修改的示例代码,就复制文件夹吧
docer cp temp:/seata-server/resources 目的路径,比如放到/home/Taurus/seata/config中
# 复制完成之后在目的路径下有个resource文件夹,里面就有配置文件
这里通过1panel的控制面板来显示结果,方式有多种,比如把配置文件复制到当前电脑,修改完成之后再上传等
其中示例代码就在application.example.yml中,而application.yml就是我修改的文件
如果在1panel中,可以点击打开进行编辑 application.example.yml
# Example.yml的内容
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
seata:
config:
# support: nacos 、 consul 、 apollo 、 zk 、 etcd3
type: file
nacos:
server-addr: 127.0.0.1:8848
namespace:
group: SEATA_GROUP
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
data-id: seataServer.properties
consul:
server-addr: 127.0.0.1:8500
acl-token:
key: seata.properties
apollo:
appId: seata-server
apollo-meta: http://192.168.1.204:8801
apollo-config-service: http://192.168.1.204:8080
namespace: application
apollo-access-key-secret:
cluster: seata
zk:
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username:
password:
node-path: /seata/seata.properties
etcd3:
server-addr: http://localhost:2379
key: seata.properties
registry:
# support: nacos 、 eureka 、 redis 、 zk 、 consul 、 etcd3 、 sofa
type: file
preferred-networks: 30.240.*
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace:
cluster: default
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
eureka:
service-url: http://localhost:8761/eureka
application: default
weight: 1
redis:
server-addr: localhost:6379
db: 0
password:
cluster: default
timeout: 0
zk:
cluster: default
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username:
password:
consul:
cluster: default
server-addr: 127.0.0.1:8500
acl-token:
etcd3:
cluster: default
server-addr: http://localhost:2379
sofa:
server-addr: 127.0.0.1:9603
application: default
region: DEFAULT_ZONE
datacenter: DefaultDataCenter
cluster: default
group: SEATA_GROUP
address-wait-time: 3000
server:
service-port: 8091 #If not configured, the default is '${server.port} + 1000'
max-commit-retry-timeout: -1
max-rollback-retry-timeout: -1
rollback-failed-unlock-enable: false
enable-check-auth: true
enable-parallel-request-handle: true
retry-dead-threshold: 130000
xaer-nota-retry-timeout: 60000
enableParallelRequestHandle: true
recovery:
committing-retry-period: 1000
async-committing-retry-period: 1000
rollbacking-retry-period: 1000
timeout-retry-period: 1000
undo:
log-save-days: 7
log-delete-period: 86400000
session:
branch-async-queue-size: 5000 #branch async remove queue size
enable-branch-async-remove: false #enable to asynchronous remove branchSession
store:
# support: file 、 db 、 redis
mode: file
session:
mode: file
lock:
mode: file
file:
dir: sessionStore
max-branch-session-size: 16384
max-global-session-size: 512
file-write-buffer-cache-size: 16384
session-reload-read-size: 100
flush-disk-mode: async
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
user: mysql
password: mysql
min-conn: 10
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
redis:
mode: single
database: 0
min-conn: 10
max-conn: 100
password:
max-total: 100
query-limit: 1000
single:
host: 127.0.0.1
port: 6379
sentinel:
master-name:
sentinel-hosts:
sentinel-password:
metrics:
enabled: false
registry-type: compact
exporter-list: prometheus
exporter-prometheus-port: 9898
transport:
rpc-tc-request-timeout: 15000
enable-tc-server-batch-send-response: false
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
boss-thread-size: 1
application.yml
# application.yml的内容
server:
# 这个是seata微服务的端口号,用于网页浏览
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console:
user:
username: seata
password: seata
###### 主要修改下面的几个配置 #########
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: file
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: file
store:
# support: file 、 db 、 redis 、 raft
mode: file
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/health,/error
首先是配置中心:seata的配置中心支持多种类型框架,就如上面提到的file文件方式,nacos方式等,这里使用nacos为例
-
配置中心的 type 设置为nacos
-
然后将example.yml的示例代码复制过来
nacos:
# nacos 微服务的地址和端口号,根据自己的微服务地址进行修改
server-addr: 127.0.0.1:8848
# 命名空间,默认是public
namespace:
# nacos 分组
group: SEATA_GROUP
# 以下的如果没有特别的设置可以不用设置,可直接注释
# username:
# password:
# context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
# 这个data-id的值可以修改,但是得对应nacos的DataID的值
data-id: seataServer.properties
注册中心同理
nacos:
# nacos微服务的名称
application: seata-server
# nacos 微服务的地址和端口号,根据自己的微服务地址进行修改
server-addr: 127.0.0.1:8848
# nacos 分组
group: SEATA_GROUP
# 命名空间,默认是public
namespace:
# 集群,这个于后面的配置有关联
cluster: default
# 以下的如果没有特别的设置可以不用设置,可直接注释
# username:
# password:
# context-path:
#access-key:
#secret-key:
配置完成之后大概就是这个样子
```yaml
# application.yml的内容
server:
# 这个是seata微服务的端口号,用于网页浏览
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console:
user:
username: seata
password: seata
###### 主要修改下面的几个配置 #########
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 10.0.0.100:8848
namespace: 配置的命名空间,默认public
group: SEATA_GROUP
username: nacos
password: nacos
data-id: seataServer.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 10.0.0.100:8848
group: SEATA_GROUP
namespace: 配置的命名空间,默认public
cluster: default
username: nacos
password: nacos
store:
# support: file 、 db 、 redis 、 raft
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.0.0.100:3306/seata?rewriteBatchedStatements=true
user: root
password: 123456
min-conn: 10
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/health,/error
2.2、docker运行seata服务(单个服务)
sudo docker run -d \
--name seata-service \
-p 8091:8091 \
-p 7091:7091 \
-v /home/Taurus/seata/config/resource/application.yml:/seata-server/resources/application.yml \
-e SEATA_IP=10.0.0.100
seataio/seata-server
参数说明:
-
--name 是docker应用的名称,不是微服务的名称
-
-d 后台运行
-
-p 端口映射
-
-v 文件挂在,宿主机目录地址 : docker内部目录地址
-
-e 环境变量设置,默认没有设置的情况下,在nacos的详情中可以发现注册的IP地址为docker内部的IP地址,docker内部的IP地址一般不会暴露给外部访问,得通过宿主机的端口转发
-
最后是docker镜像
运行之后再nacos中查看结果是否成功的将seata服务注册到nacos中
查看IP与端口是否正确,如果不设置seata_IP,默认就是docker内部的绘制,下面有环境变量的说明
环境变量的说明:
seata的支持的环境变量有:
-
SEATA_IP 可选, 指定seata-server启动的IP, 该IP用于向注册中心注册时使用, 如eureka等
-
SEATA_PORT 可选, 指定seata-server启动的端口, 默认为
8091
,这是docker内部的端口号,不是外部的,一般使用集群时才做修改,这个时seata工作端口,7091是webUI 端口 -
STORE_MODE 可选, 指定seata-server的事务日志存储方式, 支持
db
,file
,redis(Seata-Server 1.3及以上版本支持), 默认是file
,这个可以在配置文件中配置 -
SERVER_NODE 可选, 用于指定seata-server节点ID, 如
1
,2
,3
..., 默认为根据ip生成
集群中使用 -
SEATA_ENV 可选, 指定 seata-server 运行环境, 如
dev
,test
等, 服务启动时会使用registry-dev.conf
这样的配置 -
SEATA_CONFIG_NAME 可选, 指定配置文件位置, 如
file:/root/registry
, 将会加载/root/registry.conf
作为配置文件,如果需要同时指定file.conf
文件,需要将registry.conf
的config.file.name
的值改为类似file:/root/file.conf
:
扩展 - 集群部署(多个服务)
如果在一个机器设备上部署多个TCdocker服务,只需对docker运行的命令进行相应的修改,示例:
# 第一个服务
sudo docker run -d \
--name seata-service \ # 容器名不能重复也是需要主注意的
-p 8091:8091 \ # 这个后面的端口号要于环境变量设置的端口号一致,此服务使用的是默认的方式,即最后面两个的可以不写,默认就是这值
-p 7091:7091 \
-v /home/Taurus/seata/config/resource/application.yml:/seata-server/resources/application.yml \
-e SEATA_IP=10.0.0.100
-e SEATA_PORT=8091
-e SERVER_NODE=1
seataio/seata-server
# 第二个服务
sudo docker run -d \
--name seata-service2 \ # 容器名不能重复也是需要主注意的
-p 8092:8094 \ # 这个后面的端口号要于环境变量 SEATA_PORT=8094 设置的端口号一致,外部的端口要也需要相应的修改,因为宿主机的8091、7091端口号已经被第一个服务所占用
-p 7092:7091 \
-v /home/Taurus/seata/config/resource/application.yml:/seata-server/resources/application.yml \
-e SEATA_IP=10.0.0.100
-e SEATA_PORT=8094
-e SERVER_NODE=2 # 节点编号,默认是1
seataio/seata-server
2.3、上传配置到nacos
-
从 v1.4.2 版本开始,已支持从一个 Nacos dataId 中获取所有配置信息,你只需要额外添加一个 dataId 配置项。
-
首先你需要在 nacos 新建配置,此处 dataId 为 seataServer.properties,这个名称与前面seata的配置文件application.yml中的命名相一致,配置内容参考https://github.com/apache/incubator-seata/tree/develop/script/config-center 的 config.txt 并按需修改保存,详细的文件内容就不在此处显示
2.4、客户端配置(需要使用到分布式事务的都要配置)
seata:
# 配置中心配置
config:
type: nacos
nacos:
server-addr: 10.0.0.100:8848
namespace: CloudMusic
group: SEATA_GROUP
username: nacos
password: nacos
# 与服务端公用同一个配置文件,里面有client的配置信息,也有server的配置信息,这个必须,否则配置中心会失败,出现scan不到等错误
data-id: seataServer.properties
# 注册中心
registry:
type: nacos
nacos:
server-addr: 10.0.0.100:8848
namespace: CloudMusic
group: SEATA_GROUP
username: nacos
password: nacos
# 这个必填,与前面2.3要上传的配置 service.vgroupMapping.location=default 相一致
tx-service-group: location
可以直接放到nacos上,然后config.include 导入配置文件即可。
同时在每一个数据库中都添加undo_log的表,通过debug的方式可以看到结果
2.5 使用Seata
在需要事务的方法上加上@GlobalTransational的注解
然后在分支上添加@Transactional本地注解
如果想看到效果,可以通过debug模式查看
seata webUI界面中的信息