【分布式】浅谈分布式事务及解决方案

news2024/11/26 2:28:24

目录

一、背景

1.1、本地事务的基本概念

1.2、本地事务的基本特性

1.3、为什么需要分布式事务?

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

2.1、两阶段提交(2PC)

2.1.1、2PC实现原理

准备阶段(Prepare phase)

提交阶段(Commit phase)

场景枚举

2.2.2、2PC存在的问题

2.2、三阶段提交(3PC)

2.2.1、3PC实现原理

CanCommit 阶段

PreCommit 阶段

DoCommit 阶段

2.2.2、实现流程图解

2.2.3、3PC的缺点

2.3、柔性事务TCC

2.3.1、为什么会出现TCC?

2.3.2、TCC的实现原理

2.3.3、实现案例

2.3.4、存在的优势及不足

2.3.5、注意事项

业务操作分两阶段完成

允许空回滚

防悬挂控制

幂等控制

业务数据可见性控制

业务数据并发访问控制

2.4、基于消息队列的异步模型

2.4.1、业务方提供操作成功回查功能

2.4.2、本地消息表

三、参考

一、背景

1.1、本地事务的基本概念

事务就是一个程序执行单元,里面的操作要么全部执行成功,要么全部执行失败,不允许只成功一半另外一半执行失败的事情发生。例如一段事务代码做了两次数据库更新操作,那么这两次数据库操作要么全部执行成功,要么全部回滚。

1.2、本地事务的基本特性

  • Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失

1.3、为什么需要分布式事务?

其实分布式事务从实质上看与数据库事务的概念是一致的,既然是事务也就需要满足事务的基本特性(ACID),只是分布式事务相对于本地事务而言其表现形式有很大的不同。

本地事务的时代,如果需要同时操作数据库的多条记录,而这些操作可以放到一个事务中,那么我们可以通过数据库提供的事务机制就可以实现。

而随着微服务架构的推进,原本一个本地逻辑执行单元,被拆分到了多个独立的微服务中,这些微服务又分别操作了不同的数据库和表。

分布式事务是为了解决微服务架构(形式都是分布式系统)中不同节点之间的数据一致性问题。这个一致性问题本质上解决的也是传统事务需要解决的问题,即一个请求在多个微服务调用链中,所有服务的数据处理要么全部成功,要么全部回滚。当然分布式事务问题的形式可能与传统事务会有比较大的差异,但是问题本质是一致的,都是要求解决数据的一致性问题。

而分布式事务的实现方式有很多种,接下来我们分别来介绍下这几种分布式事务实现方式的原理。

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

2.1、两阶段提交(2PC)

两阶段提交又称2PC(two-phase commit protocol),2PC是一个非常经典的强一致、中心化的原子提交协议。这里所说的中心化是指协议中有两个角色:一个是分布式事务协调者(coordinator)和N个参与者(participant)。

2.1.1、2PC实现原理

两阶段提交,顾名思义就是要进行两个阶段的提交:第一阶段,准备阶段(投票阶段);第二阶段,提交阶段(执行阶段)。

准备阶段(Prepare phase)

  1. 分布式事务的发起方,向分布式事务协调者(事务管理器TransactionManager)发送请求,

  2. TransactionManager分别向参与者(Participant)A、参与者(Participant)B分别发送事务预处理请求,称之为Prepare,有些资料也叫”Vote Request”。

  3. 此时这些参与者节点一般来说就会打开本地数据库事务,然后开始执行数据库本地事务,每个数据库参与者在本地执行事务并写本地的Undo/Redo日志,但在执行完成后并不会立马提交数据库本地事务,而是先向TransactionManager进行“Vote Commit”的反馈,告知处理结果。

  4. 如果所有的参与者都向协调者做了“Vote Commit”的反馈的话,那么流程进入第二个阶段。

提交阶段(Commit phase)

场景枚举
  • 成功情况

