08-微服务Seata分布式事务使用

一、分布式事务简介

1.1 概念

事务ACID:

  • A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失 败的情况。

  • C(Consistency):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100元, 转账前和转账后的数据是正确状态这叫一致性,如果出现张三转出100元,李四账户没有增加100元这就出现了数 据错误,就没有达到一致性。

  • I(Isolation):隔离性,数据库中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事 务不能看到其他事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题。

  • D(Durability):持久性,事务完成之后,该事务对数据的更改会被持久化到数据库,且不会被回滚。

1.2 事务详解

  • 本地事务:同一数据库和服务器,称为本地事务 在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的,因此叫数据库事务,由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。

  • 分布式事务: 分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

  • 举例: 分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操 作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。
    image.png

通过以上的图中我们可以看出,其实只要涉及到操作多个数据源,就可能会产生事务问题,当然在实际开发中我们要尽量避免这种问题的出现,当然如果避免不了,我们就需要进行解决,在我们的微服务系统架构中,目前比较好,比较常用的解决方案就是Seata。

二、分布式理论

随着互联化的蔓延,各种项目都逐渐向分布式服务做转换。如今微服务已经普遍存在,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生。 分布式事务被称为世界性的难题,目前分布式事务存在两大理论依据:CAP定律 BASE理论。

2.1 CAP定律

这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

  • 一致性(C)
    在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
  • 可用性(A)
    在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
  • 分区容错性(P)
    以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择

CAP是无法同时存在的,以下通过这个例子来说明
image.png

2.2 BASE理论

BASE是Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性

  • 基本可用

    基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性—-注意,这绝不等价于系统不可用。比如:

    (1)响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了1~2秒

    (2)系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面

  • 软状态

    软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时

  • 最终一致性

    最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。

2.2.1 基本可用

基本可用:**保证核心服务是可以使用的,至于其他的服务可以适当的降低响应时间,甚至是服务降级
image.png

2.2.2 软状态

软状态:存在中间状态,不影响整体系统使用,数据同步存在延时
image.png

2.2.3 最终一致性

最终一致性:再过了流量高峰期以后,经过一段时间的同步,保持各服务数据的一致
image.png

三、分布式事务解决方案

3.1 什么是2PC

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,P是指准备阶段,C是指提交阶段。

  1. 准备阶段(Prepare phase)

  2. 提交阶段(commit phase)

举例:比如说相亲对象两个人去吃饭,店老板要求,先付钱在吃饭,这是男女双方提出了AA,也就是说只有男女双方都付钱,才能落座吃饭,但是只要两个人中有一个不统一付款就不能落座吃饭。

  • 准备阶段:老板要求男方付款,男方付款。老板要求女方付款,女方付款

  • 提交阶段:老板出餐,两人纷纷落座

其实此例子就形成了一个事务,如果男女双方有一个人拒绝付款,那么老板就不会出餐,并且会把已收取的钱原路退回。

真个事务过程是由事务管理器和参与者组成的,店老板就是事务管管理器,男女双发就是参与者,事务管理器决策整个分布式事务在计算机中关系数据库支持的两阶段提交协议:

  • 准备阶段(Prepare phase):事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事务,并写本地的Undo/Redo日志,此时事务没有提交。

  • (Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数据文件)

  • 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的资源。

image.png

image.png

四、Seata初始

官网:https://seata.io/zh-cn/docs/overview/what-is-seata.html

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

在我们的微服务系统中,对应业务被对应的拆分成独立模块,在官方提供的架构图中,我们可以看出当前是三个服务:

  • 仓储服务:对给定的商品进行增删操作记录数量

  • 订单服务:根据采购者的需求创建订单

  • 账户服务:从用户账户中扣除余额、积分等

在这套架构中,用户下单购买商品的业务,就需要三个服务来完成,每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题就没办法保证,Seata就是来进行解决这种问题的解决方案。

4.2 Seata核心概念

官网地址:https://seata.io/zh-cn/docs/overview/terminology.html

要了解Seata,首先我们要了解一下Seata的几个关键的概念:

  • TC (Transaction Coordinator) - 事务协调者

    维护全局和分支事务的状态,驱动全局事务提交或回滚。

  • TM (Transaction Manager) - 事务管理器(发起者,同时也是RM的一种)

    定义全局事务的范围:开始全局事务、提交或回滚全局事务。

  • RM (Resource Manager) - 资源管理器(每个参与事务的微服务)

    管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

