分布式事务——9种解决方案的原理与分类

news2024/12/29 11:03:30

目录

  • 一、概要
    • 1. 分布式事务的概念
    • 2. 分布式事务解决方案分类
  • 二、常见的分布式事务解决方案
    • 1. 基础的 2PC(二阶段提交)
      • 1.1 核心思想
      • 1.2 简介
      • 1.3 主要特点
        • 1.3.1 优点
        • 1.3.2 缺点
    • 2. 基础的 3PC(三阶段提交)
      • 2.1 核心思想
      • 2.2 简介
      • 2.3 主要特点
        • 2.3.1 优点
        • 2.3.2 缺点
    • 3. Seata - XA
      • 3.1 核心思想
      • 3.2 简介
      • 3.3 主要特点
        • 3.3.1 优点
        • 3.3.2 缺点
        • 3.3.3 适用场景
    • 4. Seata - AT
      • 4.1 核心思想
      • 4.2 简介
      • 4.3 主要特点
        • 4.3.1 优点
        • 4.3.2 缺点
        • 4.3.3 适用场景
    • 5. Seata - TCC
      • 5.1 核心思想
      • 5.2 简介
      • 5.3 主要特点
        • 5.3.1 优点
        • 5.3.2 缺点
        • 5.3.3 适用场景
    • 6. Seata - SAGA
      • 6.1 核心思想
      • 6.2 简介
      • 6.3 主要特点
        • 6.3.1 优点
        • 6.3.2 缺点
        • 6.3.3 适用场景
    • 7. 本地消息表
      • 7.1 核心思想
      • 7.2 简介
      • 7.3 主要特点
        • 7.3.1 优点
        • 7.3.2 缺点
        • 7.3.3 适用场景
    • 8. RocketMQ 事务消息
      • 8.1 核心思想
      • 8.2 简介
      • 8.3 主要特点
        • 8.3.1 优点
        • 8.3.2 缺点
        • 8.3.3 适用场景
    • 9. 最大努力通知
      • 9.1 核心思想
      • 9.2 简介
      • 9.3 主要特点
        • 9.3.1 优点
        • 9.3.2 缺点
        • 9.3.3 适用场景
  • 三、总结
    • 1. 分布式事务解决方案的对比
    • 2. 使用分布式事务中间件的弊端

一、概要

1. 分布式事务的概念

官话: 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成成功,要么全部失败。

白话: 本质上来说,分布式事务就是为了保证分散在各处的数据之间的一致性。

2. 分布式事务解决方案分类

分布式是否要考虑的第一个问题 —— 是否允许回滚:

  • 若不允许回滚,则事务必须执行成功,不得执行失败,因此只能采用异步通知型策略,且需要设计重试幂等
  • 若允许回滚,则需要考虑第二个问题 —— 是否要加锁:
    • 若要加锁,则事务为刚性事务(CP - 强一致性)
    • 若不加锁,则事务为柔性事务(AP - 最终一致性),且只能采用同步补偿策略

分布式事务的分类
可以通过图表的方式更加清晰地划分各种不同的分布式事务解决方案和它们的设计思想

分布式事务的分类图
接下来开始详细讲解这 9 种不同分布式事务解决方案的设计思想和优缺点。

二、常见的分布式事务解决方案

1. 基础的 2PC(二阶段提交)

1.1 核心思想

对分布式事务最暴力的做法就是让所有参与者直接执行并提交本地事务,也就是一阶段提交(1PC)。
但是这样会导致事务失去回滚能力,各个参与者之间无法进行协同,极可能出现数据不一致的问题。
当然,也可以选择放弃事务的回滚能力,要求事务必须执行成功,此时即为异步通知型事务,也即某种意义上的 1PC 模式。

为了给予分布式事务中的各个参与者协调与回滚的能力,自然地提出二阶段提交的方案:

各个参与者先执行而不提交,若所有参与者都执行成功则提交,若有某个参与者执行失败则其他参与者随之回滚。

为了让各个参与者(资源管理器)之间可以做到同步,需要一个中心节点进行统一调度,也就是事务管理器。