如果所有参与者均反馈的是成功,协调者就会向所有参与者发送“全局提交确认通知(global_commit)”,参与者Participant就会完成自身本地数据库事务的提交,并将提交结果回复“ack”消息给协调者TransactionManager,然后协调者TransactionManager就会向调用方返回分布式事务处理完成的结果。如果有任何一个参与者返回失败,则回滚事务。

  • 失败情况

如果参与者向协调者反馈“Vote_Abort”消息,即返回了失败的消息。此时分布式事务协调者Coordinator就会向所有的参与者Participant发起事务回滚的消息(“global_rollback”),此时各个参与者就会回滚本地事务,释放资源,并且向协调者发送“ack”确认消息,协调者就会向调用方返回分布式事务处理失败的结果。

以上就是两阶段提交的基本过程了,那么按照这个两阶段提交协议,分布式系统的数据一致性问题就能解决么?

2.2.2、2PC存在的问题

其实,2PC只是通过增加了事务协调者(Coordinator)的角色来通过2个阶段的处理流程来解决分布式系统中一个事务需要跨多个服务的数据一致性问题。

以下几点是XA-两阶段提交协议中会遇到的一些问题:

  • 性能问题:2PC中的所有的参与者节点都为事务阻塞型,当某一个参与者节点出现通信超时,其余参与者都会被动阻塞占用资源不能释放。

  • 协调者单点故障问题:由于严重的依赖协调者,一旦协调者发生故障,而此时参与者还都处于锁定资源的状态,无法完成事务commit操作。虽然协调者出现故障后,会重新选举一个协调者,可无法解决因前一个协调者宕机导致的参与者处于阻塞状态的问题。

  • 网络闪断导致脑裂:第二阶段中协调者向参与者发送commit命令之后,一旦此时发生网络抖动,导致一部分参与者接收到了commit请求并执行,可其他未接到commit请求的参与者无法执行事务提交。进而导致整个分布式系统出现了数据不一致。

2.2、三阶段提交(3PC)

三阶段提交又称3PC,在2PC的基础上增加了CanCommit阶段,并引入了超时机制。一旦事务参与者迟迟没有收到协调者的Commit请求,就会自动进行本地commit,这样相对有效地解决了协调者单点故障的问题。

2.2.1、3PC实现原理
CanCommit 阶段
  1. 协调者向参与者发出CanCommit ,进行事务询问操作,所有参与者都反馈yes后,才能进入下一个阶段。(这一个阶段时不锁表,不像2pc 第一个阶段就开始锁表,3pc的阶段一是为了先排除个别参与者不具备提交事务能力的前提下,而避免锁表。)简单来说就是检查下自身状态的健康性。

  2. 有任何一个参与者反馈的结果是No,整个分布式事务就会中断,协调者就会向所有的参与者发送“abort”请求。

PreCommit 阶段
  1. 在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。此时分布式事务协调者会向所有的参与者发送PreCommit请求,参与者收到后开始执行事务操作,并将Undo和Redo信息记录到事务日志中。参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈“Ack”表示已经准备好提交,并等待协调者的下一步指令。

  2. 有任何一个参与者反馈的结果是No,或协调者在等待参与者节点反馈的过程中超时(2PC中只有协调者可以超时,参与者没有超时机制)。整个分布式事务就会中断,协调者就会向所有的参与者发送“abort”请求。

DoCommit 阶段
  1. 在阶段二中如果所有的参与者都可以进行PreCommit提交,那么协调者就会从“预提交状态”->“提交状态”。然后向所有的参与者发送”doCommit”请求,参与者在收到提交请求后,执行事务提交操作,并向协调者反馈“Ack”消息,协调者收到所有参与者的Ack消息后完成事务。

  2. 同样,如果有一个参与者节点未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送abort请求,从而中断事务。

2.2.2、实现流程图解

相比较2PC而言,3PC对于协调者(Coordinator)和参与者(Participant)都设置了超时时间,解决了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。

另外,通过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的。

2.2.3、3PC的缺点

3PC在去除阻塞的同时也引入了新的问题,那就是参与者接收到precommit消息后,如果出现网络分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。

2.3、柔性事务TCC

