分布式事务总结

文章目录

    • 一、分布式事务基础
      • 什么是事务?
      • 本地事物
      • 分布式事务
      • 分布式事务的场景
    • 二、分布式事务解决方案
      • 全局事务
      • 可靠消息服务
      • TCC 事务
    • 三、Seata 分布式事务解决方案
      • 3.1 Seata-At模式
      • 3.2 秒杀项目集成 Seata
        • 启动 Seata-Server
        • 项目集成seata配置
        • AT模式代码实现
      • 3.3 Seata-TCC深度解析
        • TCC模型图
        • 模型设计
          • 扣钱业务逻辑
          • 加钱业务逻辑
          • 业务模型总结
        • 并发控制
        • 业务模型优化
        • 异常处理
          • 空回滚
          • 幂等
          • 防悬挂
        • 异常处理流程图
          • Try方法
          • Comfirm 方法
          • Cancel方法
        • TCC模式代码实现

一、分布式事务基础

什么是事务?

事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作

都成功,要么所有的操作都被撤销。简单地说,事务提供一种“要么什么都不做,要么做全套”机制

本地事物

本地事物其实可以认为是数据库提供的事务机制。说到数据库事务就不得不说,数据库事务中的四

大特性:

  • A:原子性(Atomicity),一个事务中的所有操作,要么全部完成,要么全部不完成

  • C:一致性(Consistency),在一个事务执行之前和执行之后数据库都必须处于一致性状态

  • I:隔离性(Isolation),在并发环境中,当不同的事务同时操作相同的数据时,事务之间互不影响

  • D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久的保存下来

数据库事务在实现时会将一次事务涉及的所有操作全部纳入到一个不可分割的执行单元,该执行单

元中的所有操作要么都成功,要么都失败,只要其中任一操作执行失败,都将导致整个事务的回滚

分布式事务

分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布

式系统的不同节点之上。

简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同

的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。

本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

分布式事务的场景

  • 单体系统访问多个数据库

    一个服务需要调用多个数据库实例完成数据的增删改操作

在这里插入图片描述

  • 多个微服务访问同一个数据库

    多个服务需要调用一个数据库实例完成数据的增删改操作

在这里插入图片描述

  • 多个微服务访问多个数据库

    多个服务需要调用一个数据库实例完成数据的增删改操作

    在这里插入图片描述

二、分布式事务解决方案

全局事务

全局事务基于DTP模型实现。DTP是由X/Open组织提出的一种分布式事务模型——X/Open

Distributed Transaction Processing Reference Model。它规定了要实现分布式事务,需要三种角色:

  • AP: Application 应用系统 (微服务)

  • TM: Transaction Manager 事务管理器 (全局事务管理)

  • RM: Resource Manager 资源管理器 (数据库)

整个事务分成两个阶段(2PC):

  • 阶段一: 表决阶段,所有参与者都将本事务执行预提交,并将能否成功的信息反馈发给协调者。

  • 阶段二: 执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地执行提交或者回

滚。

在这里插入图片描述

优点

  • 提高了数据一致性的概率,实现成本较低

缺点

  • 单点问题: 事务协调者宕机

  • 同步阻塞: 延迟了提交时间,加长了资源阻塞时间

  • 数据不一致: 提交第二阶段,依然存在commit结果未知的情况,有可能导致数据不一致

可靠消息服务

基于可靠消息服务的方案是通过消息中间件保证上、下游应用数据操作的一致性。假设有A和B两个

系统,分别可以处理任务A和任务B。此时存在一个业务流程,需要将任务A和任务B在同一个事务中处

理。就可以使用消息中间件来实现这种分布式事务。

RocketMQ事务消息流程图

在这里插入图片描述

1)事务消息发送及提交

(1) 发送消息(half消息)

(2) 服务端响应消息写入结果

(3) 根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)

(4) 根据本地事务状态执行Commit或者Rollback(Commit操作生产消息索引,消息对消费者可见)

2) 事务补偿