1.2 简介

基础的 2PC

  1. Prepare 阶段:
    事务管理器给每个资源管理器发送 prepare 消息,资源管理器判断是否可以执行事务。
    若可以执行,则开启本地事务,将事务写入本地的 redo log 和 undo log,但是不提交,然后返回成功;
    若不可以执行,则返回失败。
  2. Commit 阶段:
    若事务管理器没有收到任何资源管理器的失败反馈,则给所有资源管理器发送 commit 消息;
    若事务管理器收到了部分资源管理器的失败反馈,则给所有资源管理器发送 rollback 消息。
    资源管理器根据收到的消息执行本地事务的 commit 或 rollback。

1.3 主要特点

1.3.1 优点
  • 灵活性:相比于不允许回滚的分布式事务解决方案,能够允许事务的执行失败,因而灵活度更高。
1.3.2 缺点
  • 并发性能: 很低,在提交前,数据库中的记录是被排它锁独占的,因此并发性能会很低。
  • 稳定性: 如果事务管理器发送故障,RM 无法收到 TM 下达的提交命令,则未提交的数据就会长时间被锁。而此时,其他需要访问被锁数据的线程就会因无法访问而进入阻塞,随着阻塞线程越来越多,系统可能会崩溃。

核心的问题就在于对提交前数据的加锁,既导致了并发性能低的问题,也导致了线程阻塞的问题。
能不能不加锁?或能不能减少加锁时间?大部分允许回滚的改进方案都是基于这两个方面进行设计的。

2. 基础的 3PC(三阶段提交)

2.1 核心思想

3PC 模式试图通过减少加锁时间改进 2PC 模式。
为了解决 2PC 模式存在的问题,一个自然的想法就是引入超时机制,即资源管理器设等待超时时间,等待过久就自动提交或回滚,从而防止资源长期被锁导致的并发问题和线程阻塞问题。
然而,关键的问题在于在等待超时后 RM 该如何进行决策?是应该默认提交还是默认回滚?
如果不能做出可靠的决策,直接给 2PC 添加超时机制的简单做法极有可能导致数据不一致的问题。

为此,考虑在 2PC 模式的 prepare 阶段前加一个阶段,用于帮助超时后的默认操作进行决策。

2.2 简介

基础的 3PC

  1. CanCommit 阶段(新增阶段):
    事务管理器询问每个资源管理器是否可以执行事务。
    若可以执行,则资源管理器返回 Yes;若不可以执行,则资源管理器返回 No。
  2. PreCommit 阶段(2PC 的 Prepare 阶段):
    若事务管理器收到的所有回复均为 Yes,则向所有资源管理器发送 PreCommit 消息;
    若事务管理器收到的部分回复为 No,则向所有资源管理器发送 Abort 消息。
    若资源管理器收到 PreCommit 消息,则执行事务但不提交;若资源管理器收到 Abort 消息,则中断事务。

若某 RM 等待超时,则选择中断本地事务。分如下两种情况讨论。

  • 实际上 TM 发送了 PreCommit 消息,但是该 RM 已中断,其他 RM 也无法执行 DoCommit
    阶段,也就无法提交本地事务,因此全局事务失败,不会发生数据不一致。
  • 实际上 TM 发送了 Abort 消息,则该 RM 执行的中断是正确的操作,全局事务本应失败,保证了数据一致。
  1. DoCommit 阶段(2PC 的 Commit 阶段):
    若事务管理器收到了所有资源管理器在 PreCommit 阶段返回的成功 ack,则向它们发送 doCommit 消息;
    若事务管理器收到了某个资源管理器在 PreCommit 阶段返回的失败 ack,则向它们发送 rollback 消息。
    资源管理器根据收到的消息执行本地事务的 commit 或 rollback。

若某 RM 等待超时,则选择提交本地事务。因为全局事务可以执行到 DoCommit 阶段,是因为在 CanCommit 阶段所有 RM 都回应了 Yes(可以执行),因此可以认为全局事务大概率会执行成功,所以选择提交本地事务,可以大概率保证数据一致性。