2.3.1、为什么会出现TCC?

无论是 2PC 还是 3PC,都存在一个大粒度资源锁定的问题。我们先来想象这样一种场景,用户在电商网站购买商品1000元,使用余额支付800元,使用红包支付200元。

我们看一下在 2PC 中的流程:

prepare 阶段:

  • 下单系统插入一条订单记录,不提交

  • 余额系统减 800 元,给记录加锁,写 redo 和 undo 日志,不提交

  • 红包系统减 200 元,给记录加锁,写 redo 和 undo 日志,不提交

commit 阶段:

  • 下单系统提交订单记录

  • 余额系统提交,释放锁

  • 红包系统提交,释放锁

为什么说这是一种大粒度的资源锁定呢?

因为在 prepare 阶段,当数据库给用户余额减 800 元之后,为了维持隔离性,会给该条记录加锁,在事务提交前,其它事务无法再访问该条记录。

但实际上,我们只需要预留其中的 800 元,不需要锁定整个用户余额。这是 2PC 和 3PC 的局限,因为这两者是资源层的协议,无法提供更灵活的资源锁定操作。

为了解决这个问题,TCC 应运而生。TCC 本质上也是一个二阶段提交协议,但和 JTA 中的二阶段协议不同的是,它是一个服务层的协议,因此开发者可以根据业务自由控制资源锁定的粒度。

2.3.2、TCC的实现原理

TCC 将事务的提交过程分为 try-confirm-cancel(实际上 TCC 就是 try、confirm、cancel 的简称) 三个阶段:

  • try:完成业务检查、预留业务资源

  • confirm:使用预留的资源执行业务操作(需要保证幂等性)

  • cancel:取消执行业务操作,释放预留的资源(需要保证幂等性)

流程如下:

  1. 事务发起方向事务协调器发起事务请求,事务协调器调用所有事务参与者的 try 方法完成资源的预留,这时候并没有真正执行业务,而是为后面具体要执行的业务预留资源,这里完成了一阶段。

  2. 如果事务协调器发现有参与者的 try 方法预留资源时候发现资源不够,则调用参与方的 cancel 方法回滚预留的资源,需要注意 cancel 方法需要实现业务幂等,因为有可能调用失败(比如网络原因参与者接受到了请求,但是由于网络原因事务协调器没有接受到回执)会重试。

  3. 如果事务协调器发现所有参与者的 try 方法返回都 OK,则事务协调器调用所有参与者的 confirm 方法,不做资源检查,直接进行具体的业务操作。

  4. 如果协调器发现所有参与者的 confirm 方法都 OK 了,则分布式事务结束。

  5. 如果协调器发现有些参与者的 confirm 方法失败了,或者由于网络原因没有收到回执,则协调器会进行重试。这里如果重试一定次数后还是失败,常见的是做事务补偿。

2.3.3、实现案例

通过一个支付场景看看 TCC 在该场景中的流程:

Try 操作

  • tryX 下单系统创建待支付订单

  • tryY 冻结账户红包 200 元

  • tryZ 冻结资金账户 800 元

Confirm 操作

  • confirmX 订单更新为支付成功

  • confirmY 扣减账户红包 200 元

  • confirmZ 扣减资金账户 800 元

Cancel 操作

  • cancelX 订单处理异常,资金红包退回,订单支付失败

  • cancelY 冻结红包失败,账户余额退回,订单支付失败

  • cancelZ 冻结余额失败,账户红包退回,订单支付失败

可以看到,我们使用了冻结代替了原先的账号锁定(实际操作中,冻结操作可以用数据库减操作+日志实现),这样在冻结操作之后,事务提交之前,其它事务也能使用账户余额。

2.3.4、存在的优势及不足

这种分布式事务的实现方式的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。

而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。

// 改动前
// 修改代码状态
orderClient.updateStatus();

// 改动后
orderClient.tryUpateStatus();
orderClient.confirmUpateStatus();
orderClient.cancelUpateStatus();

此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口还必须实现幂等。