(1) 对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查”

(2) Producer收到回查消息,检查回查消息对于的本地事务的状态

(3) 根据本地事务状态,重新Commit或者Rollback

其中,补偿阶段用户解决消息Commit或者Rollback发生超时或者失效的情况

3) 事务消息状态

事务消息共有三种状态,提交状态,回查状态,中间状态:

  • TransactionStatus.CommitTransaction: 提交事务,它允许消费者消费此消息
  • TransactionStatus.RollbackTransaction: 回滚事务,它代表消息将被删除,不允许被消费
  • TransactionStatus.Unknown: 中间状态,它代表需要消息队列来确认状态

消息生产者实现

发送代码如下:

Message<OperateIntergralVo> message = MessageBuilder.withPayload(vo).setHeader("orderNo",orderNo).build();
TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction("tx_group", "tx_topic", message, orderNo);
String sendStatus = sendResult.getSendStatus().name();
String localTXState = sendResult.getLocalTransactionState().name();
og.info(">>>> send status={},localTransactionState={} <<<<",sendStatus,localTXState);
if(sendResult.getLocalTransactionState().equals(LocalTransactionState.COMMIT_MESSAGE)){
    return "退款成功";
}else{
    return "退款失败";
}

创建事务消息生产者端的消息监听器,注意是生产者,不是消费者,我们需要实现的是RocketMQLocalTransactionListener接口,代码如下:

@RocketMQTransactionListener(txProducerGroup = "tx_group")
@Slf4j
public class OrderTXMsgListener implements RocketMQLocalTransactionListener {
    @Autowired
    private IOrderInfoService orderInfoService;
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        log.info("执行本地事务");
        RocketMQLocalTransactionState result = RocketMQLocalTransactionState.COMMIT;
        try {
            String orderNo = (String) arg;
            orderInfoService.changeOrderStatusToRefund(orderNo);
        } catch (Exception e) {
            result = RocketMQLocalTransactionState.ROLLBACK;
        }
        return result;
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        String orderNo = (String) msg.getHeaders().get("orderNo");
        if(!StringUtils.isEmpty(orderNo)){
            OrderInfo orderInfo = orderInfoService.getOrderStatus(orderNo);
            if(OrderInfo.STATUS_REFUND.equals(orderInfo.getStatus())){
                return RocketMQLocalTransactionState.COMMIT;
            }
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }
}

优缺点:

  • 优点:实现最终一致性,并发较高,性能较快
  • 缺点:异步执行,无法直接获取到远程服务的返回结果
  • 缺点:场景限制,只有消费者无论如何都能执行成功的场景,才适合采用此方案
  • 缺点:可能存在短暂的不一致

TCC 事务

TCC 即为 Try Confirm Cancel,它属于补偿型分布式事务。TCC 实现分布式事务一共有三个步骤:

  • Try:尝试待执行的业务

这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的全部资源

  • Confirm:确认执行业务

确认执行业务操作,不做任何业务检查, 只使用Try阶段预留的业务资源。通常情况下,采用TCC

则认为 Confirm 阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的

出错了,需引入重试机制或人工处理。

  • Cancel:取消待执行的业务

取消Try阶段预留的业务资源。通常情况下,采用TCC则认为Cancel阶段也是一定成功的。若

Cancel阶段真的出错了,需引入重试机制或人工处理。

在这里插入图片描述

TCC 两阶段提交与 XA 两阶段提交的区别是:

  • XA 是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。

  • TCC 是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

TCC 事务的优缺点:

  • 优点:把数据库层的二阶段提交上提到了应用层来实现,规避了数据库层的2PC性能低下问题。

  • 缺点:TCC的Try、Confirm和Cancel操作功能需业务提供,开发成本高。

三、Seata 分布式事务解决方案

2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And

Rollback),其愿景是让分布式事务的使用像本地事务的使用一样,简单和高效,并逐步解决开发者们

遇到的分布式事务方面的所有难题。后来更名为 Seata,意为:Simple Extensible Autonomous