2.3 主要特点

2.3.1 优点
  • 并发性能: 优于 2PC 模式,有效缓解了 2PC 模式中由于资源长期被锁而产生的并发问题和线程阻塞问题。
2.3.2 缺点
  • 数据一致性: 不能绝对保证,3PC 模式通过添加一个 CanCommit 阶段来判断在 DoCommit 阶段等待超时的情况下应该如何决策。虽然相比于直接引入超时机制的 2PC 模式,能够更大概率地保证数据一致性,但是并不能绝对地保证数据一致性

3. Seata - XA

3.1 核心思想

直接基于数据库的 XA 协议来忠实的实现 2PC(二阶段提交)。

3.2 简介

  • 第一阶段(prepare): 所有 RM 准备执行事务并锁住所需的资源,然后各个 RM 向 TM 报告是否 ready。
  • 第二阶段(commit 或 rollback): 如果所有 RM 都是 ready ,则 TM 向所有参与者发送 commit 命令;如果有参与者 RM 不是 ready,则 TM 向所有参与者发送 rollback 命令。

Seata - XA

3.3 主要特点

3.3.1 优点
  • 使用难度: 非常简单,因为是基于数据库自带特性实现,无需改动任何数据库表,也无需开发任何额外代码。
  • 数据一致性: 强一致性,不会存在数据不一致的中间状态,因为是 CP 模式,放弃了可用性 A。
3.3.2 缺点
  • 并发性能: 很低,因为会长时间锁资源,使其他线程被阻塞,而且各个 RM 之间会产生短板效应,所有 RM 都要锁资源并等待最慢的 RM。
3.3.3 适用场景

并发量低,对数据的一致性要求很高,对中间结果较敏感的业务场景。

4. Seata - AT

4.1 核心思想

AT 是 Automatic Transaction 的缩写,因为它能够自动完成事务的提交与回滚操作,不需要额外的代码开发。

其实现自动提交与回滚的方式如下:
TM 和 RM 所有数据库里都要额外加一张表 UNDO_LOG,自动生成并存储所有 SQL 的逆向 SQL 语句。

收到 TC 的分支提交,就删除 UNDO_LOG;收到 TC 的分支回滚,就执行 UNDO_LOG 中存储的逆向 SQL 语句。

本质上,Seata - AT 是通过补偿的方式回滚事务(同步补偿型),从而避免数据的加锁。

4.2 简介

执行本地业务和保存 redo/undo log 在同一个本地事务中,从而保证事务最终无论是 commit 还是 rollback 都必定能够执行。
第一阶段执行全部主要逻辑,第二阶段主要做回滚或日志清理。
仍然属于二阶段提交,只是以数据库加表为代价,自己模拟 MySQL 的 undo log 用于事务的回滚,从而避免加锁。
Seata - AT

4.3 主要特点

4.3.1 优点
  • 并发性能: 较高,因为本质上是同步补偿型事务,所以不用长时间锁定资源。
  • 使用难度: 简单,因为是靠 Seata 自己解析生成反向 SQL 并回滚,无需额外的代码开发,只需添加数据库表。
4.3.2 缺点
  • 数据一致性: 会存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性,所以若事务需要回滚,则在补偿前会存在数据不一致的中间状态。
  • 业务侵入度: 少量,因为所有数据库都需要额外添加一个 UNDO_LOG 表。
4.3.3 适用场景

高并发,允许数据出现短时不一致的业务场景。

5. Seata - TCC

5.1 核心思想

TCC 是 Try、Confirm、Cancel 三个单子的首字母缩写,本质上是二阶段模式(Confirm、Cancel 在二阶段二选一)
设计理念上希望 90% 的事在 T 阶段(第一阶段)做完,CC 阶段(第二阶段)只做简单操作。
然而,TCC 模式可能需要改动数据库表,还需要自己额外编写 3 个接口,以实现其复杂逻辑。