2.3.5、注意事项
业务操作分两阶段完成

接入TCC前,业务操作只需要一步就能完成,但是在接入TCC之后,需要考虑如何将其分成2阶段完成,把资源的检查和预留放在一阶段的Try操作中进行,把真正的业务操作的执行放在二阶段的Confirm操作中进行;

TCC服务要保证第一阶段Try操作成功之后,二阶段Confirm操作一定能成功;

允许空回滚

事务协调器在调用TCC服务的一阶段Try操作时,可能会出现因为丢包而导致的网络超时,此时事务协调器会触发二阶段回滚,调用TCC服务的Cancel操作。

TCC服务在未收到Try请求的情况下收到Cancel请求,这种场景被称为空回滚;TCC服务在实现时应当允许空回滚的执行。

防悬挂控制

事务协调器在调用TCC服务的一阶段Try操作时,可能会出现因网络拥堵而导致的超时,此时事务协调器会触发二阶段回滚,调用TCC服务的Cancel操作;在此之后,拥堵在网络上的一阶段Try数据包被TCC服务收到,出现了二阶段Cancel请求比一阶段Try请求先执行的情况;

用户在实现TCC服务时,应当允许空回滚,但是要拒绝执行空回滚之后到来的一阶段Try请求;

幂等控制

无论是网络数据包重传,还是异常事务的补偿执行,都会导致TCC服务的Try、Confirm或者Cancel操作被重复执行;用户在实现TCC服务时,需要考虑幂等控制,即Try、Confirm、Cancel 执行次和执行多次的业务结果是一样的。

业务数据可见性控制

TCC服务的一阶段Try操作会做资源的预留,在二阶段操作执行之前,如果其他事务需要读取被预留的资源数据,那么处于中间状态的业务数据该如何向用户展示,需要业务在实现时考虑清楚;通常的设计原则是“宁可不展示、少展示,也不多展示、错展示”。

业务数据并发访问控制

TCC服务的一阶段Try操作预留资源之后,在二阶段操作执行之前,预留的资源都不会被释放;如果此时其他分布式事务修改这些业务资源,会出现分布式事务的并发问题。

用户在实现TCC服务时,需要考虑业务数据的并发控制,尽量将逻辑锁粒度降到最低,以最大限度的提高分布式事务的并发性。

2.4、基于消息队列的异步模型

基于消息队列的异步模型指的是在核心业务执行完成后,同步的对外发出一个消息,供其他模块消费使用后执行各自的业务。

例:电商的下单操作,假如其他的验证都已经完成,满足下单的情况下,给订单表写入订单信息后,系统生成了订单号,订单模块知道把带订单号的订单信息对外发出一个消息(MQ),下单操作就算完成。订单模块发出的MQ供后续的库存扣减,财务收款,仓库生产等业务使用,这里的库存扣减,财务收款和仓库生产属于不同的模块,各自的操作有自己的事务,这就实现了把一个大事务拆分为多个小事务,各自去执行,互不影响,提升系统性能的目的。

目前基于消息队列的异步模型,其实现方式有多种,在这里我列出两种进行介绍,一种是业务方提供本地操作成功回查功能,一种是基于本地事务消息表。

2.4.1、业务方提供操作成功回查功能

整体的流程描述:本地事务执行前,把需要发送的mq消息先发送到MQ服务器上,但该消息属于不能投递的消息,需要有标识标明。当MQ发送方收到MQ服务器返回的收到发送的mq消息的确认后,执行本地事务,根据本地事务的执行结果再向MQ的服务器发送该消息的本地事务执行结果,告诉MQ服务器是把mq消息投递到消费方还是把mq消息回滚丢弃。当MQ服务端超时未收到MQ发送端对mq消息的处理通知(Commit OR Rollback)时,MQ服务端会向MQ发送方进行查询该mq消息的事务状态,以确定该mq消息的处理结果是投递还是丢弃。整体的操作流程图如下:

