微服务系列六:分布式事务与seata

目录

实验环境说明

前言

一、分布式事务问题与策略

1.1 分布式事务介绍

1.2 分布式事务解决策略分析

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

2.1 认识Seata

2.2 Seata的工作原理

2.3 部署Seata微服务

2.3.1 准备数据库表

2.3.2 准备配置文件

2.3.3 docker部署

2.4 微服务集成Seata

2.4.1 引入Seata依赖

2.4.2 添加共享配置 

2.4.3 添加引导配置

2.4.4 导入数据库备份表AT

2.5 测试Seata的效果

2.5.1 修改事务注解@GlobalTransactional

2.5.2 重启测试Seata分布式事务

三、Seata解决分布式事务问题的策略模式介绍

3.1 Seata的四种策略

3.2 (拓展)XA规范

四、XA策略模式 : 先阻塞后一并提交

4.1 XA事务模型

4.2 XA执行流程

4.3 XA优缺点分析

4.4 XA模式实现步骤

五、AT策略模式: 先提交备份后修复

4.1 AT事务模型

4.2 AT执行流程

4.3 AT模式的实现步骤

4.3 AT模式测试

六、分布式微服务知识追问巩固


实验环境说明

本文有部分地方需要实验进行。首先对于看过黑马微服务的同学应该会比较熟悉。如果没有你也可以参考我实验的环境搭个简单的测试环境,用于实验。实验的目的也是为了更好的理解业务、理解知识点。

本地环境部分:

服务名端口号备注
nginx18080 / 18081前端运行环境
sentinel8090服务保护监控
hm-gateway8080后端项目网关模块
item-service8081后端商品服务模块
cart-service8082 后端购物车服务模块
item-service28083后端商品服务模块
item-service38084后端商品服务模块
user-service8085后端用户管理模块
trade-service8086后端交易服务模块
pay-service8087后端支付服务模块

远程服务器环境部分:

服务名端口号备注
nacos8848注册中心及配置中心,非容器镜像
nginx18080/18081线上前端运行环境,容器镜像
mysql3306线上数据库,容器镜像
docker-hm8080线上后端运行环境,容器镜像
seata7099分布式事务解决方案模块,非容器镜像

注意事项:

  • 远程环境中非容器镜像指nacos、seata是后单独配置的容器,而mysql、nginx、docker-hm是使用compose统一部署的。
  • 在本节实验中,线上环境的nginx和docker-hm我们不会使用到,而是使用本地的nginx和后端项目
  • 请你确保在配置线上环境时,mysql必须比nacos 和 seata先启动。如果nacos、seata先启动将无法连接数据库。此时你需要停止nacos/seata容器,先启动mysql。
  • 部署seata服务的数据库表等相关资料可以在黑马Springcloud课程中获得。或者后期有需要也会整理一份。

前言

本篇是微服务入门系列的最后一篇,先前我们逐步学习了微服务的远程调用、服务治理、请求路由、身份认证、配置管理、服务保护等知识。

微服务作为分布式的系统项目,难免会遇到分布式事务等相关问题。本篇将会从分布式事务照成的数据不一致问题出发,去探讨一个相对完善的分布式事务解决方案。

一、分布式事务问题与策略

1.1 分布式事务介绍

以购物车下单业务为例,该业务目前是否满足ACID特性呢?

下单业务,前端请求首先进入订单服务,创建订单并写入数据库。然后订单服务调用购物车服务和库存服务:

  • 购物车服务负责清理购物车信息
  • 库存服务负责扣减商品库存

如图所示,当前两部分请求成功后都直接提交了,可是商品库存不足导致扣减库存部分失败了。这就导致了订单创建了、购物车清空了,但是库存是不足的这种矛盾的产生。这就是数据一致性问题。

所谓的分布式事务就是为了解决这种问题。我们希望创建订单、清空购物车、扣减库存这几个动作一起成功,一起失败。在单体项目中很好解决,我们只需要添加@Transactional注解即可。不过在微服务架构中,这种事务原子性就比较复杂了。

分布式事务实验】将商品库存改成0,然后尝试下单,查看购物车清空清空和商品库存接口的矛盾性。

1.2 分布式事务解决策略分析

那么,如何做到分布式事务一起成功/一起失败呢?