Transaction Architecture,是一套分布式事务解决方案。

Seata 的设计目标是对业务无侵入,因此从业务无侵入的2PC方案着手,在传统2PC的基础上演进。

它把一个分布式事务理解成一个包含了若干分支事务的全局事务。全局事务的职责是协调其下管辖的分

支事务达成一致,要么一起成功提交,要么一起失败回滚。此外,通常分支事务本身就是一个关系数据

库的本地事务。

3.1 Seata-At模式

Seata主要由三个重要组件组成:

  • TC:Transaction Coordinator 事务协调器,管理全局的分支事务的状态,用于全局性事务的提交

和回滚。

  • TM:Transaction Manager 事务管理器,用于开启、提交或者回滚全局事务。

  • RM:Resource Manager 资源管理器,用于分支事务上的资源管理,向TC注册分支事务,上报分

支事务的状态,接受TC的命令来提交或者回滚分支事务。

在这里插入图片描述

Seata-AT模式的执行流程如下:

  1. A服务的TM向TC申请开启一个全局事务,TC就会创建一个全局事务并返回一个唯一的XID

  2. A服务的RM向TC注册分支事务,并及其纳入XID对应全局事务的管辖

  3. A服务执行分支事务,向数据库做操作4. A服务开始远程调用B服务,此时XID会在微服务的调用链上传播

  4. B服务的RM向TC注册分支事务,并将其纳入XID对应的全局事务的管辖

  5. B服务执行分支事务,向数据库做操作

  6. 全局事务调用链处理完毕,TM根据有无异常向TC发起全局事务的提交或者回滚

  7. TC协调其管辖之下的所有分支事务, 决定是否回滚

Seata-AT模式实现2PC与传统2PC的差别

  1. 架构层次方面,传统2PC方案的 RM 实际上是在数据库层,RM本质上就是数据库自身,通过XA协

议实现,而 Seata 的 RM 是以 jar 包的形式作为中间件层部署在应用程序这一侧的。

  1. 两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollback,事务性资源的锁都要保

持到Phase2完成才释放。而 Seata 的做法是在 Phase1 就将本地事务提交,这样就可以省去Phase2

持锁的时间,整体提高效率。

3.2 秒杀项目集成 Seata

启动 Seata-Server

详情请看部署文档/seata-server部署文档.md

项目集成seata配置

详情请看 集成文档/seata客户端集成文档.md

AT模式代码实现

分布式事务发起方只需要贴@GlobalTransactional注解即可

分支分布式事务贴上@Transactional即可

3.3 Seata-TCC深度解析

TCC模型图

在这里插入图片描述

模型设计

业务场景

1.账户支付,用户账户金额减少

2.账户退款,用户账户金额增加

表设计

