springCloud组件专题(五) --- seata

news2025/5/23 11:03:31

一.Seata介绍

        1. seata是什么

是一款开源的分布式事务解决方案,供了 AT、TCC、SAGA 和 XA 事务模式。

        2.分布式事务中的概念

                2.1. 二阶段提交

二阶段提交的含义就是将事务的提交分成两个步骤,分别为:

                准备阶段:事务协调者询问所有参与者是否准备好提交或者回滚事务,并等待它们的响应。(注意,等待响应一般会设置时间,利用超时进行事务回退是常见的一种方式)

                提交阶段:如果所有参与者都准备好提交,事务协调者通知它们提交事务;如果有任何一个参与者未能准备好或者出现错误,事务协调者通知它们回滚事务.

                二阶段提交中,从第一阶段的准备阶段,业务所涉及的数据就被锁定,并且锁定跨越整个提交流程。在高并发和涉及业务模块较多的情况下 对数据库的性能影响较大,但是它提供了解决分布式系统下数据一致性问题的思路

                2.2.三阶段提交

                三阶段提交是对两阶段提交的改进,通过在第一阶段引入额外的准备阶段来解决某些情况下的阻塞问题。在三阶段提交中,除了准备和提交阶段外,还有一个称为“预提交”或“预准备”阶段,用于减少参与者在第二阶段的等待时间

                2.3.TC,TM,RM

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

维护全局和分支事务的状态,驱动全局事务提交或回滚。对于我们使用seata来说,TC就是我们部署的seata服务端、

                TM (Transaction Manager) - 事务管理器​

定义全局事务的范围:开始全局事务、提交或回滚全局事务。seata的AT,XA模式中,TM可以片面的理解成加了@GlobalTransactional的方法的代理类(这个例子为了方便大家理解,并不完全准确)。

                RM (Resource Manager) - 资源管理器​

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。seata的AT,XA模式中,RM可以理解成datasource(这个例子为了方便大家理解,并不完全准确)。

        3.XA,AT,TCC,SAGA概念

                3.1. XA

                Seata XA 模式是利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种事务模式,简单来说,就是seata作为一个协调者,借助数据库本身的能力进行分布式事务管理。

具体工作机制参见官网:

Seata XA 模式 | Apache Seata

                3.2. AT

                AT 模式是 Seata 的一种非侵入式的分布式事务解决方案,代码层面来讲,只需要一个注解就可以实现分布式事务管理,使用AT模式时候,我们操作数据库实际上用的是 Seata 自带的数据源代理 DataSourceProxy,Seata 在这层代理中加入了很多逻辑,比如插入回滚 undo_log 日志,检查全局锁等。简单来讲,AT将事务分成两阶段:

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源

二阶段:无异常,提交异步化,非常快速地完成。有异常,滚通过一阶段的回滚日志进行补偿。

具体的读写隔离的原理参考官网:

https://seata.apache.org/zh-cn/docs/dev/mode/at-mode

                3.3. TCC

                TCC 模式是 Seata 支持的一种由业务方细粒度控制的侵入式分布式事务解决方案,其分布式事务模型直接作用于服务层,不依赖底层数据库。

                从代码角度讲就是,TCC需要我们不仅要自己写业务代码,还要写失败的补偿代码,成功的提交代码。这样带来的好处就是,不仅能支持关系型数据库,还能支持redis,三方调用等任何方式的数据层修改。

具体执行模型见官网:

Seata TCC 模式 | Apache Seata

                3.4.SAGA

                SAGA官方说法是支持长事务的一种模式,其实简单来理解,它是流程+TCC的结合。在使用上,我们需要先定义状态机,然后对每个步骤进行编码。

其原理详见官网:

Seata Saga 模式 | Apache Seata

二.Seata-Server 搭建

2.1. Seata-Server下载

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

下载完成之后需要解压

2.2. Seata-Server配置

2.2.1. 需要打开conf目录
2.2.2. 配置registry.conf文件

这个文件用来管理seata服务的注册,我们修改Seata的注册中心和配置中心为Nacos