其实方法思维还是很简单的,参考单体项目的@Transactional。我们只需要判断所有的事务全部成功后再一并提交,这就是一种解决策略。(先阻塞后一并提交)

除此之外,还可以这么做。仍然是每个动作执行成功后提交,但是在提交之前保存一份备份。我们只需要判断是否所有的事务执行成功,如果不是的话,那就恢复备份。这样也是一种解决策略。(先各自提交,后回滚修复)

但是,我们又如何知道分布式事务从哪里开始到哪里结束呢?

这个过程无疑是最难判断的。好在我们市面上有许多成熟的工具,可以帮助我们完成这一点。本篇之中,我们会使用seata分布式事务解决方案工具。

总结

分布式事务方案
先阻塞等待,等完全成功后一并提交事务
先各自提交做好备份,如果有事务失败了,大家一起恢复备份状态

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

2.1 认识Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

Seata 是什么? | Apache Seataicon-default.png?t=O83Ahttps://seata.apache.org/zh-cn/docs/overview/what-is-seata/我们前面讲过了,分布式事务系统中,最关键的就是确定事务从哪里开始,到哪里结束。确定好这一部分,分布式事务就比较好解决了。而seata就是一个统一的事务协调者,与多个分支事务通信,检测每个分支事务的执行状态,保证全局事务下的每一个分支事务同时成功或失败。

2.2 Seata的工作原理

在Seata的事务管理中有三个重要的角色:

  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。

  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。

  • RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

Seata的工作架构图

  • TMRM:可以理解为Seata的客户端部分,引入到参与事务的微服务依赖中即可。会协助微服务,实现本地分支事务与TC之间交互,实现事务的提交或回滚。
  • TC: 事务协调中心(SEATA),是一个独立的微服务,需要单独部署。

2.3 部署Seata微服务

2.3.1 准备数据库表

TC服务在运行过程中需要管理事务相关,像事务从哪里开始到哪里结束等。因此我们需要配置相应的数据库连接。

目前我们只需要导入TC表即可

2.3.2 准备配置文件

准备资料里有个seata目录,都要上传到服务器/root目录下

查看applictaion.yml

