【Spring】SpringCloudAlibaba学习笔记

Nacos

  1. Nacos是一个更易于构建云原生应用的动态服务发现/服务配置服务管理平台
  2. 核心功能:
    1. 服务注册: Nacos Client会通过发送REST请求向Nacos Server注册自己的服务, 提供自己的元数据, 如ip地址/端口等信息; Nacos Server收到注册请求后, 就会把这些信息存储在Map中
    2. 服务心跳: 在服务注册后, Nacos Client会维护一个定时心跳来持续通知Nacos Server, 说明服务一致处于可用状态, 防止被剔除 默认5s发送一次心跳
    3. 服务发现: 服务消费者在调用服务提供者的服务时, 会发送一个REST请求给Nacos Server, 获取上面注册的服务清单, 并且缓存在Nacos Client本地; 同时在Nacos Client本地开启一个定时任务定时拉取最新的注册表信息到本地缓存
    4. 服务健康检查: Nacos Server会开启一个定时任务来检查注册服务实例的健康情况, 对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false; 如果某个实例超过30s没有收到心跳, 直接剔除该实例

主流注册中心对比

指标NacosEurekaConsulCoreDNSZookeeper
一致性协议CP/APAPCP-CP
健康检查TCP/HTTP/MySQL/Client BeatClient BeatTCP/HTTP/gRPC/Cmd--
负载均衡策略权重/metadata/SelectorRibbonFabioRoundRobin-
雪崩保护
自动注销实例支持支持支持不支持支持
访问协议HTTP/DNSHTTPHTTP/DNSDNSTCP
监听支持支持支持支持不支持支持
多数据中心支持支持支持不支持不支持
跨注册中心同步支持不支持支持不支持不支持
SpringCloud集成支持不支持支持不支持支持
Dubbo集成支持不支持支持不支持支持
K8S集成支持不支持支持支持不支持

基本使用

集群部署1

apiVersion: v1
kind: Service
metadata:name: nacos-svc
spec:type: LoadBalancerports:- port: 8848name: servertargetPort: 8848- port: 9848name: client-rpctargetPort: 9848- port: 9849name: raft-rpctargetPort: 9849## 兼容1.4.x版本的选举端口- port: 7848name: old-raft-rpctargetPort: 7848selector:app: nacos
---
apiVersion: v1
kind: Service
metadata:name: nacos-headlesslabels:app: nacos-headless
spec:type: ClusterIPclusterIP: Noneports:- port: 8848name: servertargetPort: 8848- port: 9848name: client-rpctargetPort: 9848- port: 9849name: raft-rpctargetPort: 9849## 兼容1.4.x版本的选举端口- port: 7848name: old-raft-rpctargetPort: 7848selector:app: nacos
---
apiVersion: v1
kind: ConfigMap
metadata:name: nacos-cm
data:mysql.host: "server.passnight.local"mysql.db.name: "nacos_devtest"mysql.port: "3306"mysql.user: "nacos"mysql.password: "*****************"
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: nacos
spec:serviceName: nacos-headlessreplicas: 3template:metadata:labels:app: nacosannotations:pod.alpha.kubernetes.io/initialized: "true"spec:containers:- name: nacosimagePullPolicy: Alwaysimage: nacos/nacos-server:latestresources:requests:memory: "128Mi"cpu: "500m"ports:- containerPort: 8848name: client- containerPort: 9848name: client-rpc- containerPort: 9849name: raft-rpc- containerPort: 7848name: old-raft-rpcenv:- name: NACOS_REPLICASvalue: "3"- name: MYSQL_SERVICE_HOSTvalueFrom:configMapKeyRef:name: nacos-cmkey: mysql.host- name: MYSQL_SERVICE_DB_NAMEvalueFrom:configMapKeyRef:name: nacos-cmkey: mysql.db.name- name: MYSQL_SERVICE_PORTvalueFrom:configMapKeyRef:name: nacos-cmkey: mysql.port- name: MYSQL_SERVICE_USERvalueFrom:configMapKeyRef:name: nacos-cmkey: mysql.user- name: MYSQL_SERVICE_PASSWORDvalueFrom:configMapKeyRef:name: nacos-cmkey: mysql.password- name: SPRING_DATASOURCE_PLATFORMvalue: "mysql"- name: MYSQL_SERVICE_DB_PARAMvalue: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai- name: NACOS_SERVER_PORTvalue: "8848"- name: NACOS_APPLICATION_PORTvalue: "8848"- name: PREFER_HOST_MODEvalue: "hostname"- name: NACOS_SERVERSvalue: "nacos-0.nacos-headless.default.svc.cluster.local:8848 nacos-1.nacos-headless.default.svc.cluster.local:8848 nacos-2.nacos-headless.default.svc.cluster.local:8848"selector:matchLabels:app: nacos