image-20220111191919517.png

五、Seata下载配置

官方下载地址:https://github.com/seata/seata/releases

下载之后解压
我下载的版本为1.8.0

5.1 Seata-Server配置文件

修改seata-server-1.8.0\seata\conf下面的application.yml文件

主要配置如下,seata下面的config、registry、store

注册中心、配置中心、模式

#  Copyright 1999-2019 Seata.io Group.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${log.home:${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: seatapassword: seata
seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:serverAddr: 127.0.0.1:8848namespace: group: SEATA_GROUPusername: nacospassword: nacosdataId: seataServer.propertiesregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: cluster: defaultusername: nacospassword: nacosstore:# support: file 、 db 、 redismode: dbsession:mode: dblock:mode: dbdb:datasource: duriddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://rm-8vb0l231l029347gjco.mysql.zhangbei.rds.aliyuncs.com:3306/pro-2022?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=trueuser: rootpassword: wsrbbmin-conn: 10max-conn: 100global-table: global-tablebranch-table: branch-tablelock-table: lock-tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login

5.2 Seata-server db创建

在seata-server-1.8.0\seata\script\server\db 下找到数据库SQL脚本,根据自己数据库类型选择对应的脚本执行即可

数据库名称随意,只要能找到就行。执行完成后如下
image.png

5.3 Nacos添加配置文件config.txt

#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h#Log rule configuration, for client and server
log.exceptionRate=100#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
#Used for password encryption
store.publicKey=#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
store.db.user=root
store.db.password=wsrbb
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.sentinel.sentinelPassword=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

配置文件的注意事项:

service.vgroupMapping.my_tx_group=default

数据库修改上面配置的位置
image.png

有可能提示脚本有误。只需要吧一些空值给删除即可

5.4 启动Seata

启动Seata脚本。我这里是window版本,所以直接执行seata-server.bat
注意: 确保Nacos服务启动成功,Seata也是一个服务,需要注册到Nacos中
image.png

六、AT模式

AT模式是一种无侵入的分布式事务解决方案,在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

6.1 整体概览

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。

一阶段

在一阶段中,Seata会拦截“业务SQL“,首先解析SQL语义,找到要更新的业务数据,在数据被更新前,保存下来"undo",然后执行”业务SQL“更新数据,更新之后再次保存数据”redo“,最后生成行锁,这些操作都在本地数据库事务内完成,这样保证了一阶段的原子性。

二阶段

相对一阶段,二阶段比较简单,负责整体的回滚和提交,如果之前的一阶段中有本地事务没有通过,那么就执行全局回滚,否在执行全局提交,回滚用到的就是一阶段记录的"undo Log",通过回滚记录生成反向更新SQL并执行,以完成分支的回滚。当然事务完成后会释放所有资源和删除所有日志。

image.png

6.2 案例讲解

  • 创建两个服务order,stock
  • order服务通过openfegin远程调用stock,执行业务逻辑操作

6.2.1 创建两个数据库order、stock

执行undo_logo日志回滚表

CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

image.png

6.2.2 对应服务增加依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  <version>8.0.25</version>  
</dependency>  
<dependency>  <groupId>com.alibaba</groupId>  <artifactId>druid-spring-boot-starter</artifactId>  <version>1.1.10</version>  
</dependency>  
<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-jdbc</artifactId>  
</dependency>

6.2.3 配置yml文件

注意:两个服务的配置文件保持一致

server:  port: 8801  
spring:  application:  name: seata-order  cloud:  nacos:  discovery:  server-addr: localhost:8848  alibaba:  seata:  tx-service-group: mygroup   # 事务组, 随便写  datasource:  driver-class-name: com.mysql.cj.jdbc.Driver  url: jdbc:mysql://localhost:3306/order?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true  username: root  password: wsrbb  type: com.alibaba.druid.pool.DruidDataSource  
management:  endpoint:  web:  exposure:  include: '*'  
seata:  tx-service-group: mygroup # 事务组名称,要和服务端对应  service:  vgroup-mapping:  mygroup: default # key是事务组名称 value要和服务端的机房名称保持一致

6.2.4 关键代码

加上全部事务@GlobalTransactional

@Resource  
private JdbcTemplate jdbcTemplate;  
@Autowired  
private StockApi stockApi;  @GlobalTransactional  
public void create(){  stockApi.decrement();  int i = 1/0;  jdbcTemplate.update("insert into order_at (product_id, count) values (1, 10)");  System.out.println("生成订单");  
}