server:port: 7099spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${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_logstashconsole:user:username: adminpassword: adminseata:config:# support: nacos, consul, apollo, zk, etcd3type: file# nacos:#   server-addr: ca355066792d:8848#   group : "DEFAULT_GROUP"#   namespace: ""#   dataId: "seataServer.properties"#   username: "nacos"#   password: "nacos"registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 192.168.186.140:8848group : "DEFAULT_GROUP"namespace: ""username: "nacos"password: "nacos"
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/loginserver:# service-port: 8091 #If not configured, the default is '${server.port} + 1000'max-commit-retry-timeout: -1max-rollback-retry-timeout: -1rollback-retry-timeout-unlock-enable: falseenable-check-auth: trueenable-parallel-request-handle: trueretry-dead-threshold: 130000xaer-nota-retry-timeout: 60000enableParallelRequestHandle: truerecovery:committing-retry-period: 1000async-committing-retry-period: 1000rollbacking-retry-period: 1000timeout-retry-period: 1000undo:log-save-days: 7log-delete-period: 86400000session:branch-async-queue-size: 5000 #branch async remove queue sizeenable-branch-async-remove: false #enable to asynchronous remove branchSessionstore:# support: file 、 db 、 redismode: dbsession:mode: dblock:mode: dbdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://mysql:3306/seata?rewriteBatchedStatements=true&serverTimezone=UTCuser: rootpassword: 123min-conn: 10max-conn: 100global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000# redis:#   mode: single#   database: 0#   min-conn: 10#   max-conn: 100#   password:#   max-total: 100#   query-limit: 1000#   single:#     host: 192.168.150.101#     port: 6379metrics:enabled: falseregistry-type: compactexporter-list: prometheusexporter-prometheus-port: 9898transport:rpc-tc-request-timeout: 15000enable-tc-server-batch-send-response: falseshutdown:wait: 3thread-factory:boss-thread-prefix: NettyBossworker-thread-prefix: NettyServerNIOWorkerboss-thread-size: 1
  • server.port :7099 是seata服务的运行端口
  • spring.application.name :seata-server 是seata的服务名称
  • seara.config 是seata的配置部分
    • type: file 表示配置文件默认写在本文件下
    • registry:表示将seata微服务注册到哪个注册中心
      • type:nacos 本次实验选取的注册中心是nacos
      • nacos:这里配置的是nacos相关参数,需要注意
        • server-addr:192.168.186.140:8848 这里指定访问地址,我们等会部署到云端,可以通过容器名进行访问,抱歉这里我的容器名不是nacos,所以我直接使用IP地址进行访问
        • group:“DEFAULT_GROUP” 这个分组一定要指定,和其他微服务要一致
        • namespace: 命名空间,不填就是默认default
        • username: nacos 登录账号
        • password: nacos 登录密码
      • console:
        • user:配置seata控制台的登录账号密码
          • username: admin
          • password: admin
  • store: 配置seata的存储相关
    • mode: db 存储到db文件
    • db: 配置数据库的连接信息参数

2.3.3 docker部署

查看网络段信息

注意,一定要确保seata部署的网络段要和nacos和mysql一致!不清楚的可以先查询网络段信息。 

我们网络段为 : zhicong2

创建容器

在虚拟机的/root目录执行下面的命令:

docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=192.168.186.140 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network zhicong2 \
-d \
seataio/seata-server:1.5.2

查看容器

查看控制台

2.4 微服务集成Seata

参与分布式事务的每一个微服务都需要集成Seata,我们以交易微服务trade-service为例。

2.4.1 引入Seata依赖

为了方便各个微服务集成seata,我们后面会把把seata的配置注册到nacos中,所以trade-service模块不仅要引入seata依赖,也要引入nacos依赖

<!--统一配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--读取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency>

2.4.2 添加共享配置 

在nacos上添加一个共享的seata配置,命名为shared-seata.yaml

seata:registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址type: nacos nacos:server-addr: 192.168.186.140:8848  namespace: "" # namespace,默认为空group: DEFAULT_GROUP application: seata-server username: nacospassword: nacostx-service-group: hmall service:vgroup-mapping: # 事务组与tc集群的映射关系hmall: "default"

2.4.3 添加引导配置

在trade-service模块的bootstrap.yaml添加seata共享配置引导:

spring:application:name: trade-service # 服务名称profiles:active: devcloud:nacos:server-addr: 192.168.186.140:8848 # nacos地址config:file-extension: yaml # 文件后缀名shared-configs: # 共享配置- dataId: shared-jdbc.yaml # 共享mybatis配置- dataId: shared-log.yaml # 共享日志配置- dataId: shared-swagger.yaml # 共享日志配置- dataId: shared-seata.yaml # 共享seata配置

2.4.4 导入数据库备份表AT

 seata的客户端在解决分布式事务的时候需要记录一些中间数据,保存在数据库中。因此我们要先准备一个这样的表。

将seata-at.sql分别文件导入项目模块的数据库中:

其他模块也是一样的,去试试吧!

2.5 测试Seata的效果

其实到这里Seata已经可以正常使用了。接下来就让我们实验一下如何实验Seata吧

2.5.1 修改事务注解@GlobalTransactional

找到trade-service模块下的com.hmall.trade.service.impl.OrderServiceImpl类中的createOrder方法,也就是下单业务方法。将其上的@Transactional注解改为Seata提供的@GlobalTransactional

@GlobalTransactional注解的作用:

这个注解是seata提供的,用于标记分布式事务的入口的注解,将来TM就会基于这个方法判断全局事务范围,初始化全局事务。

2.5.2 重启测试Seata分布式事务

【重启项目】

查看购物车】下单小白鞋为例

修改购物车库存为0

 【点击下单

查看购物车是否删减】没有删减

查看控制台信息

交易微服务下单报错、商品微服务更新接口报错、购物车也不再执行删除的接口

三、Seata解决分布式事务问题的策略模式介绍

3.1 Seata的四种策略

Seata支持四种不同的分布式事务解决方案:XA、TCC、TA、SAGA

其中XA和TA正是我们开篇思考出来的两者策略,因此本篇文章会着重讲解这两者策略是如何使用的,Seata又是如何帮我们实现的。

Seata四种模式的特点介绍

  1. XA模式

    • 强一致性:XA模式是四种模式中唯一支持强一致性的。在XA模式下,当本地事务提交而全局事务未提交时,直接操作数据库也无法看到本地事务提交的数据。
    • 可靠性高但性能较低:由于其强一致性的保证,XA模式相对其他模式来说更加可靠,但这也导致了其性能相对较低。
  2. TCC模式

    • 不依赖RM支持:TCC(Try-Confirm-Cancel)模式不依赖于资源管理器(RM)对分布式事务的支持,而是通过对业务逻辑的分解来实现分布式事务。
    • 手动实现三个方法:在TCC模式下,所有事务都需要手动实现Try、Confirm、Cancel三个方法。这增加了业务代码的复杂性,但提供了更高的灵活性。
    • 二阶段提交:TCC模式也采用二阶段提交机制,但与AT模式不同的是,TCC对业务代码的侵入性很强。
  3. AT模式

    • 无入侵式:AT模式是一种对业务无入侵式的分布式事务解决方案。用户只需关注自己的业务SQL,Seata框架会自动生成事务的二阶段提交和回滚操作。
    • 两阶段提交机制:AT模式采用两阶段提交机制。在一阶段,业务数据和回滚日志记录在同一个本地事务中提交;在二阶段,根据全局事务的状态决定是提交还是回滚。
    • 快速提交与异步回滚:一阶段的提交是异步化的,非常快速;而回滚则是通过一阶段的回滚日志进行反向补偿。
  4. SAGA模式

    • 补偿协议:Saga是一种补偿协议,在Saga模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务。
    • 正向与逆向操作:用户需要根据业务场景实现每个参与者的正向操作和逆向回滚操作。如果所有正向操作都执行成功,则分布式事务提交;如果任何一个正向操作失败,则分布式事务会执行前面各参与者的逆向回滚操作。
    • 灵活性高:Saga模式提供了很高的灵活性,可以根据业务场景进行定制化的实现。 

3.2 (拓展)XA规范

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。

简单理解,XA规范就是把事务分成了两阶段工作,以下是各个阶段进行的工作:

一阶段:

  • 事务协调者通知每个事务参与者执行本地事务

  • 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁

二阶段:

  • 事务协调者基于一阶段的报告来判断下一步操作

  • 如果一阶段都成功,则通知所有事务参与者,提交事务

  • 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务

四、XA策略模式 : 先阻塞后一并提交

4.1 XA事务模型

Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:

4.2 XA执行流程

RM一阶段的工作:

  1. 注册分支事务到TC

  2. 执行分支业务sql但不提交

  3. 报告执行状态到TC

TC二阶段的工作:

  TC检测各分支事务执行状态

  1. 如果都成功,通知所有RM提交事务

  2. 如果有失败,通知所有RM回滚事务

RM二阶段的工作:

  • 接收TC指令,提交或回滚事务

4.3 XA优缺点分析

  • 事务的强一致性,满足ACID原则

  • 常用数据库都支持,实现简单,并且没有代码侵入

  • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差

  • 依赖关系型数据库实现事务

4.4 XA模式实现步骤

调整配置文件】在nacos中,修改shared-seata.yaml配置文件,指定XA模式

seata:data-source-proxy-mode: XA

标记分布式事务入口】在需要用到分布式事务的方法上,依旧是添加@GlobalTransactional注解

五、AT策略模式: 先提交备份后修复

AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。是典型的空间换时间策略。

4.1 AT事务模型

事务模型可以看出,AT策略模式不会锁死请求,而是形成数据库备份,如果后续出现了事务异常,全部执行回滚恢复。利用备份解决了XA模式中锁定数据库资源的弊端。因此也是Seata默认的分布式事务策略。

4.2 AT执行流程

阶段一RM的工作:

  • 注册分支事务

  • 记录undo-log(数据快照)

  • 执行业务sql并提交

  • 报告事务状态

阶段二提交时RM的工作:

  • 删除undo-log即可

阶段二回滚时RM的工作:

  • 根据undo-log恢复数据到更新前

4.3 AT模式的实现步骤

导入备份表】先前已经导入过了

调整配置文件】 修改shared-seata.yaml文件,指定AT模式(其实不配置默认就是AT模式)

seata:data-source-proxy-mode: AT

标记分布式事务入口】在需要用到分布式事务的方法上,依旧是添加@GlobalTransactional注解

4.3 AT模式测试

我们测试一下AT模式中生成数据库备份,并且后续删除的过程

给扣减库存方法打断点,验证数据库快照的生成

放行断点后,数据库快照删除

观察控制台

六、分布式微服务知识追问巩固

1. 什么是分布式事务?分布式事务问题是如何发生的?

2. 单体项目中如何解决数据不一致问题?

3. 微服务如何解决数据不一致问题?你能想到有哪些方案?

4. 事务管理中有哪些角色?它们分别的作用是什么?

5. 你了解过Seata么?它在事务管理中充当了一个什么样的角色?

6. 请你谈谈Seata的工作原理是什么?

7. 分布式事务中,Seata是如何标记分布式事务的入口与出口?

8. 介绍一下什么是XA事务解决策略模式?它的优缺点是什么?

9. 介绍一下什么是AT事务解决策略模式?它与XA模式的不同点?

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

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

相关文章

adb:Android调试桥

Android 调试桥 (adb) 是一种功能多样的命令行工具&#xff0c;可以通过命令行与设备进行通信。 查询设备 adb devices adb 会创建一个字符串&#xff0c;用于通过端口号唯一标识设备。 adb devices -l 加入 -l 选项&#xff0c;devices 命令会告知设备是什么。当连接了多个…

【C语言】分支和循环详解(下)猜数字游戏

与诸君共进步&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 文章目录 1. 随机数的生成2. 猜数字小游戏的实现 1. 随机数的生成 掌握了前⾯学习的这些知识&#xff0c;我们就可以写⼀些稍微有趣的代码了&#xff0c;⽐如&#xff1a; 写⼀个猜数字游戏 游戏要求…

Java | Leetcode Java题解之第546题移除盒子

题目&#xff1a; 题解&#xff1a; class Solution {int[][][] dp;public int removeBoxes(int[] boxes) {int length boxes.length;dp new int[length][length][length];return calculatePoints(boxes, 0, length - 1, 0);}public int calculatePoints(int[] boxes, int l…

Pytorch学习--神经网络--现有网络模型的使用及修改

一、VGG16 weights (Optional[VGG16_Weights]): 这个参数是可选的&#xff0c;指的是预训练的权重。用户可以选择使用不同的预训练权重&#xff0c;具体可参见 VGG16_Weights 的详细说明。默认情况下&#xff0c;如果不提供此参数&#xff0c;模型将不会使用任何预训练权重。 p…

内部知识库:优化企业培训流程的关键驱动力

在当今快速变化的商业环境中&#xff0c;企业培训的重要性日益凸显。内部知识库作为整合、管理和分享企业内部学习资源的关键工具&#xff0c;正逐步成为优化企业培训流程的核心。以下将探讨内部知识库如何通过多种功能&#xff0c;助力企业提升培训效率、质量和员工满意度。 …

若依系统前端项目解读——从使用过程解读

登录系统 用户初次登录&#xff0c;浏览器中未存用户信息&#xff08;token&#xff09;&#xff0c;需向后端请求并保存至浏览器中用户再次登录系统&#xff0c;向后端发请求会携带token在请求头中&#xff0c;并与后端Redis缓存的token比较&#xff0c;判断token是否还在有效…

前后端交互接口(三)

前后端交互接口&#xff08;三&#xff09; 前言 前两集我们先做了前后端交互接口的约定以及浅浅的阅读了一些proto代码。那么这一集我们就来看看一些重要的proto代码&#xff0c;之后把protobuffer给引入我们的项目当中&#xff01; gateway.proto 我们来看一眼我们的网关…

【Python TensorFlow】进阶指南

在前文中&#xff0c;我们介绍了TensorFlow的基础知识及其在实际应用中的初步使用。现在&#xff0c;我们将进一步探讨TensorFlow的高级特性&#xff0c;包括模型优化、评估、选择、高级架构设计、模型部署、性能优化等方面的技术细节&#xff0c;帮助读者达到对TensorFlow的精…

2款使用.NET开发的数据库系统

今天大姚给大家分享2款使用.NET开发且开源的数据库系统。 Garnet Garnet是一款由微软研究院基于.NET开源的高性能、跨平台的分布式缓存存储数据库&#xff0c;该项目提供强大的性能&#xff08;吞吐量和延迟&#xff09;、可扩展性、存储、恢复、集群分片、密钥迁移和复制功能…

【react】React Router基础知识

1. 基础用法 npm i react-router-dom通过浏览器地址栏的切换&#xff0c;可以实现不同组件之间的切换。 import React from "react"; import ReactDOM from "react-dom/client"; // import App from "./App"; import reportWebVitals from &qu…

std::back_inserter

std::back_inserter 是 C 标准库中的一个函数模板&#xff0c;它用于创建一个插入迭代器&#xff08;insert iterator&#xff09;&#xff0c;这个迭代器可以在容器末尾插入新元素。它定义在 <iterator> 头文件中。 函数原型 template <typename Container> bac…

使用 FFmpeg 进行音视频转换的相关命令行参数解释

FFmpeg 是一个强大的多媒体框架&#xff0c;能够解码、编码、转码、录制、播放以及流化几乎所有类型的音频和视频。它广泛应用于音视频处理任务中&#xff0c;包括格式转换、剪辑、合并、水印添加等。本文中简鹿办公将介绍如何使用 FFmpeg 进行一些常见的音视频转换任务。 安装…

力扣:94--中序遍历二叉树

树 – 二叉树 完全二叉树&#xff1a; 完全二叉树可以用数组完美匹配位置&#xff08;先序存储&#xff1a;根左右&#xff09;&#xff0c; 推论一 &#xff1a; 位置为k的节点&#xff0c;左孩子&#xff1a;2*k 1 &#xff0c;右孩子 &#xff1a; 2 * &#xff08;k 1&…

CSS——选择器、PxCook软件、盒子模型

选择器 结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&quo…

SpringMVC学习记录(三)之响应数据

SpringMVC学习记录&#xff08;三&#xff09;之响应数据 一、页面跳转控制1、快速返回模板视图2、转发和重定向 二、返回JSON数据1、前置准备2、ResponseBody 三、返回静态资源1、静态资源概念2、访问静态资源 /*** TODO: 一个controller的方法是控制层的一个处理器,我们称为h…

推荐一款ETCD桌面客户端——Etcd Workbench

Etcd Workbench 我相信很多人在开始管理ETCD的时候都去搜了Etcd客户端工具&#xff0c;然后找到了官方的Etcd Manager&#xff0c;但用完之后发现它并不好用&#xff0c;还不支持多连接和代码格式化&#xff0c;并且已经好几年不更新了&#xff0c;于是市面上就有了好多其他客…

FET113i-S核心板已支持RISC-V,打造国产化降本的更优解 -飞凌嵌入式

FET113i-S核心板是飞凌嵌入式基于全志T113-i处理器设计的国产工业级核心板&#xff0c;凭借卓越的稳定性和超高性价比&#xff0c;FET113i-S核心板得到了客户朋友们的广泛关注。作为一款拥有A7核RISC-V核DSP核的多核异构架构芯片&#xff0c;全志科技于近期释放了T113-i的RISC-…

实践出真知:MVEL表达式中for循环的坑

目录标题 背景MVEL脚本(有问题的)MVEL脚本(正确的)结论分析 背景 需要从一个URL的拼接参数中解析出id的值并输出 比如&#xff1a; 存在URLhttps://xxxxxxxxxx?id999999&type123&name345 然后需要输出id999999 MVEL脚本(有问题的) 入参&#xff1a;parseThisUrlhttp…

【数据集】【YOLO】【目标检测】道路裂缝数据集 5466 张,YOLO/VOC格式标注!

数据集介绍 【数据集】道路裂缝数据集 5466 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。数据集中包含一种分类&#xff0c;检测范围城市道路裂缝、高速道路裂缝、乡村道路裂缝。 戳我头像获取数据&#xff0c;或者主页私聊博主哈~ 一、数据概述 道路裂缝检测…

SCRM开发新趋势打造高效客户关系管理系统

内容概要 在当今数字化的浪潮中&#xff0c;客户关系管理&#xff08;SCRM&#xff09;系统的开发正迎来了突破性的新趋势。传统的客户管理方式已经无法满足现代企业对灵活性与高效性的需求&#xff0c;我们必须顺应时代的发展&#xff0c;采用更为智能化的解决方案。SCRM开发…