** 配置文件里一堆东西都不用管,type指定了nacos,只修改nacos的就行 ** 

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"
  
  # type  指定了nacos,这里我们只需要管nacos的配置就行  后面的config也是
  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
    aclToken = ""
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  # type  指定了nacos,这里我们只需要管nacos的配置就行
  # 注意,这里指定了一个配置文件,叫做 seataServer.properties
  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
    dataId = "seataServer.properties"
  }
  consul {
    serverAddr = "127.0.0.1:8500"
    aclToken = ""
  }
  apollo {
    appId = "seata-server"
    ## apolloConfigService will cover apolloMeta
    apolloMeta = "http://192.168.1.204:8801"
    apolloConfigService = "http://192.168.1.204:8080"
    namespace = "application"
    apolloAccesskeySecret = ""
    cluster = "seata"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
    nodePath = "/seata/seata.properties"
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}

2.2.3. 修改file.conf

这个文件管理Seata的存储模式。
        Server端存储模式(store.mode)支持三种:
                1. file:单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
                2. DB:高可用模式,全局事务会话信息通过DB共享,相对性能差一些
                3. redis:Seata-Server1.3及以上版本支持,性能较高,存在事务信息丢失风险,需要配合实际场景使用。


我们把Seata的默认存储模式修改为数据库"DB",同时需要配置JDBC 如下:

## transaction log store, only used in seata-server
store {
  ## store mode: file、db、redis
  mode = "db"
  ## rsa decryption public key
  publicKey = ""
  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
    url = "jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=UTF-8"
    user = "root"
    password = "root"
    minConn = 5
    maxConn = 100
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  ## redis store property
  redis {
    ## redis mode: single、sentinel
    mode = "single"
    ## single mode property
    single {
      host = "127.0.0.1"
      port = "6379"
    }
    ## sentinel mode property
    sentinel {
      masterName = ""
      ## such as "10.28.235.65:26379,10.28.235.65:26380,10.28.235.65:26381"
      sentinelHosts = ""
    }
    password = ""
    database = "0"
    minConn = 1
    maxConn = 10
    maxTotal = 100
    queryLimit = 100
  }
}

数据库中,我们需要建几个seata的表
建表语句地址:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql
- global_table :  全局事务会话表
- branch_table:  分支事务会话表
- lock_table:       锁数据表

也可以从我这里粘:

-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
    `xid`                       VARCHAR(128) NOT NULL,
    `transaction_id`            BIGINT,
    `status`                    TINYINT      NOT NULL,
    `application_id`            VARCHAR(32),
    `transaction_service_group` VARCHAR(32),
    `transaction_name`          VARCHAR(128),
    `timeout`                   INT,
    `begin_time`                BIGINT,
    `application_data`          VARCHAR(2000),
    `gmt_create`                DATETIME,
    `gmt_modified`              DATETIME,
    PRIMARY KEY (`xid`),
    KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
    `branch_id`         BIGINT       NOT NULL,
    `xid`               VARCHAR(128) NOT NULL,
    `transaction_id`    BIGINT,
    `resource_group_id` VARCHAR(32),
    `resource_id`       VARCHAR(256),
    `branch_type`       VARCHAR(8),
    `status`            TINYINT,
    `client_id`         VARCHAR(64),
    `application_data`  VARCHAR(2000),
    `gmt_create`        DATETIME(6),
    `gmt_modified`      DATETIME(6),
    PRIMARY KEY (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(128),
    `transaction_id` BIGINT,
    `branch_id`      BIGINT       NOT NULL,
    `resource_id`    VARCHAR(256),
    `table_name`     VARCHAR(32),
    `pk`             VARCHAR(36),
    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_status` (`status`),
    KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;
2.2.4.nacos配置中心替换file.conf 

本地启动可以不做这一步,seata集群,或者企业项目,一般会用nacos的配置中心而非本地file.conf文件

在1.2.2中,我们进行了nacos的配置,其中有一个config{ dataId: "xxxx" }

我们可以在配置中心的配置管理里,加一个对应的配置,来使用配置中心而非本地文件配置

内容如下:

#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


#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=file
store.session.mode=file


#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.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
store.db.user=root
store.db.password=123456
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



#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

每个属性的含义可以在seata官网查到,太多了这里就不一个个介绍了

2.3. 启动

启动步骤为,先启动nacos然后在启动Seata-Server

启动Seata-Server的方式非常简单,直接双击此文件即可:seata-server-1.4.2\bin\seata-server.bat

linux的话运行.sh

启动完成效果

然后在nacos控制台上就可以看到Seata-Server

三.微服务项目集成

3.1. 引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

3.2. 配置TC(Seata-server)地址

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    # 参考tc服务自己的registry.conf中的配置
    type: nacos
    nacos: # 用于在nacos中寻找tc
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP  # 分组名要入registry.conf中的配置一致
      application: seata-tc-server # tc服务在nacos中的服务名称
      cluster: SH                  # 对应TC的配置
  tx-service-group: seata-demo # 事务组,根据这个获取tc服务的cluster名称
  service:
    vgroup-mapping: # 事务组与TC服务cluster的映射关系
      seata-demo: SH

3.3. 模式配置

        3.3.1. 使用XA模式

        XA模式是通过数据库的支持达到事务的。使用xa模式,需要两个条件

        1,数据库本身支持XA事务

        2,java程序通过jdbc访问数据库

        需要进行的配置如下:

        step1: yml配置文件中增加配置:

seata:
  data-source-proxy-mode: XA

        step2:要使用事务的方法上加 @GlobalTransactional

@Service
public class BusinessService {
 
    @GlobalTransactional
    public void doBusiness() {
        // 执行本地事务
        // ...
        // 调用远程服务
        // ...
    }
}

        3.3.2. 使用AT模式

        AT模式的本质是Seata 的 JDBC 数据源代理通过对业务 SQL 的解析,把业务数据在更新前的数据镜像组织成回滚日志,利用 本地事务的 ACID 特性,将业务数据的更新和回滚日志的写入在同一个本地事务中提交。

        具体操作步骤如下:

        step1: yml配置文件中增加配置:

seata:
    data-source-poxy-mode: AT

        step2:每个服务的数据库增加一个表:

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`)
) 

        step3:Service层增加注解