5.2 简介

  • Try 阶段: 尝试执行,完成所有业务检查,预留所需的业务资源。
  • Confirm 阶段: 确认执行,真正执行业务,不需要再进行业务检查,直接使用 Try 阶段预留的业务资源(Confirm 失败后需要进行重试,因此 Confirm 操作要有幂等设计)。
  • Cancel 阶段: 取消执行,释放 Try 阶段预留的业务资源(Cancel 操作也要有幂等设计)。
    Seata - TCC

5.3 主要特点

5.3.1 优点
  • 并发性能: 高,因为在数据库中额外存储准备状态的数据,不用长时间锁定资源。
  • 灵活性: 高,各个分布式节点可以混用各种不同数据库,因为 Try、Confirm 和 Cancel 操作的具体逻辑都是自己实现。
5.3.2 缺点
  • 数据一致性: 存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性。
  • 使用难度: 非常困难,TCC 模式中,Seata 只负责全局事务的提交与回滚指令,具体的提交与回滚操作全部需要开发人员自己实现,从而产生大量额外工作。
  • 业务侵入度: 高,因为可能涉及到数据库表的改动,自定义的 Confirm 和 Cancel 操作也容易对业务逻辑造成影响。
5.3.3 适用场景

高并发,允许数据出现短时不一致的业务场景。

6. Seata - SAGA

6.1 核心思想

考虑需要与外部第三方进行交互的事务,例如:调用支付宝支付接口 -> 出库失败 -> 调用支付宝退款接口
此时无法对外部系统的内部进行操作,只能通过接口调用进行交互,因此给每个操作实现一个逆向操作,这样就可以通过调用第三方的逆向操作接口来进行回滚。

6.2 简介

给每个操作实现一个逆向操作,通过逆向操作接口来进行回滚。
将长事务拆分为多个本地短事务,由事务管理器协调。如果某个步骤失败,则根据相反的顺序依次调用补偿操作
本质上是同步补偿型的二阶段模式。
Seata - SAGA

6.3 主要特点

6.3.1 优点
  • 并发性能: 较高,因为无需对资源加锁,而是直接提交本地短事务,若需回滚则执行逆向操作。
6.3.2 缺点
  • 数据一致性: 存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性。
  • 使用难度: 困难,因为本地短事务的提交操作和逆向补偿操作都需要开发者自己实现。
6.3.3 适用场景

需要与外部第三方进行交互,只能通过接口调用进行事务的回滚操作的场景。

异步通知型方案:可靠消息 VS 最大努力通知
都是异步通知型,区别在于消息的发送方和接收方谁来保证消息必定被传达。

  • 可靠消息:由发送方保证。
  • 最大努力通知:由接收方保证。

可靠消息的两个关键要求:

  1. 事务发起方一定能够将消息成功发送出去(让事务发起方的本地事务与能够消息协同)
  2. 事务参与方一定能够成功接收到消息(让事务参与方的本地事务与能够消息协同) 为了满足可靠消息的两个要求,必须有一个节点负责落库并维护消息, 由事务发起方维护即为本地消息表,由消息中间件维护即为 MQ 事务消息。

7. 本地消息表

7.1 核心思想

通过让事务发起方落库并维护消息的方式,满足可靠消息模式的两个关键要求。

  • 要求 1: 将本地消息表的落库与发起方的本地事务放入同一个本地事务中,从而保证发起方本地事务的执行成功与本地消息的落库成功保持原子性
  • 要求 2: 本地消息表维护消息的状态,对于“未完成”状态的消息,不断重试发送,直到收到参与方对该消息的回执,从而保证消息必定能够被参与方成功接收

7.2 简介

  • 写业务数据和写消息数据在一个本地事务中,从而保证了业务操作和发送消息的原子性。
  • 生产者定时扫描本地消息表,将未删除的消息进行重发,从而保证所有消息都会发送给 MQ。
  • 生产者收到 MQ 的回执 ACK 之后删除本地消息表中的对应消息,从而保证所有消息都被 MQ 成功接收。
  • MQ 会将未能成功发送给消费者的消息重新发送,从而保证所有消息都会发送给消费者。