注意这里会报错

error: error validating "nacos.yml": error validating data: ValidationError(StatefulSet.spec.template.metadata): unknown field "spec" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta; if you choose to ignore these errors, turn validation off with --validate=false

需要添加一层spec标签2

再登录会报错No DataSource set

需要配置MySQL8的一些常用配置项3并自己执行初始化脚本4; 需要执行对应版本的sql脚本nacos/distribution/conf/nacos-mysql.sql at 2.0.3 · alibaba/nacos (github.com) docker:latest对应的是2.0.3

这里把节点亲和性给去掉了; 允许所有节点部署Nacos

然后使用用户名nacos密码nacos就可以登陆了

在这里插入图片描述

java应用代码

使用nacos首先要引入Maven依赖

    <dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.9.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

然后再application.properties添加必要的配置

# 这个对应服务名
spring.application.name=stock-service 
spring.cloud.nacos.server-addr=192.168.100.73:8848
# 后面三项式默认配置
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
spring.cloud.nacos.discovery.namespace=public

之后就可以在服务列表中看到相应的服务了

在这里插入图片描述

Nacos服务发现

在服务注册后, 就可以通过服务名进行调用和负载均衡了

首选准备带负载均衡功能的客户端:

    @Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}

然后准备两个服务

@AllArgsConstructor
@RestController
@RequestMapping("/OrderController")
public class OrderController {private final RestTemplate restTemplate;@GetMapping("/add")public String add() {String response = restTemplate.getForObject("http://stock-service/StockService/reduce", String.class);return "In order-service, stock-service response: " + response;}
}
@RestController
@RequestMapping("/StockService")
public class StockController {@GetMapping("/reduce")public String reduce() {return "reduce stock";}
}

之后调用订单服务, 订单服务就会调用到库存服务 默认的负载均衡器是robbin

passnight@passnight-s600:~$ curl localhost:8010/OrderController/add
In order-service, stock-service response: reduce stock

配置中心使用

  1. Nacos提供用于配置存储和其他元数据的key/value存储; 为分布式系统中的外部化配置提供服务器端和客户端支持. 使用Spring Cloud Alibaba Nacos Config, 可以在Nacos Server中集中管理配置
  2. 使用Nacos有以下好处
    1. 易维护
    2. 时效性
    3. 安全性

Dubbo

  1. Dubbo以一款高性能的RPC框架
    1. 面向接口代理的高性能RPC调用: 为开发者屏蔽调用的底层细节
    2. 智能负载均衡
    3. 服务自动注册与发现
    4. 高扩展: 基于微内核+插件设计; 几乎所有的核心能力都支持第三方实现
    5. 运行期流量调度: 通过配置路由规则, 可以实现灰度发布/同机房优先等功能
    6. 可视化的服务治理与运维: 提供可视化的运维工具和服务治理工具

使用

安装dubbo-admin

version: "3.0"
services:dubbo-admin:image: apache/dubbo-admin:0.6.0container_name: dubbo-adminports:- "20018:38080"volumes:- /opt/docker/dubbo-admin/data:/dataenvironment:admin.registry.address: nacos://192.168.100.71:8848admin.config-center: nacos://192.168.100.71:8848admin.metadata-report.address: nacos://192.168.100.71:8848restart: always

然后使用docker-compose up -d启动即可