@Service
public class BusinessService {
 
    @GlobalTransactional
    public void doBusiness() {
        // 执行本地事务
        // ...
        // 调用远程服务
        // ...
    }
}

        3.3.2. 使用TCC模式

        TCC是比较复杂的一个事务模式,它不依赖于底层数据资源的事务支持,且Try-Confirm-Cancel三者完全由开发者自行开发定义:

  • 一阶段 prepare 行为:调用 自定义 的 Try逻辑。
  • 二阶段 commit 行为:调用 自定义的 Confirm 逻辑。
  • 二阶段 rollback 行为:调用 自定义的 Cancel 逻辑

        当服务中涉及如下情况,则可考虑使用TCC模式:

  • 不支持事务的数据库与中间件(如redis)等的操作
  • AT模式暂未支持的数据库(目前AT支持Mysql、Oracle与PostgreSQL)
  • 跨公司服务(第三方服务)的调用(无法共享Seata Server)
  • 跨语言的应用调用
  • 有手动控制整个二阶段提交过程的需求

        **我实际做过的项目里,没有使用TCC的,所以这东西,了解一下就好**

        具体操作步骤如下:

        step1:由于TCC模式不赖数据库事务能力,所以不再需要进行data-source-poxy-mode的配置,yml文件中不需要改东西

        step2:编写两个服务的service,每个service都要手动编写commit,rollback,接口声明如下

服务A的service

public interface serviceOne {
    @TwoPhaseBusinessAction(name = "prepare", commitMethod = "commit", rollbackMethod = "rollback")
    public boolean prepare(BusinessActionContext actionContext, @BusinessActionContextParameter(paramName = "a") String a);

    public boolean commit(BusinessActionContext actionContext);

    public boolean rollback(BusinessActionContext actionContext);
}

服务B的service

public interface serviceTwo {
    @TwoPhaseBusinessAction(name = "prepare", commitMethod = "commit", rollbackMethod = "rollback")
    public boolean prepare(BusinessActionContext actionContext, @BusinessActionContextParameter(paramName = "a") String a);

    public boolean commit(BusinessActionContext actionContext);

    public boolean rollback(BusinessActionContext actionContext);
}

        step3:编写业务主方法

@GlobalTransactional
public String doTransactionCommit(){
    //服务A事务参与者
    serviceOne.prepare(null,"one");
    //服务B事务参与者
    serviceTwo.prepare(null,"two");
}

        3.3.2. 使用SAGA模式

        官方介绍:Saga 模式是 SEATA 提供的长事务解决方案,在 Saga 模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

        个人理解:saga其实类似TCC,开发者自己来维护事务的提交和失败补偿,但是saga引入了类似流程引擎的东西,通过定义流程来确定成功,失败该使用对应的什么方式来处理,sage可以视作一种TCC的增强(TCC+引擎模板)。