本地消息表

7.3 主要特点

7.3.1 优点
  • 灵活性: 不依赖任何分布式事务中间件,完全依靠开发者自己实现的可靠消息模式。
7.3.2 缺点
  • 使用难度: 中等,需要在数据库中添加本地消息表,并实现其增删改查和定时扫码重发、回执接收等功能。
  • 数据一致性: 存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性。
  • 业务入侵度: 较高,容易与业务耦合,不利于扩展和维护,难以实现通用。
7.3.3 适用场景

可以接受异步通知型方案,不希望依赖分布式事务中间件的业务场景。

8. RocketMQ 事务消息

8.1 核心思想

通过让消息中间件落库并维护消息的方式,满足可靠消息模式的两个关键要求。

  • 要求 1: 发起方的本地事务执行前 MQ 落库半消息,发起方的本地事务执行成功则 MQ 将半消息投递到参与方,发起方的本地事务执行失败则 MQ 将半消息丢弃,从而保证发起方本地事务的执行成功与本地消息的发送成功保持原子性
  • 要求 2: 由消息中间件对“未完成”的消息进行重试,直到收到参与方的回执,从而保证消息必定能够被参与方成功接收

8.2 简介

  • MQ 定期回查每个未 commit 或 rollback 的半消息对应的生产者的事务状态,从而保证生产者方的本地事务必有一个终态。
  • 消费者完成本地事务后需要将 MQ 中对应的消息标记为已消费,从而保证消费者必定完成每个消息对应的事务。

RocketMQ 事务消息
因此,所以使用 RocketMQ 的事务消息需要自己实现两个方法:

  • 执行本地事务的方法:在发起方的本地事务的末尾需要给 MQ 发 commit / rollback 的消息。
  • 查询本地事务状态的方法:提供给 MQ,用于对发起方的本地事务状态进行回查。

8.3 主要特点

8.3.1 优点
  • 业务侵入度: 业务系统与消息系统的耦合度明显低于本地消息表模式。
  • 使用难度: 比较简单,只需实现本地事务的执行与查询两个方法,消息的维护由中间件负责。
8.3.2 缺点
  • 灵活性: 需要依赖消息中间件。
  • 数据一致性: 存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性。
8.3.3 适用场景

可以接受异步通知型方案,对达到最终一致性的时间敏感度较低的业务场景。

9. 最大努力通知

9.1 核心思想

与可靠消息模式相反,最大努力通知模式由接收方保证消息必定被传达
事务发起方只负责“尽最大努力”通知事务参与方,但是并不保证消息的成功送达,事务参与方需要主动调用消息校对接口来确保事务主动方的消息被成功接收。

9.2 简介

最大努力通知

9.3 主要特点

9.3.1 优点
  • 业务侵入度: 较低,事务主动方只需提供一个消息校对接口。
9.3.2 缺点
  • 数据一致性: 存在数据不一致的中间状态,因为是保障最终一致性的柔性事务(AP),放弃了数据的强一致性。
  • 使用难度: 中等,需要额外的定期校验机制对数据进行兜底,保证数据的最终一致性。
9.3.3 适用场景

跨平台、跨企业的系统间业务交互,外部系统网络环境复杂、不可信,对达到最终一致性的时间敏感度较低的业务场景。如充值平台与运营商、支付对接、商户通知等等跨平台、跨企业的系统间业务交互场景。

三、总结

1. 分布式事务解决方案的对比