暴露服务

  1. 引入dubbo依赖

            <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.23</version></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.10.0</version></dependency><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-nacos</artifactId><version>2.7.23</version></dependency>
    

原理

负载均衡机制

  1. RandomLoadBalance: 基于权重的随机负载均衡
  2. RoundRobinLoadBalance: 基于权重的轮询负载均衡 差分轮询算法
  3. LeastActiveLoadBalance: 最少活跃数负载均衡机制, 总是选择响应速度最快的服务
  4. ConsistentHashLoadBalance: 基于一致性哈希算法的负载均衡机制

Sentinel

基本概念

  1. 在微服务调用链路中某个服务故障, 引起整个链路中的微服务都不可用, 即雪崩

  2. 解决雪崩的方法

    1. 超时处理: 设定超时时间, 请求超过一定时间没有响应就返回错误信息, 不会无休止等待
    2. 仓壁模式: 限制每个业务所能够使用的资源, 以避免部分业务耗尽整个系统的资源; 即线程隔离
    3. 熔断降级: 由断路器统计业务执行的异常比例, 如果超出阈值则熔断该业务, 拦截访问该业务的一切请求
    4. 流量控制: 限制业务访问的QPS; 避免服务因为流量突增而故障
  3. 实现服务保护的技术对比:

    技术SentinelHystrix
    隔离策略信号量线程池/信号量
    熔断降级策略基于慢调用比例或异常比例基于失败比例
    实时指标实现滑动窗口滑动窗口(基于RxJava)
    规则配置支持多种数据源支持多种数据源
    扩展性多个扩展点插件形式
    基于注解的支持支持支持
    线瘤基于QPS, 支持基于调用关系的限流有限的支持
    流量整形支持慢启动/匀速排队模式不支持
    系统自适应保护支持不支持
    控制台开箱即用, 可配置规则, 查看秒级监控, 机器发现等不完善
    常见的框架的适配Servlet/Spring Cloud/ Dubbo/ gRPC等Servlet/ Spring Cloud Netfix

基本使用

  1. 安装dashboard

    version: "2.1"
    services:sentinel-dashboard:image: bladex/sentinel-dashboard:1.8.0container_name: sentinel-dashboardports:- "20019:8858"
    
  2. 引入依赖

            <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
    
  3. 配置dashboard地址

    spring.cloud.sentinel.transport.dashboard=server.passnight.local:20019
    
  4. 之后就可以在dashboard中看到请求信息了

    在这里插入图片描述

  5. 选中端点并配置流量限制; 然后就可以实现流控了:

    1. 在这里插入图片描述

    2. 在这里插入图片描述

限流规则

  1. 簇点链路: 即项目中的调用链路, sentinel默认监控SpringMVC中的端点
  2. 流控模式:
    1. 关联: 统计与当前资源相关的另一个资源, 触发阈值时, 触发当前资源的限流 当read QOS达到阈值时, 对write限流

      1. 在这里插入图片描述
    2. 链路模式: 根据请求来源进行限流; 使用@SentinelResource将服务中的方法设置为资源

    3. 热点参数请求: 根据参数进行限流, 需要添加@SentinelResource才能生效 查询下, 对不同资源分别限流

  3. 流控效果:
    1. 快速失败: 达到阈值后, 新的请求会立即被拒绝, 并抛出异常 默认处理方式
    2. 预热模式: 对超出阈值的请求同样抛出异常, 但阈值会动态变化, 从最小值增加到最大值; 初识阈值为 t h r e s h o l d c o l d F a c t o r \frac{threshold}{coldFactor} coldFactorthreshold; 等待预热时间后达到阈值QPS
    3. 排队等待: 将请求放入队列, 直到预期等待时长请求超出等待时长才会拒绝请求 流量整形