这个模式我没有在实际开发中用过,建议大家看这位大佬的:

springcloud+eureka整合阿里seata-saga模式_51CTO博客_spring cloud整合seata

稍微总结一下,就是

step1:定义状态机(就是一个json文件)

step2:增加三张库表,用于维护状态机状态

step3:类似于TCC模式,自己变成写事务的提交,回滚方法

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

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

相关文章

Django分页组件封装

目录 1. 前言 2. 代码 3. 使用 3.1 view.py 3.2 list.html 1. 前言 在日常开发中&#xff0c;我们也许会遇到一页内容太多不够展示的问题&#xff0c;过于冗余。 此时&#xff0c;我们就需要进行分页&#xff0c;分页的方式有两种&#xff1a;1. ajax异步分页 2. 普通选…

记一些零碎的只是点和一些安全工具的使用(这里建议将漏洞原理搞清楚,然后可以尝试手动和使用工具)

目录 信息收集 扫描端口 工具 nmap TxPortMap tideFinger fscan 漏洞扫描 目录扫描 利群使用 不同系统、不同框架的漏洞 OA weblogic Struts2 thinkphp漏洞 shiro 蚁剑使用 更高级的连接工具 免杀类型 主机端的免杀 流量层的免杀 安全设备 主机端安全设备…

Docker容器数据库启动,如何用别名JAR jdbc:postgresql://别名:5432/postgres

如果想了解为啥这样做得同学&#xff0c;请去看这个文章 Docker容器网络&#xff08;七&#xff09;_host.docker.internal-CSDN博客 因为docker0网络&#xff0c;需要用别名的话&#xff0c;还得在host文件加 dockerIp(172.0.0.2) 别名 怎么查&#xff0c; docker network …

每日一题 ~ LCR 015. 找到字符串中所有字母异位词

. - 力扣&#xff08;LeetCode&#xff09; 题目解析 题目要求找出字符串中所有的字母异位词。所谓字母异位词指的是两个字符串中字符出现的次数相同&#xff0c;但顺序可以不同的情况。 思路分析 固定窗口&#xff1a;使用滑动窗口技巧&#xff0c;窗口大小固定为待匹配字…

Latex基本数学公式

LaTeX数学公式入门 LaTeX作为一种广泛使用的排版系统&#xff0c;尤其在学术界和科技领域&#xff0c;以其强大的排版能力和灵活性著称。而它的公式编辑能力更是让人叹为观止&#xff0c;经常与Markdown结合使用&#xff0c;以简化文档编写和公式展示的过程。 LaTeX 公式 L…

数字的位操作——326、504、263、190、191、476、461、477、693

326. 3 的幂&#xff08;简单&#xff09; 给定一个整数&#xff0c;写一个函数来判断它是否是 3 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 整数 n 是 3 的幂次方需满足&#xff1a;存在整数 x 使得 n 3x 示例 1&#xff1a; 输入&a…

本地部署持续集成工具Jenkins并配置公网地址实现远程自动化构建

文章目录 前言1. 安装Jenkins2. 局域网访问Jenkins3. 安装 cpolar内网穿透软件4. 配置Jenkins公网访问地址5. 公网远程访问Jenkins6. 固定公网地址 前言 本文主要介绍如何在Linux CentOS 7中安装Jenkins并结合cpolar内网穿透工具实现远程访问管理本地部署的Jenkins服务. Jenk…

DDR等长,到底长度差多少叫等长?

DDR4看这一篇就够了 - 知乎 (zhihu.com) 【全网首发】DDR4 PCB设计规范&设计要点PCB资源PCB联盟网 - Powered by Discuz! (pcbbar.com) 终于看到较为权威的DDR4等长要求了: !!!! 依据这个要求&#xff0c;H616项目的等长线不合格&#xff1a;

JazzEE(2)

JazzEE&#xff08;2&#xff09; 8、异常引入try-catchcatch中如何处理异常try-catch-finally多重catch异常的分类throw和throws区别小案例 重载和重写的异常处理自定义异常 9、常用类包装类引入Integer String类String字符串内存 StringBuilder类可变和不可变常见方法StringB…

SpringBoot整合Juint,ssm框架