基础 2PC基础 3PCSeata - XASeata - ATSeata - TCCSeata - SAGA本地消息表事务消息最大努力通知
一致性强一致强一致强一致最终一致最终一致最终一致最终一致最终一致最终一致
并发性能很低较低很低较高较高中等中等较高
使用难度简单中等简单简单非常困难困难中等比较简单中等
业务侵入无侵入无侵入无侵入少量较高较高较低较低
优点· 允许事务的执行失败和回滚,因而灵活度更高· 业务无侵入
· 并发性能高于 2PC
· 使用简单
· 强一致性,无数据不一致的中间状态
· 使用简单
· 并发性能较高
· 并发性能较高
· 可以混用数据库
· 并发性能较高
· 便于与外部第三方进行交互
· 易于实现,使用简单
· 不依赖任何分布式事务中间件
· 对业务侵入较少
· 通过消息中间件解耦,下游事务异步化
· 对业务侵入较少
缺点· 稳定性差,容易造成大量线程阻塞· 无法绝对保证数据一致性· 并发性能很低,会长时间锁资源· 最终一致性,会存在数据不一致的中间状态
· 有少量的业务侵入性
· 最终一致性,会存在数据不一致的中间状态
· 使用难度高,会带来大量额外工作
· 业务侵入度高
· 最终一致性,会存在数据不一致的中间状态
· 使用难度较高,会带来额外的开发工作
· 最终一致性,会存在数据不一致的中间状态
· 容易与业务耦合,难以实现通用
· 最终一致性,会存在数据不一致的中间状态
· 需要依赖消息中间件。
· 最终一致性,会存在数据不一致的中间状态
· 需要额外的定期校验机制对数据进行兜底
适用业务· 要求强一致性
· 短事务
· 并发量低
· 要求强一致性
· 短事务
· 并发量低
· 要求强一致性
· 短事务
· 并发量低
· 并发量高
· 允许出现短时间的数据不一致
· 并发量高
· 允许出现短时间的数据不一致
· 并发量高
· 允许出现短时间的数据不一致
· 需要与外部第三方进行交互
· 可以接受异步通知型方案
· 允许出现短时间的数据不一致
· 不希望依赖分布式事务中间件
· 可以接受异步通知型方案
· 允许出现短时间的数据不一致
· 允许出现短时间的数据不一致
· 跨平台、跨企业的系统间业务交互
· 外部系统网络环境复杂、不可信

2. 使用分布式事务中间件的弊端

  • 引入分布式事务中间件会造成系统大规模耦合。
  • TC(事务协调者)作为基础设施却需要对外部的 TM(事务管理器)暴露,一定程度上违背了微服务的理念。
  • 带来了额外的学习成本与开发成本,提高了开发者的使用门槛,如果用不好反而会带来更多棘手的问题。

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

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

相关文章

【MySQL索引】(重点)

文章目录 一、见见索引二、认识磁盘三、索引的学习1.建立共识2.重谈page3.单page和多page同样存在效率低下的问题单page的缺陷多page的缺陷 页目录单page多page B树为什么行!详谈细节 其他数据结构为什么不行?聚簇索引和非聚簇索引 回表查询 四、索引的操作1.创建主…

简单好用的文本识别方法--付费的好用,免费的更有性价比

文章目录 先说付费的进入真题,免费的来喏!PixPin微信 先说付费的 直达网址!!! 进入真题,免费的来喏! PixPin 商店里就有 使用示例: 可以看到:贴在桌面上的图片可以复制图片中的文字,真的很…

详细分析ping的基本知识以及常见网络故障的诊断(图文解析)

目录 前言1. 基本知识2. 常见故障分析2.1 请求超时2.2 域名无法解析 前言 由于全栈开发,在运维过程中难免会出现无法ping通等故障 针对多种情况进行详细分析 1. 基本知识 为了更好的加深ping的基本命令以及拓展更多知识点,详细科普其基本知识 ping&…

算法与数据结构汇总

刷题建议步骤 求职硬通货:一,好的学历,这个要下血本。本科,可以考研,读研。专科,可以专升本,再考研,读研,二,软考,一年考两次,有些科…

【Flutter】AppBar、TabBar和TabBarView

🔥 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏:Flutter学习 🌠 首发时间:2024年5月26日 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 目…

到底该用英文括号还是中文括号?

这篇博客写的还挺详细的,不错。

最重要的时间表示,柯桥外贸俄语小班课

в第四格 1、与表示“钟点”的数词词组连用 例: в шесть часов утра 在早上六点 в пять тридцать 在五点半 2、与表示“星期”的名词连用 例: в пятницу 在周五 в следующий понедельник …