该方案需要业务方针对每一个事务提供一个回查接口给MQ服务端;同时,MQ服务端还需要有定时任务来检查未投递的消息,并计算消息是否已经超时,如果已经超时需要回查业务方提供的回查事务状态接口以便确认对该消息的处理;该方案对业务的侵入比较大,不利于方案的扩展。

目前支持该模式的消息队列有Apache RocketMQ。

可参考:【RocketMQ】揭开事务消息的神秘面纱

2.4.2、本地消息表

该方案指的是主业务数据表和待发送的消息存储表共存于同一个数据库,便于数据写入的时候由一个事务保证,数据写入成功后,事务即成功。此时,需要一个任务来执行对消息表里的消息进行发送到MQ,消息发送MQ成功后,删除消息表里的消息,达到异步处理的目的。比如:还是下单操作,下单完成后,需要通知库存扣减库存,财务进行收款,仓库进行发货等操作,设计时,可以把订单表与订单消息表共同存储到一个数据库里,当订单表写入的时候也同步写订单消息表,2个表同时写成功后,事务才算成功。然后再通过一个任务来查询订单消息表把订单消息表里的消息发送到MQ,当收到MQ的成功回执消息后,再把消息表里的消息进行删除。库存扣减、财务收款、仓库发货等均消费MQ里的该消息来完成各自的业务操作。

该方式的操作流程模型如下:

在该方案模型中,当MQ发送方把消息发送后,长时间未收到MQ服务端的结果回执,此时需要再次发送该消息,这导致消息的发送可能会重复多次发送,需要消费方保证处理消息的接口幂等;该方案的优点是对业务的侵入小,核心业务只需要关注把自己业务做完的同时把需要发送的消息写入消息表即可。该方案也是在企业生产中落地实现用的比较多的方案之一。

三、参考

  • 京东物流技术团队|分布式事务,你了解多少?

  • 阿里云|分布式事务之TCC服务设计和实现注意事项

  • 京东云开发者|浅谈分布式事务及解决方案

  • 看了 5种分布式事务方案,我司最终选择了 Seata,真香!

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

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

相关文章

Oracle-pl/sql developer客户端连接报错问题分析

问题一: 用户在windows电脑使用pl/sql developer客户端使用tns方式连接数据库时,出现ORA-12170 TNS连接超时报错 使用ezconnect方式连接可以成功 问题一分析: 首先,查看pl/sql developer软件的Oracle客户端配置configure-->preferences,确…

详细介绍下OP-TEE,以及TF-A与OP-TEE的关系

什么是OP-TEE OP-TEE(Open Portable Trusted Execution Environment)是一个开源的可信执行环境(TEE)框架,用于嵌入式系统中的安全应用程序执行。它提供了一种安全的执行环境,用于保护敏感数据和执行安全操…

JRT文件服务实现

网站与客户端打印和导出方面已经无大碍了,今天抽时间整整文件服务,文件服务设计可以查看下面连接。原理一样,代码会有些变化。 文件服务设计 首先实现文件服务的服务端,就是一个业务脚本,用来接收上传、移动和删除文件…

大华摄像头windows、linuxJavaSDK开发使用

文章目录 简介环境要求库加载问题及解决方法大华摄像头Java SDK,完成摄像头设备登录、视频录像目录结构windows 的c代码Linux的C代码项目结构 登录云台控制录像调用的接口注意码云地址 简介 本文档主要介绍 SDK 接口参考信息,包括主要功能、接口函数和回…

使用Git进行版本控制

参考:《Python编程从入门到实践》 前言1、安装、配置 Git1.1 在Linux系统中安装Git1.2 在OS X系统中安装Git1.3 在Windows系统中安装Git1.4 配置Git 2、创建项目3、忽略文件4、初始化仓库5、检查状态6、将文件加入到仓库中7、执行提交8、查看提交历史 前言 版本控制…

计算机毕业设计 SpringBoot的乐乐农产品销售系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

stu05-前端的几种常用开发工具

前端的开发工具有很多,可以说有几十种,包括记事本都可以作为前端的开发工具。下面推荐的是常用的几种前端开发工具。 1.DCloud HBuilder(轻量级) HBuilder是DCloud(数字天堂)推出的一款支持HTML5的web开发…