CREATE TABLE `user_account` (
  `user_id` varchar(100) NOT NULL COMMENT '用户UID',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `amount` bigint(20) NOT NULL COMMENT '用户余额',
  PRIMARY KEY (`user_id`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
扣钱业务逻辑

场景: 账户A上有100元,要扣除其中的30元

Try: 检查余额,扣除其中30元;

在这里插入图片描述

Confirm: 空提交

在这里插入图片描述

Cancel: 返还扣除的30元

在这里插入图片描述

加钱业务逻辑

Try: 空操作;

在这里插入图片描述

Confirm: 增加可用金额30元

在这里插入图片描述

Cancel: 空操作

在这里插入图片描述

业务模型总结

在这里插入图片描述

并发控制

账户A上有100元,事务T1要扣除其中30元,事务T2也要扣除30元,出现并发

Try: 检查余额,扣除其中30元

在这里插入图片描述

T2 Confirm: 空提交

在这里插入图片描述

T1 Cancel: 释放T1预留的30元

在这里插入图片描述

业务模型优化

表增加冻结金额字段

CREATE TABLE `user_account` (
  `user_id` varchar(100) NOT NULL COMMENT '用户UID',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `amount` bigint(20) NOT NULL COMMENT '用户余额',
  `freezed_amount` bigint(20) unsigned DEFAULT '0',
  PRIMARY KEY (`user_id`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

扣钱为例: 账户上有100元,要扣除其中30元(此时里面的可用金额=amount-freezed_amount)

Try: 检查余额,扣除其中30元(freezed_amount=freezed_amount+30)

在这里插入图片描述

Confirm: 扣除30元( amount=amount-30 freezed_amount=freezed_amount-30)

在这里插入图片描述

Cancel: 释放预留的30元(freezed_amount=freezed_amount-30)

在这里插入图片描述

加钱为例: 账户上有100元,要加30元(此时里面的可用金额=amount-freezed_amount)

Try: 空操作

在这里插入图片描述

Confirm: 增加30元( amount=amount+30)

在这里插入图片描述

Cancel: 空操作

在这里插入图片描述

异常处理
空回滚

Try 方法未执行,Cancel 执行了

出现原因:

  1. Try 超时
  2. 分布式事务回滚,触发 Cancel
  3. 未收到 Try,收到 Cancel

解决方案: Cancel 方法需要识别出是否执行 Try 方法,如果执行了就正常执行 Cancel,如果没有就直接结束

增加事务日志表来实现这个功能.

CREATE TABLE `account_transaction` (
  `tx_id` varchar(100) NOT NULL COMMENT '事务Txid',
  `action_id` varchar(100) NOT NULL COMMENT '分支事务id',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `user_id` varchar(100) NOT NULL COMMENT '账户Uid',
  `amount` varchar(100) NOT NULL COMMENT '变动金额',
  `type` varchar(100) NOT NULL DEFAULT '' COMMENT '变动类型',
  PRIMARY KEY (`tx_id`,`action_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
幂等

多次调用二阶段方法

出现原因:

  • 网络异常
  • 分支事务所在服务器宕机

解决方案: 做幂等性处理

CREATE TABLE `account_transaction` (
  `tx_id` varchar(100) NOT NULL COMMENT '事务Txid',
  `action_id` varchar(100) NOT NULL COMMENT '分支事务id',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `user_id` varchar(100) NOT NULL COMMENT '账户Uid',
  `amount` varchar(100) NOT NULL COMMENT '变动金额',
  `type` varchar(100) NOT NULL DEFAULT '' COMMENT '变动类型',
  `state` smallint(4) NOT NULL COMMENT '状态: 1.初始化 2.已提交 3.已回滚',
  PRIMARY KEY (`tx_id`,`action_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
防悬挂

Cancel 比 Try 先执行

出现原因:

  1. Try 超时(拥堵)

  2. 分布式事务回滚触发 Cancel

  3. 拥堵的 Try 到达

要允许空回滚,但是要拒绝空回滚之后的 Try 方法.

解决方案: 在Try方法中, 如果根据全局事务ID能查询出数据出来,说明在try方法之前执行了空回滚,此时就不能进行try方法。否则就正常执行try方法.

异常处理流程图
Try方法

在这里插入图片描述

Comfirm 方法

在这里插入图片描述

Cancel方法

在这里插入图片描述

TCC模式代码实现

分布式事务发起方只需要贴@GlobalTransactional注解即可

分支事务需要完成下面步骤:

1.在接口上贴上@LocalTCC@TwoPhaseBusinessAction注解,具体配置如下:

@LocalTCC
public interface IUsableIntegralService {
    /**
     * 增加积分
     */
    @TwoPhaseBusinessAction(name = "incrIntergralTry", commitMethod = "incrIntergralCommit", rollbackMethod = "incrIntergralRollback")
    void incrIntergralTry(@BusinessActionContextParameter(paramName = "operateIntergralVo") OperateIntergralVo operateIntergralVo, BusinessActionContext context);
    void incrIntergralCommit(BusinessActionContext context);
    void incrIntergralRollback(BusinessActionContext context);
}

2.添加实现类,实现try,confirm,cancel方法逻辑即可

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【自主探索】基于 frontier_exploration 的单个机器人自主探索建图

文章目录 一、概述1、功能2、要求 二、使用方法1、用于运行演示2、用于开发人员2.1. 探索无/地图数据2.2. 使用 /map 数据进行探索 三、提供的组件1、explore_client1.1. 调用的操作1.2. 订阅主题1.3. 发布主题 2、explore_server2.1. 提供的操作2.2. 调用的操作2.3. 调用的服务…

AMESim与MATLAB联合仿真demo

本文是AMESim与MATLAB联合仿真的demo&#xff0c;记录一下如何进行联合仿真。 AMESim与MATLAB联合仿真可以大幅度提高工作效率。 author&#xff1a;xiao黄 缓慢而坚定的生长 csdn:https://blog.csdn.net/Python_Matlab?typeblog主页传送门 博主的联合仿真环境如下&#xff…

闲人闲谈PS之四十七——PS顾问能力评价参考标准

惯例闲话&#xff1a;逝者如斯夫&#xff0c;一晃2023年进入年尾&#xff0c;初步盘点下今年做的事情&#xff0c;还真不少&#xff0c;PLM项目、接口开发、扫码系统、数字彩虹图、专利申请…闲人发现&#xff0c;不经意间&#xff0c;SAP从自己的主营业务中占据的比重已经越来…

【21年扬大真题】编写程序,去除掉字符串中所有的星号。

【21年扬大真题】 编写程序&#xff0c;去除掉字符串中所有的星号。 int main() {int i 0;int j 0;char arr[30] {0};char brr[30] {0};printf("请输入一个字符串:");gets(arr);for (i 0;i < 30;i){if (arr[i] ! *) {brr[j] arr[i];j;}}int tmp j;for (i …

Nginx模块开发之http handler实现流量统计(2)

文章目录 一、概述二、Nginx handler模块开发2.1、代码实现2.2、编写config文件2.3、编译模块到Nginx源码中2.4、修改conf文件2.5、执行效果 总结 一、概述 上一篇【Nginx模块开发之http handler实现流量统计&#xff08;1&#xff09;】使用数组在单进程实现了IP的流量统计&a…

【ArcGIS Pro微课1000例】0036:栅格影像裁剪与提取(矢量范围裁剪dem高程数据)

本实验讲解在ArcGIS Pro中进行栅格影像裁剪与提取(矢量范围裁剪dem高程数据)的方法。DEM、DOM、DSM等栅格数据方法也可以实现。 文章目录 一、加载实验数据二、裁剪工具的使用1. 裁剪栅格2. 按掩膜提取一、加载实验数据 加载配套实验数据包中的0036.rar中的dem数据和矢量裁剪…

网工内推 | 美的、得力集团,包吃包住,IE认证优先,14薪

01 美的 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1.负责IT网络设备、IDC机房的日常维护巡检、监控和管理&#xff1b; 2.负责路由、交换、防火墙、无线控制器、AP等网络设备的开通、调整、优化升级&#xff1b; 3.负责公司OT、IT网络规划&#xff0c;项目实施以…

N-134基于java实现捕鱼达人游戏

开发工具eclipse,jdk1.8 文档截图&#xff1a; package com.qd.fish;import java.awt.Graphics; import java.io.File; import java.util.ArrayList; import java.util.List;import javax.imageio.ImageIO;public class Fishes {//定义一个集合来管理鱼List<Fish> fish…

安装compiler version 5

这个compiler version5 在我的资源里面可以免费下载&#xff1b; 另外这个东西还需要安装&#xff0c;安装教程在这里&#xff1a;Keil最新版保姆教程&#xff08;解决缺少V5编译器问题&#xff09; - 哔哩哔哩 (bilibili.com) 看吧安装好了year

Java自动装箱(autoboxing)和自动拆箱(autounboxing)介绍

Java自动装箱(autoboxing)和自动拆箱(autounboxing)介绍 先回顾一下 Java 中的基本数据类型和包装类。 基本数据类型&#xff08;Primitive Data Types&#xff09;&#xff1a; Java 提供了一组基本数据类型&#xff0c;有8种基本数据类型&#xff1a;byte、short、int、long…

旋转框检测项目相关python库知识总结

旋转框常用于检测带有角度信息的矩形框&#xff0c;即矩形框的宽和高不再与图像坐标轴平行。相较于水平矩形框&#xff0c;旋转矩形框一般包括更少的背景信息。旋转框检测常用于遥感等场景中&#xff0c;本博文简单的介绍了可应用于旋转框数据训练的开源库&#xff0c;数据结构…

Spring 七大组件

文章目录 Spring 七大组件 Spring 七大组件 核心容器(Spring core) 核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean&#xff0c;它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式…

报错AttributeError: module ‘cv2‘ has no attribute ‘ximgproc‘

报错AttributeError: module ‘cv2’ has no attribute ‘ximgproc’ 首先查看是否安装opencv-contrib-python pip list | grep opencv显示 opencv-contrib-python 4.4.0.46 opencv-python 4.8.1.78 opencv-pyt…

Python 基础【五】--数据类型-序列【2023.11.24】

1.定义 Python 中的序列是一块可存放多个值的连续内存空间&#xff0c;所有值按一定顺序排列&#xff0c;每个值所在位置都有一个编号&#xff0c;称其为索引&#xff0c;我们可以通过索引访问其对应值。 list1 [Google, Runoob, 1997, 2000] list2 [1, 2, 3, 4, 5 ] list3…

【工具使用】Keil工具的使用——常用配置介绍

Keil调试具体教程学习 目录 ​​​​​​​Keil调试具体教程学习 常用功能总结 &#xff08;2&#xff09;目标设置&#xff08;Target&#xff09; ①设置晶振频率 ②跨模块优化选项 ③微库选项 &#xff08;3&#xff09;输出设置&#xff08;Output&#xff09; ①…

Java枚举详解

一、什么是枚举类型 枚举类型是一种特殊的数据类型&#xff0c;用于定义一组固定的命名常量。枚举类型提供了一种更强大、更安全和更易读的方式来表示一组相关的常量。 在Java中&#xff0c;枚举类型是通过使用enum关键字来定义的。枚举类型可以包含一个或多个枚举常量&#xf…

P1028 [NOIP2001 普及组] 数的计算

时刻记住一句话&#xff1a;写递归&#xff0c;1画图&#xff0c;2大脑放空&#xff01;&#xff01;&#xff01; 意思是&#xff0c;自己写递归题目&#xff0c;先用样例给的数据画图&#xff0c;然后想一个超级简单的思路&#xff0c;直接套上去就可以了。 上题干&#xff…

Theta*: Any-Angle Path Planning on Grids 原文翻译

Theta*: Any-Angle Path Planning on Grids 文章目录 Theta*: Any-Angle Path Planning on Grids翻译摘要1.Introduction2. Path-Planning Problem and Notation3. Existing Terrain Discretizations4.Existing Path-Planning Algorithms4.1 A* on GridsA* with Post-Smoothed …

EFAK-v3.0.1版部署与使用

一、前言 EFAK&#xff08;(Eagle For Apache Kafka&#xff0c;以前称为Kafka Eagle&#xff09;用于在使用 Topic 的情况下监控 Kafka 集群。包含Offset 的产生、Lag的变化、Partition的分布、Owner、Topic的创建以及修改的时间等信息。 二、环境&安装包 官方下载连接E…

2023年【R1快开门式压力容器操作】考试资料及R1快开门式压力容器操作复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R1快开门式压力容器操作考试资料参考答案及R1快开门式压力容器操作考试试题解析是安全生产模拟考试一点通题库老师及R1快开门式压力容器操作操作证已考过的学员汇总&#xff0c;相对有效帮助R1快开门式压力容器操作复…