使用printf的两种方法,解决printf不能使用的问题

使用printf的两种方法,解决printf不能使用的问题 一、微库法 我们使用printf前要加上重定向fputc //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)0);//循环发送,直到发送完毕 USART1->DR (uint8_t) ch; return…

数字图像处理冈塞雷斯第四版课后习题答案【英文原版】

第二章 第三章 . 第四章 傅里叶变换是一个线性过程,而计算梯度的平方根和平方根则是非线性运算。傅里叶变换可以用来计算微分的差值(如问题4.50),但必须在空间域中直接计算平方和平方根值。 (a)实际上,由于高通操作,环有一个暗中心…

LabelMe下载及关键点检测数据标注

本文关键点数据集链接,提取码:x1pk 1.LabelMe下载 这部分内容和YOLOv8_seg的标注软件是一样的,使用anaconda创建虚拟环境安装LabelMe,指令如下: conda create -n labelme python=3.6 -y conda activate labelme conda install pyqt conda install pillow pip install la…

Java进阶学习笔记23——API概述

API: API(Application Programming Interface)应用程序编程接口 就是Java帮我们写好了一些程序:如类、方法等等,我们直接拿过来用就可以解决一些问题。 为什么要学别人写好的程序? 不要重复造轮子。开发…

【Spring Boot】分层开发 Web 应用程序(含实例)

分层开发 Web 应用程序 1.应用程序分层开发模式:MVC1.1 了解 MVC 模式1.2 MVC 和三层架构的关系 2.视图技术 Thymeleaf3.使用控制器3.1 常用注解3.1.1 Controller3.1.2 RestController3.1.3 RequestMapping3.1.4 PathVariable 3.2 将 URL 映射到方法3.3 在方法中使用…

【JVM实践与应用】

JVM实践与应用 1.类加载器(加载、连接、初始化)1.1 类加载要完成的功能1.2 加载类的方式1.3 类加载器1.4 双亲委派模型1.5自定义ClassLoader1.6 破坏双亲委派模型2.1 类连接主要验证内容2.2 类连接中的解析2.3 类的初始化3.1 类的初始化时机3.2 类的初始化机制和顺序3.2 类的卸…

电子电器架构 - AUTOSAR软件架构Current Features in a Nutshell

电子电器架构 - AUTOSAR软件架构Current Features in a Nutshell 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的…

数据清洗操作及众所周知【数据分析】

各位大佬好 ,这里是阿川的博客 , 祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 前面的博客 数据分析—技术栈和开发环境搭建 …

7.Redis之String编码方式应用场景业务

1.内部编码 字符串类型的内部编码有 3 种: • int:8 个字节(64位)的⻓整型。 • embstr:⼩于等于 39 个字节的字符串。压缩字符串.适用于表示比较短的字符串。 • raw:⼤于 39 个字节的字符串。普通字…

红蓝对抗-HW红蓝队基本知识(网络安全学习路线笔记)

第一, 什么是蓝队 蓝队,一般是指网络实战攻防演习中的攻击一方。 蓝队一般会采用针对目标单位的从业人员,以及目标系统所在网络内的软件、硬件设备同时执行多角度、全方位、对抗性的混合式模拟攻击手段;通过技术手段实现系统提权、控制业务、…

阻塞信号集和未决信号集_代码实现

1. 程序验证内容 将编号为0,1,2添加到阻塞信号集中&#xff0c;i<信号编号时&#xff0c;发出信号&#xff0c;观察未决信号集状态 当解除阻塞后&#xff0c;原先的信号是否执行&#xff0c;执行顺序是什么 2. 代码实现 #include <unistd.h> #include <stdlib.h…

AI数据面临枯竭

Alexandr Wang&#xff1a;前沿研究领域需要大量当前不存在的数据&#xff0c;未来会受到这个限制 Alexandr Wang 强调了 AI 领域面临的数据问题。 他指出&#xff0c;前沿研究领域&#xff08;如多模态、多语言、专家链式思维和企业工作流&#xff09;需要大量当前不存在的数…