HCIP---RSTP/MSTP

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 STP协议虽然能够解决环路问题,但是收敛速度慢,影响了用户通信质量。IEEE于2001年发布的802.1w标准定义了快速生成树协议RSTP(Rapid Spanning-Tree Proto…

309. 买卖股票的最佳时机含冷冻期(leetcode) 动态规划思想

文章目录 前言一、题目分析二、算法原理1.状态表示2.状态转移方程3.初始化边界条件4.填表顺序5.返回值是什么 三、代码实现总结 前言 在本文章中,我们将要详细介绍一下Leetcode中买卖股票的最佳时机含冷冻期相关的内容,本题采用动态规划的思想解决 一、…

Android Studio Gradle下载慢解决方法

Android Studio Gradle下载慢解决方法 最近在练习模型部署,主要是在手机端部署,所以使用到了Android Studio,但是在创建项目的时候,一致在下载gradle,而且网速还很慢,不对,是极慢哪种&#xff0…

研表究明,文字的序顺并不定一能响影GPT-4读阅

深度学习自然语言处理 原创作者:yy 很多年前,你一定在互联网上看过这张图,展示了人脑能够阅读和理解打乱顺序的单词和句子!而最近东京大学的研究发现,大语言模型(LLMs) 尤其是 GPT-4&#xff0c…

【设计模式--创建型--原型模式】

设计模式--创建型--原型模式 原型模式概述结构实现结果 案例代码结果使用场景 扩展(深\浅克隆)浅克隆演示:结果:使用深克隆(利用对象流)结果 原型模式 概述 用一个已经创建的实例作为原型,通过…

【MySQL】MySQL库的操作

MySQL库的操作 一、创建数据库创建数据库案例字符集和校验规则校验规则对数据库的影响 二、操纵数据库1、查看数据库2、查看当前正在使用的数据库3、使用数据库4、显示创建语句5、数据库删除6、数据库的修改7、备份和恢复8、查看连接情况 一、创建数据库 创建数据库的语法如下…

使用python绘制现有彩票记录走势图

在数据分析和可视化的领域中,彩票走势图是一个经典的例子,它可以展示彩票数字随时间的出现频率和趋势。这里使用英国使用EuroMillions彩票的历史数据作为示例,使用Python和Matplotlib库来创建一个简单的走势图。可以在以下网站搜索.csv文件。…

基于SSM的剧本杀预约系统的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

Promise与async/await的简单介绍

在 JavaScript 中,处理异步操作一直是开发者们面临的挑战之一。传统的回调函数方式往往导致代码难以维护、可读性差、易产生回调地狱等问题。为了解决这些问题,出现了 Promise 和 Async/Await 这两种处理异步操作的方式。 一、异步产生问题示例 当我们…

6.4 U-boot 移植

一、ST 官方 U-boot 编译测试 1. ST 官方 uboot 源码打补丁 1.1 获得 ST 官方的 uboot 源码 https://www.cnblogs.com/toutiegongzhu/p/17578847.html 这里可以看如何下载uboot源码。解压完后输入以下命令: cd stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/s…

什么是图片懒加载(image lazy loading)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

区块链媒体宣发:揭示优势与趋势,引领信息传播新时代

在数字化潮流中,区块链技术正以惊人的速度改变着传媒行业的格局。从区块链媒体宣发中获得的种种优势和未来的趋势,不仅为企业带来了新的推广途径,也在信息传播领域掀起了一场革命。本文将深入探讨区块链媒体宣发的优势以及未来的发展趋势。 1…

一款基于ESP32的迷你四足机器人

一、软件介绍 增加自定义动作模式,可以在小程序中自定义一个最多10个步骤的动作。 附件中:带自定模式固件bin.zip esp32c3固件文件 烧录下图设置 无串口版本esp32c3开发板烧录前先按住BOOT键再插线进入烧录模式,LoadMode选择USB。 二、AP…