目录 SpringBoot整合Juint 1.导入相关的依赖 2.创建测试类&#xff0c;使用注解SpringBootTest SpringBoot整合ssm框架 1.使用脚手架创建Spring项目 2.修改pom.xml 我先修改了SpringBoot的版本&#xff0c;修改为2.3.10.RELEASE&#xff0c;因为SpringBoot版本太高会出现…

数据集——鸢尾花介绍和使用

文章目录 一、鸢尾花数据集内容二、使用中常转换DataFrame 一、鸢尾花数据集内容 from sklearn import svm, datasets # 鸢尾花数据 iris datasets.load_iris() print(iris.data) X iris.data[:, :2] # 为便于绘图仅选择2个特征 y iris.target它包含了150个样本&#xff0c…

3.8.语义分割

语义分割 ​ 语义分割将图片中的每个像素分类到对应的类别(有监督学习) 1.图像分割和实例分割 图像分割将图像划分为若干组成区域&#xff0c;这类问题的方法通常利用图像中像素之间的相关性。它在训练时不需要有关图像像素的标签信息&#xff0c;在预测时也无法保证分割出的区…

单细胞数据整合-去除批次效应harmony和CCA (学习)

目录 单细胞批次效应学习 定义 理解 常用的去批次方法-基于Seurat 1&#xff09; Seurat-integration&#xff08;CCA&#xff09; 2&#xff09; Seurat-harmony 去批次代码 ①Seurat-integration&#xff08;CCA&#xff09; ②Seurat-harmony 单细胞批次效应学习 …

【C++进阶学习】第十一弹——C++11(上)——右值引用和移动语义

前言&#xff1a; 前面我们已经将C的重点语法讲的大差不差了&#xff0c;但是在C11版本之后&#xff0c;又出来了很多新的语法&#xff0c;其中有一些作用还是非常大的&#xff0c;今天我们就先来学习其中一个很重要的点——右值引用以及它所扩展的移动定义 目录 一、左值引用和…

AI智驾时代降临,端到端奏响“三重奏”

“追上未来&#xff0c;抓住它的本质&#xff0c;把未来转变为现在”&#xff0c;俄国哲学家车尔尼雪夫斯曾这样描述未来。而走到今天的新能源汽车&#xff0c;其通向未来的本质就是做好智能化。 呐喊智能化的口号&#xff0c;从2023年延续到2024年。如今&#xff0c;智能化的…

如何清理电脑浏览器缓存和内存 macbookpro浏览器怎么清理

浏览器已经成为我们日常生活中不可或缺的工具。然而&#xff0c;随着时间的推移&#xff0c;浏览器缓存的积累可能会逐渐影响我们的上网体验&#xff0c;导致网页加载速度变慢、浏览器运行卡顿等问题。因此&#xff0c;定期清理浏览器缓存变得尤为重要。那么Mac怎么清除浏览器缓…

单元测试之打桩-stub

首先&#xff0c;了解两个单元测试和集成测试的基本概念&#xff1a; 驱动程序/驱动模块&#xff08;driver&#xff09;&#xff0c;用以模拟被测模块的上级模块。驱动模块在集成测试中接受测试数据&#xff0c;把相关的数据传送给被测模块&#xff0c;启动被测模块。 桩程序…

Kubernetes Prometheus 系列 | AlertManager实现企业微信报警

helm部署prometheusgrafana直通车&#xff08;与本文章关联&#xff09; 首先注册企业微信&#xff1a;https://work.weixin.qq.com/ 目录 一、第一种根据企业id&#xff0c;应用secret等绑定二、第二种方式-添加群聊天机器人webhook&#xff08;推荐&#xff09; 前言&#x…

滑动窗口专题

前言&#xff1a; ①单调队列模板&#xff08;左边是队头hh&#xff0c;右边是队尾tt&#xff09; 首先维护两个指针hh和tt的位置 常见模型&#xff1a;找出滑动窗口中的最大值/最小值 int hh 0, tt -1; for (int i 0; i < n; i ) {while (hh < tt && check_…

区间DP---多边形 与金字塔

多边形&#xff1a;https://www.acwing.com/problem/content/285/ 其实就是环形的石子合并&#xff0c;只不过由于乘法的存在还要记录一下最大值与最小值。 AC代码&#xff1a; #include <bits/stdc.h> using namespace std; int a[105]; char b[105]; int dpmax[105]…