隔离和降级

  1. 熔断降级: 断路器统计服务调用的异常比例/慢比例; 若超过阈值就会熔断该服务, 当服务恢复时自动放行该服务的请求 熔断时解决雪崩的重要手段, 即当服务异常则停止其提供服务

    失败达到阈值
    熔断时间结束
    success
    快速失败
    失败打开断路器
    一次请求成功, 关闭断路器
    Closed
    Open
    Half Open
  2. 熔断策略: 熔断策略有三种, 慢调用/异常比例/异常数

    1. 慢调用: 业务的相应时长(RT), 大于指定时长请求认定为慢调用请求, 在指定时间内, 如果请求数量超过最小数量, 慢调用比例大于设定值, 则触发熔断
    2. 异常比例/异常数: 指定事件内的调用, 若调用次数超过指定请求数, 且异常比例/异常数超过阈值, 则触发熔断
  3. 授权规则: 根据调用方来源进行控制, 有白名单黑名单两种方式例如绕过网关则block, 可以通过添加http header实现

  4. 自定义异常: 实现BlockExceptionHandler接口即可

规则持久化

  1. Sentinel控制台的规则管理有三种模式:

    1. 原始模式: 将规则保存在内存当中, 重启服务会丢失 默认模式

    2. pull模式: 控制台将配置的规则推送到Sentinel客户端, 而客户端会将规则持久化, 之后定时去本地文件或数据库中查询, 更新本地规则

      在这里插入图片描述

    3. push模式: 控制台将配置规则推送到配置中心, 服务监听配置中心 需要自己实现

      在这里插入图片描述

实现原理

Hystrix实现原理5

  1. 根据Hystrix的流程图来看, Hystrix主要实现的功能有三点:
    1. 缓存请求: 若请求结果在缓存当中, 则直接返回缓存中的结果
    2. 断路保护: 若命中了断路规则, 则直接断路, 执行fallback函数
    3. 池化请求: 由线程池(信号量)创建并执行请求; 因此若发生异常, 可以将异常隔离在Hystrix的线程池当中
    4. 在这里插入图片描述

Seata

项目准备

CREATE TABLE account_t
(id      BIGINT PRIMARY KEY AUTO_INCREMENT,user_id VARCHAR(64),money   DOUBLE
);
CREATE TABLE storage_t
(id             BIGINT PRIMARY KEY AUTO_INCREMENT,commodity_code VARCHAR(64),count          INT
);CREATE TABLE order_t
(id             BIGINT PRIMARY KEY AUTO_INCREMENT,user_id        VARCHAR(64),commodity_code VARCHAR(64),count          INT,money          DOUBLE
);INSERT INTO account_t (user_id, money) VALUE ('user1', 1000);
INSERT INTO storage_t(commodity_code, count) VALUE ('00001', 10);

请求

curl -X POST -d '{"userId": "user1", "commodityCode": "00001", "count": 2, "money": 200}' --header "Content-Type: application/json" server.passnight.local:8010/OrderController/create-order

触发库存不足异常:

curl -X POST -d '{"userId": "user1", "commodityCode": "00001", "count": 20, "money": 200}' --header "Content-Type: application/json" server.passnight.local:8010/OrderController/create-order

OrderService因为rpc调用失败, 且标注了@Transactional所以事务回滚; StockService因为异常所以没有扣减库存; 但UserService正常执行, 账户被扣减; 这不符合业务要求.

基本概念

  1. Seata事务管理中有三个重要角色:
    1. 事务协调者(Transaction CVoordinator): 维护全局和分支事务的状态, 协调全局事务提交或回滚
    2. 事务管理器(Transactrion Manager): 定义全局事务的范围, 开始全局事务, 提交或回滚全局事务
    3. 资源管理器(Resource Manager): 管理分支事务处理的资源, 与事务TC交谈以注册分支事务和报告分支事务的状态, 并驱动分支事务提交或回滚
  2. Seata分布式解决方案
    1. XA模式: 强一致分阶段事务模式, 牺牲一定的可用性, 无业务侵入
    2. TCC模式: 最终一致性的分阶段事务模式, 有业务侵入
    3. AT模式: 最终一致性的分阶段事务模式, 无业务侵入 是Seata的默认模式
    4. SAGA模式: 长事务模式, 有业务侵入

基本使用

部署TC服务