6.2.5 启动order、stock服务

浏览器访问http://localhost:8801/order/order/create,此时服务肯定会抛出异常,数据应该回滚。

我们通过debug模式可以看到减库存stock服务在数据库中已经减掉了。此时发生异常后数据回滚
image.png

image.png

undo_log表快照记录
image.png

如果对你有帮助,可以关注博主(不定期更新各种技术文档) 给博主一个免费的点赞以示鼓励,谢谢 ! 欢迎各位🔎点赞👍评论收藏⭐️

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

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

相关文章

npm install运行报错npm ERR! gyp ERR! not ok问题解决

执行npm install的时候报错&#xff1a; npm ERR! path D:..\node_modules\\**node-sass** npm ERR! command failed ...npm ERR! gyp ERR! node -v v20.11.0 npm ERR! gyp ERR! node-gyp -v v3.8.0 npm ERR! gyp ERR! not ok根据报错信息&#xff0c;看出时node-sass运行出现…

写点东西《检查和更新NPM包》

写点东西《检查和更新NPM包》 检查和更新 NPM 包 TL;DR&#xff1b; 用于检查和更新软件包的 NPM 命令# [](#npm-outdated)npm outdatednpm updatenpm update --save-dev --savenpm update -g npm-check-updates 检查和更新软件包的命令npm install -g npm-check-updatesnpx np…

Idea Community社区版如何添加Run Dashboard

最近在学习spring cloud&#xff0c;跟着视频添加run dashboard&#xff0c;发现里面介绍的方法无法适用于idea community(社区版)。 然后自己研究了一下&#xff0c;成功添加&#xff0c;下面分享自己的方法。 如图&#xff0c;我的项目里添加了两个module&#xff0c;我想通…

kubeadm部署k8s1.27.2版本高可用集群(外部etcd集群带TLS认证)

文章目录 环境软件版本服务器系统初始化etcd 证书生成etcd集群部署负载均衡器部署部署k8s集群部署网络组件FAQ 环境 控制平面节点主机的配置最少是2C2G,否则kubeadm init的时候会报错 主机名IP组件系统os128192.168.177.128etcd、kube-apiserver、kube-controller-manager、k…

Cesium for Unity包无法加载

太上老君急急如律⚡令⚡ &#x1f959;关闭UnityHub&#x1f9c0;启动梯子&#x1f96a;cmd 启动UnityHub &#x1f959;关闭UnityHub &#x1f9c0;启动梯子 &#x1f96a;cmd 启动UnityHub 把批处理启动文件&#x1f448;中的exe的路径换成自己的安装目录&#xff01;保存…

前端项目对接protobufjs的时候,踩坑总结

Protobuf&#xff08;Protocol Buffers&#xff09;是一种用于序列化结构化数据的语言无关、平台无关、可扩展的机制。在JS/TS项目中&#xff0c;使用WebSocket与Protobuf可以实现高效的通信和数据传输。protobufjs官方仓库:https://github.com/protobufjs/protobuf.js 安装pro…

SpringBoot-多数据源切换和事物处理(免费)

作者原始文章: SpringBoot-多数据源切换和事物处理 最新内容和改动请看上面的文章 安装 <dependency><groupId>com.gitee.huanminabc</groupId><artifactId>dynamic-datasource</artifactId><version>1.0.3-RELEASE</version> <…

算法训练day21Leetcode530二叉搜索树的最小绝对差501二叉搜索中的众数236二叉树最近公共祖先

530 二叉搜索树的最小绝对差 题目描述 https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/ 我的想法 中序遍历二叉树存入数组&#xff0c;再遍历数组求节点之间的最小差值 我的acm模式代码 #include <iostream> #include <vector&g…

几款提高开发效率的Idea 插件

1、ignore 开发代码过程中经常会有一些需要提交到代码仓库的文件&#xff0c;比如java文件生成的.class、.jar 等&#xff0c;如果将编译后的文件都提交到代码库那么代码库会很大&#xff0c;关键是没有必要。 这款插件就可以很方便的解决某类文件或者某个文件夹不需要提交到…

密闭空间可燃气体监测终端:守护燃气管网安全