version: "3"
services:seata-server:container_name: seata-serverimage: seataio/seata-server:2.0.0hostname: seata-serverports:- "20020:8091"- "20021:7091"volumes:- "/opt/docker/seata/config:/seata-server/resources"- "/etc/localtime:/etc/localtime"- "/etc/timezone:/etc/timezone"environment:- SEATA_PORT=8091- STORE_MODE=file

建表

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE 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_status_gmt_modified` (`status` , `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 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 = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(128),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;CREATE TABLE IF NOT EXISTS `distributed_lock`
(`lock_key`       CHAR(20) NOT NULL,`lock_value`     VARCHAR(20) NOT NULL,`expire`         BIGINT,primary key (`lock_key`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

添加

[lock.DataBaseDistributedLocker] [              <init>]  [] : The distribute lock table is not config, please create the target table and config it
store.db.distributed-lock-table=distributed_lock

分布式事务

XA模式

  1. Seata XA模式是在数据库XA模式上做了简单的封装 Seata的RM仅转发事务到db的RM
  2. 特点
    1. 优点:
      1. 强一致性, 满足ACID原子
      2. 常用的数据库都支持, 实现简单, 且没有代码侵入
    2. 缺点
      1. 一阶段需要锁定资源, 等到二阶段结束后才能释放, 性能较差
      2. 依赖关系型数据库实现事务 例如redis不支持XA, 则无法使用XA模式
实现
  1. 引入依赖

            <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency>
    
  2. 启动Seata

    @EnableSeataSpringConfig
    
  3. 配置Seata

    # seata
    seata.registry.type=nacos
    seata.registry.nacos.server-addr=192.168.100.71:8848
    seata.registry.nacos.namespace=public
    seata.registry.consul.cluster=default
    seata.config.nacos.group=SEATA_GROUP
    seata.registry.nacos.application=seata-server
    seata.tx-service-group=seata-sell
    # use XA mode
    seata.data-source-proxy-mode=XA
    seata.service.vgroup-mapping.seata-sell=default
    
  4. 在方法上标注@GlobalTransactional

        @Override@GlobalTransactionalpublic Long createOrder(Order order) {orderMapper.insert(order);accountService.deduct(order.getUserId(), order.getMoney());stockService.deduct(order.getCommodityCode(), order.getCount());return order.getId();}
    

AT模式

  1. AT模式同样是分阶段提交的事务模型, 不过弥补了XA模型中锁定周期过长的缺陷 相比于XA模式, 它会直接提交事务; 而非等待执行

  2. 回滚方式: RM会拦截事务, 并生成undo快照, 失败则执行undo操作

  3. 二阶段提交只需要删除undo log; 并且报告TC的操作可以异步, 因为资源已经释放

  4. 在这里插入图片描述

  5. 可能存在的问题:

    事务1和事务2同时执行update account set money = money - 10 where id = 1

    事务1事务2
    获取锁, 保存快照{id: 1, money: 100}
    执行sql, set money = 90
    提交事务, 释放DB锁
    获取DB锁, 保存快照: {id : 1, money: 90}
    执行sql, set money = 80
    提交事务 释放DB锁
    回滚, set money = 100

    该过程丢失了事务2的更新

  6. 为了解决该问题, 使用全局锁实现写隔离, 全局锁有类似以下结构:

    xid(事务id)table(表)pk(行号)

    使用该数据结构隔离其他事务更新; 这样执行流程就变成了:

    事务1事务2
    获取锁, 保存快照{id: 1, money: 100}
    执行sql, set money = 90
    提交事务, 释放DB锁
    获取DB锁, 保存快照: {id : 1, money: 90}
    执行sql, set money = 80; 但需要等待全局锁
    回滚, set money = 100, 但需要等待DB锁 此时产生了死锁
    任务超时, 回滚业务, 释放全局锁
    获取DB锁, 根据快照恢复数据
  7. 尽管加了全局锁, 但该全局锁由Seata管理, 因此非Seata管理的服务可以访问该数据; 且锁的粒度是;

  8. 对于非Seata管理的全局事务, AT模式模式通过以下方式管理

    事务1事务2
    获取锁, 保存快照before-image: {id: 1, money: 100}
    执行sql, set money = 90
    提交事务, 释放DB锁
    获取DB锁
    保存快照after-image: {id: 1, money: 90}
    执行sql, set money = 80; 无需等待全局锁
    提交事务, 释放DB锁
    回滚, 将当前数据与after-image对比, 发现 90 ≠ 80 90 \ne 80 90=80; 说明数据被其他事务修改
    此时记录异常, 发送警告, 人工介入
  9. 特点

    1. 优点:

      1. 一阶段提交事务, 直接释放数据库资源, 性能较好
      2. 利用全局锁实现读写隔离
      3. 没有代码侵入, 框架自动完成代码的回滚和提交
    2. 缺点

      1. 两个阶段之间属于软状态, 属于最终一致性方案
      2. 框架的快照功能会影响性能, 但依旧比XA模式好很多
实现
  1. 在微服务中创建undo_log的表

    CREATE TABLE 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 'creation time',log_modified  DATETIME(6)  NOT NULL COMMENT 'modify datetime',UNIQUE INDEX uni_undo_log (xid, branch_id)
    )
    
  2. 开启seataAT模式: seata.data-srouce-proxy-mode=AT

TCC模式

  1. TCC模式与AT模式相似, 每个阶段都是独立事务; 区别在于TCC是通过人工编码实现数据恢复的:

    1. Try: 资源的检测和预留
    2. Confirm: 完成资源操作业务
    3. Cancel: 预留资源释放 可以理解为Try的反向操作
  2. 在这里插入图片描述

  3. 举例(扣减用户余额30元):

    1. Try: 冻结金额30元
    2. Confirm: 清除掉冻结金额
    3. Cancel: 余额增增加冻结金额的值
  4. 特点

    1. 优点
      1. 性能好
      2. 不依数据库事务, 因此可以支持非事务型数据库
    2. 缺点
      1. 代码侵入性较大
      2. 软状态, 是最终一致性模型
      3. 需要考虑Confirm和Cancel的失败情况, 做好幂等处理
  5. 空回滚: 某分支try阶段阻塞, 导致全局事务触发cancel操作; 没有try的操作也要执行cancel操作, 此时cancel不能修改数据, 这就是空回滚: 在这里插入图片描述

  6. 业务悬挂: 在执行空回滚之后, try恢复, 此时不能执行try操作, 这就是业务悬挂

使用TCC实现扣款功能
  1. 需求:

    1. 编写TCC业务逻辑
    2. Try: 冻结金额, 扣减可用金额
    3. configm: 删除冻结金额
    4. cancel: 删除冻结金额, 恢复可用金额
    5. 保证confirm和cancel接口的幂等性 因为这些接口可能会因为执行失败重试
    6. 允许空回滚
    7. 拒绝业务悬挂
  2. 创建冻结表

    CREATE TABLE account_freeze_t
    (xid          VARCHAR(128) PRIMARY KEY NOT NULL,user_id      VARCHAR(255)    DEFAULT NULL COMMENT '用户id',freeze_money DOUBLE UNSIGNED DEFAULT 0 COMMENT '冻结金额',state        INT(1)          DEFAULT NULL COMMENT '事务状态, 0:try, 1:confirm, 2:cancel'
    );
    

SAGA模式

  1. SAGA模式是seata提供的长事务解决方案; 也分为两个阶段

    1. 阶段1: 直接提交本地事务 与TCC不同的是, tcc是在confirm阶段提交事务
    2. 阶段2: 若成功则什么都不做, 若失败则通过编写补偿业务回滚
  2. 在这里插入图片描述

  3. 特点:

    1. 优点:
      1. 基于事件驱动实现异步调用, 吞吐量高
      2. 一阶段直接提交, 性能较好
      3. 不用编写TCC三个阶段, 实现简单
    2. 缺点:
      1. 软状态持续时间不确定, 时效性差
      2. 没有锁, 没有事务隔离, 因此有脏写问题

引用


  1. Kubernetes Nacos ↩︎

  2. [google cloud platform - Kubernetes: Error validating data: ValidationError(Deployment.spec): unknown field “containers” in io.k8s.api.apps.v1.DeploymentSpec - Stack Overflow ↩︎

  3. https://github.com/nacos-group/nacos-docker/issues/251#issuecomment-1102186326 ↩︎

  4. https://github.com/nacos-group/nacos-docker/issues/251#issuecomment-1613891832 ↩︎

  5. How it Works · Netflix/Hystrix Wiki (github.com) ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/36515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java毕业设计 基于SSM vue药店管理系统小程序 微信小程序

Java毕业设计 基于SSM vue药店管理系统小程序 微信小程序 SSM 药店管理系统小程序 功能介绍 用户 登录 注册 首页 药品信息 药品详情 加入购物车 立即购买 收藏 购物车 立即下单 新增收货地址 我的收藏管理 用户充值 我的订单 留言板 管理员 登录 个人中心 修改密码 个人信息…

分布式并行最短路径

此前我 “自然而然” 做了两个小算法&#xff0c;最短路径 和 最小生成树&#xff0c;我喜欢大自然的第一性原理&#xff0c;最小作用量&#xff0c;梯度下降&#xff0c;爆炸&#xff0c;河水泛滥&#xff0c;本质上都是一回事。 大自然另一风格是分布式并行&#xff0c;没外…

Java使用poi生成word文档的简单实例

Java使用poi生成word文档的简单实例 生成的效果如下&#xff1a; 用到的poi的简单的知识 新建一个word对象 //新建文件 XWPFDocument document new XWPFDocument();新建段落以及文字样式 //创建段落 XWPFParagraph paragraph document.createParagraph(); paragraph.se…

Idea启动服务报 Command line is too long

一、背景 合不同分支代码后&#xff0c;启动服务报 Error running Application, Command line is too long, Shorten the command line via JAR manifest or via a classpath file and rerun. 没有在意&#xff0c;然后点击了manifest 来进行 二、问题 然后自己在重新启动&…

Linux网络编程:套接字编程

1.Socket套接字编程 1.1.什么是socket套接字编程 Socket套接字编程 是一种基于网络层和传输层网络通信方式&#xff0c;它允许不同主机上的应用程序之间进行双向的数据通信。Socket是网络通信的基本构件&#xff0c;它提供了不同主机间的进程间通信端点的抽象。一个Socket就是…

智能猫砂盆到底是不是智商税?解救上班族双手的测评合集来了

不得不说&#xff0c;像我这样的上班族真的是很需要一个智能猫砂盆了。普通的猫砂盆一天就要打扫3次&#xff0c;遇到很能拉的猫咪的时候&#xff0c;就不止是三次那么简单了。如果有个产品能帮我解决这个问题&#xff0c;让我能放心外出&#xff0c;那又何乐而不为呢&#xff…

马面裙的故事:汉服如何通过直播电商实现产业跃迁

【潮汐商业评论/原创】 波澜壮阔的千里江山在马面裙的百褶上展开&#xff0c;织金花纹在女性的步伐之间若隐若现&#xff0c;从明清到现代&#xff0c;如今马面裙又流行了回来&#xff0c;成为女性的流行单品&#xff0c;2024年春节期间&#xff0c;马面裙更是成为华夏女孩们的…

Halcon 如何根据特征过滤区域和XLD

一 如何跟进特征过滤区域和XLD dev_open_window(0,0,512,512,black,WindowHandle)read_image(Image,fabrik)threshold(Image,Region,128,255)connection(Region,ConnectedRegions)*根据面积范围[8000,9000] dev_display(Image)select_shape(ConnectedRegions,SelectedRegions,…

【Vue】集成富文本编辑器

这文章使用的是wangeditor插件&#xff0c;官网地址&#xff1a;wangEditor&#xff0c;这个比较简单 安装 npm i wangeditor --save 使用 <div id"editor"></div>import E from "wangeditor"const editor new E("#editor") e…

Modbus为何要转成EtherCAT

1. Modbus是什么&#xff1f; Modbus是一种工业通信协议&#xff0c;广泛应用于工业自动化领域。它支持多种通信方式&#xff0c;包括RS-232、RS-485和TCP/IP等。Modbus协议简单易用&#xff0c;能够实现设备之间的数据交换和控制命令的传输。然而&#xff0c;它在数据传输速率…

Mac电脑安装HomeBrew工具(100%成功)

1.Homebrew是什么&#xff1f; homebrew是一款Mac OS平台下的软件包管理工具&#xff0c;拥有安装、卸载、更新、查看、搜索等功能。通过简单的指令可以实现包管理&#xff0c;而不用关心各种依赖和文件路径情况。 2.homebrew常用命令 检测是否安装HomeBrew: brew -v卸载Hom…

8. Revit API UI: DockablePane(可停靠窗口)

8. Revit API UI: DockablePane&#xff08;可停靠窗口&#xff09; 接着前面的预览控件和外部事件&#xff0c;这一篇&#xff0c;我们来看看可停靠窗口DockablePane的实现。 实现流程 可停靠窗口相关的类与接口主要有DockablePane和IDockablePageProvider&#xff0c;都是…

具备生成自签名文档证书能力的印章管理软件_电子骑缝章软件

最新版的e-章宝具体生成自签名文档证书的能力&#xff0c;这种证书可用内部文档发布的签名&#xff0c;文档一旦用证书签名并发布&#xff0c;具有不可抵赖性&#xff0c;阅读者也能确认所发布的文档是否是发布者发布的&#xff08;即中途有没有被他人恶意修改过&#xff09;&a…

Qt样式表及相关案例

一.Qt样式表介绍 Qt样式表是一个可以自定义部件外观的强大机制&#xff0c;样式表的概念、术语、语法均受到HTML的层叠样式表(Cascading Style Sheets,CSS)的启发。 样式表可通过QApplication::setStyleSheet()函数将其设置到整个应用程序上&#xff0c;也可以使用QWidget::se…

第9关:索引(2024数据库期末综合)

第9关&#xff1a;索引&#xff08;注意看下面的温馨提示&#xff01;&#xff01;&#xff09; 任务描述 湖南人口hnpeople数据表结构如图所示&#xff0c;各字段含义如下 cs&#xff08;城市)、qx(区县)、rk(人口)、man(男)、woman(女)、child(儿童)、adult(成人)、old(老人)…

揭秘数据合并的秘密:一文掌握一对一、多对一、多对多合并技巧与实战!

使用pd.merge()合并 类似 MySQL 中表和表直接的合并merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并每一列元素的顺序不要求一致1. 一对一合并 df1 = pd.DataFrame({"…

必应bing搜索广告投放介绍,投放的广告形式和效果

必应Bing搜索广告以其独特的市场定位、高质量的用户群体和强大的全球覆盖能力&#xff0c;成为众多企业拓展业务、提升品牌影响力的重要渠道。作为微软旗下的一款搜索引擎&#xff0c;必应不仅在美国市场占据重要份额&#xff0c;其在全球范围内的影响力也不容小觑。对于寻求国…

前端开源项目Vuejs:让前端开发如虎添翼!

文章目录 引言一、Vue.js的优势二、Vue.js实战技巧三、Vue.js社区与资源结语 引言 在前端开发的世界里&#xff0c;Vue.js凭借其简洁、轻量且功能强大的特性&#xff0c;逐渐崭露头角&#xff0c;成为众多开发者心中的首选框架。 一、Vue.js的优势 Vuejs项目地址 Vue.js之…

Java web应用性能分析之【自定义prometheus监控指标】

Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 Java web应用性能分析之【java进程问题分析工具】-CSDN博客 Java web应用性能分析之【jvisualvm远程连接云服务器】-CSDN博客 Java web应用性能分析之【java进程问题分析定位】-CSDN博客 Java web应用性能分析之【…

手写SpringMVC之调度器DispatcherServlet

DispatcherServlet&#xff1a;分发、调度 根据上一节&#xff0c;已经实现了将controller的方法添加到容器中&#xff0c;而DispatcherServlet的作用就是接收来自客户端的请求&#xff0c;然后通过URI的组合&#xff0c;来找到对应的RequestMapping注解的方法&#xff0c;调用…