在这个瞬息万变的时代&#xff0c;燃气安全问题始终是我们关注的焦点。地下燃气管线因老化或腐蚀等造成燃气泄漏&#xff0c;并扩散至地下管沟、窨井等相邻空间&#xff0c;引发爆炸的风险&#xff0c;尤其在密闭空间中潜在的危险常常不易察觉&#xff0c;但一旦发生事故&#…

OpenCV书签 #余弦相似度的原理与相似图片/相似文件搜索实验

1. 介绍 余弦相似度&#xff08;Cosine Similarity&#xff09;&#xff0c;又称为余弦相似性&#xff0c;是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度仅仅与向量的指向方向相关&#xff0c;与向量的长度无关&#xff0c;它将向量根据坐标值绘制到向量空间…

1130 - Host 182.244.45,94‘ is not allowed to connect to this MySQL server

1130 - Host 182.244.45,94’ is not allowed to connect to this MySQL server MySQL错误代码 1130 表明连接 MySQL 服务器的主机被拒绝。在这个错误消息中&#xff0c;你提到的是主机 “182.244.45.94”&#xff0c;但可能有一个小错误&#xff0c;IP 地址中的逗号应该是点&…

5、直方图和密度图(数据分布)

创建直方图和密度图 在本教程中,您将了解有关直方图和密度图的所有知识。 文章目录 1、设置笔记本2、直方图3、密度图4、2D KDE 图4、颜色编码的图1、设置笔记本 我们首先设置编程环境。(此代码是隐藏的,但你可以通过点击此文本右侧的 “Code” 按钮来显示它。) In [1]: i…

【STM32】STM32学习笔记-W25Q64简介(37)

00. 目录 文章目录 00. 目录01. SPI简介02. W25Q64简介03. 硬件电路04. W25Q64框图05. Flash操作注意事项06. 预留07. 附录 01. SPI简介 在大容量产品和互联型产品上&#xff0c;SPI接口可以配置为支持SPI协议或者支持I 2 S音频协议。SPI接口默认工作在SPI方式&#xff0c;可以…

(2)(2.4) CRSF/ELRS Telemetry

文章目录 前言 1 ArduPilot 参数编辑器 前言 &#xff01;Note ELRS&#xff08;ExpressLRS&#xff09;遥控系统使用穿越火线协议&#xff0c;连接方式类似。不过&#xff0c;它不像穿越火线那样提供双向遥测。 TBS CRSF 接收机与 ArduPilot 的接口中包含遥测和遥控信息。…

【 CSS 】HTML5、CSS3 提高

人生犹如航海&#xff0c;不在于船在港口的安全&#xff0c;而在于船能否顺利航行&#xff0c;穿越重重风浪&#xff0c;抵达梦想的彼岸。 1. HTML5新特性 1.1 概述 HTML5 的新增特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等。 这些…

Webpack5 基本使用 - 2

常用 loader loader 是辅助打包工具。webpack 默认只能打包 js 文件&#xff0c;打包其它模块就需要配置 loader 来告诉 webpack 该怎么去打包其它文件。loader 可以将文件从不同的语言转换为 JavaScript。一类文件如果需要多个 loader 处理&#xff0c;loader 的执行顺序是从…

变压器消谐电阻器测试仪

产品概述 KDZD3000X消谐电阻器参数测试仪能实现自动检测消谐器在电流峰值为0.3mA、0.5mA 、1mA 、3mA 、5mA、10mA时相对应的电压峰值或有效值&#xff0c;并能自动绘制出消谐器伏安特性曲线图。 仪器依据的标准 Q/GDW415-2010《电磁式电压互感器用非线性电阻性消谐器技术规…

畅聊未来:低代码打造在线聊天系统

前言 现代社交网络的普及使得在线聊天成为人们日常生活中不可或缺的一部分。然而&#xff0c;传统的开发方式往往复杂且耗时&#xff0c;因此寻找一种更快捷、灵活且可视化的方法来构建在线聊天系统变得尤为重要。本文将介绍如何利用低代码平台来快速搭建一个功能齐全的在线聊…

存内计算引领新一代技术革新,开启算力新时代

文章目录 存内计算与传统计算的区别 存内计算与传统计算的区别 存内计算芯片的优势 存内计算在各个领域的应用 存内计算技术对未来发展的影响 CSDN存内计算开发者社区&#xff1a;引领新一代技术革新的最前沿 社区内容专业度 社区具备的资源 社区的开放性 社区招募令…