【分布式事务】初步探索分布式事务的概率和理论,初识分布式事的解决方案 Seata,TC 服务的部署以及微服务集成 Seata

文章目录

  • 一、分布式服务案例
    • 1.1 分布式服务 demo
    • 1.2 演示分布式事务问题
  • 二、分布式事务的概念和理论
    • 2.1 什么是分布式事务
    • 2.2 CAP 定理
    • 2.3 BASE 理论
    • 2.4 分布式事务模型
  • 三、分布式事务解决方案 —— Seata
    • 3.1 什么是 Seata
    • 3.2 Seata 的架构
    • 3.3 Seata 的四种分布式事务解决方案
  • 四、Seata 服务的部署和集成
    • 4.1 部署 Seata 的 TC 服务
    • 4.2 微服务集成 Seata


一、分布式服务案例

在了解分布式事务之前,让我们通过一个微服务的案例来演示一下分布式事务存在的问题。

1.1 分布式服务 demo

首先,我准备了一个微服务的 demo 项目,这个项目的结构如下:

在这个Spring Cloud 项目中一共有三个服务:account-service 账户服务,order-service 订单服务和 storage-service 库存服务。其中order-service 负责下单业务,在下单时会调用订单服务,创建订单并写入数据库。然后订单服务调用账户服务和库存服务:

  • 账户服务负责扣减用户余额;
  • 库存服务负责扣减商品库存。

这个调用的流程图如下:

目前这三个服务涉及到了三种数据库表,它们的结构如下:

  1. 首先是订单表:

  2. 然后是账户表:

  3. 最后是库存表:

这三个服务的核心业务代码如下:

  1. 首先是 order-service

    @Override
    @Transactional
    public Long create(Order order) {
        // 创建订单
        orderMapper.insert(order);
        try {
            // 扣用户余额
            accountClient.deduct(order.getUserId(), order.getMoney());
            // 扣库存
            storageClient.deduct(order.getCommodityCode(), order.getCount());
    
        } catch (FeignException e) {
            log.error("下单失败,原因:{}", e.contentUTF8(), e);
            throw new RuntimeException(e.contentUTF8(), e);
        }
        return order.getId();
    }
    
  2. 然后是account-service

    @Override
    @Transactional
    public void deduct(String userId, int money) {
        log.info("开始扣款");
        try {
            accountMapper.deduct(userId, money);
        } catch (Exception e) {
            throw new RuntimeException("扣款失败,可能是余额不足!", e);
        }
        log.info("扣款成功");
    }
    
  3. 最后是storage-service

    @Transactional
    @Override
    public void deduct(String commodityCode, int count) {
        log.info("开始扣减库存");
        try {
            storageMapper.deduct(commodityCode, count);
        } catch (Exception e) {
            throw new RuntimeException("扣减库存失败,可能是库存不足!", e);
        }
        log.info("扣减库存成功");
    }
    

可以发现,这三个核心的业务代码都加上了 @Transactional 注解来开启事务,下面就通过 Postman 来演示一下这个过程。

1.2 演示分布式事务问题

在演示之前,先看看数据库中的数据:

  1. order_tbl

  2. account_tbl

  3. storage_tbl

首先是正常状态,即余额和库存都充足的情况:

通过 Postman 发送如下请求,此时指定商品的数量为 2,库存充足:

最终成功执行,然后让我们看一看数据库中的数据变化

  1. order_tbl 中新增了一条订单数据:

  2. account_tbl表中该用户的余额成功扣减 200:

  3. storage_tbl表中该商品的库存数量也成功扣减 2 个:

然后让我们来演示一下当库存不足的情况下,是否会存在问题:

现在设置要扣减的库存为 10,而此时的库存数量为 8,则整个过程应该执行失败:


然后再让我们来看一看数据库中的数据变化:

  1. order_tbl表中没有新增订单:

  2. account_tbl表中却扣减了 200 金额:

  3. storage_tbl表中没有扣减库存:

在上面的微服务中,一个业务跨越多个服务或数据源,每个服务都是一个分支事务,要保证所有分支事务最终状态一致,这样的事务就是分布式事务。

但是,上面的微服务上没有实现分布式事务,而只有分支事务,站在分支事务的角度上来看:

  • 订单服务虽然下单成功,但是因为调用库存服务,库存服务因为库存不足调用失败回滚了,因此订单服务作为外部事务也会回滚。
  • 账户服务在执行的时候没有问题,因此执行成功了。
  • 库存服务因为库存不足,业务失败因此回滚了。

因此,要想保证整个业务的流程都能够正常执行,那么就需要采用分布式事务,即要么所有的分支事务都执行成功,要么都执行失败。

二、分布式事务的概念和理论

2.1 什么是分布式事务

分布式事务是指在分布式系统中,多个独立的事务操作需要协同工作以维护数据的一致性和完整性。在传统的单机事务中,ACID(原子性、一致性、隔离性、持久性)属性可以轻松满足,但在分布式系统中,由于涉及多个数据存储节点,实现分布式事务变得更加复杂。

关键问题包括如何协调各个参与者的事务、如何处理网络分区和节点故障、如何保证全局数据一致性等。因此,分布式事务需要特殊的技术和协议来管理和维护数据一致性,以确保分布式系统的正确运行。

2.2 CAP 定理

CAP 定理是分布式系统理论中的一个重要概念,由计算机科学家 Eric Brewer 提出。CAP 定理指出,一个分布式系统的设计不能同时满足以下三个属性:

  • 一致性(Consistency):所有节点看到的数据是一致的,即在任何时刻,系统中的所有节点都能看到相同的数据。

  • 可用性(Availability):系统在任何时刻都能处理读写请求,即系统保持可用状态,不会出现服务不可用的情况。

  • 分区容忍性(Partition Tolerance):系统能够在网络分区或节点故障的情况下继续工作,即系统能够容忍部分节点无法通信或故障。

CAP 定理指出,在分布式系统中,最多只能满足其中的两个属性,而必须牺牲其中一个。这意味着在面对网络分区或故障时,要么保证一致性和可用性,但失去了分区容忍性;要么保证一致性和分区容忍性,但失去了可用性。这对分布式系统的设计和架构提出了重要挑战。

例如:ES 集群出现分区时,故障节点会被剔除集群,数据分片会重新分配到其它节点,保证数据一致。因此是低可用性,高一致性,属于CP 模式。

2.3 BASE 理论

BASE 理论是对 CAP 定理的一种思考和解决方案,它的名称是对以下三个核心概念的缩写:

1. Basically Available(基本可用性): 这意味着分布式系统在出现故障时仍然能够保持基本的可用性。即使部分组件故障或数据出现不一致,系统仍然可以提供有限的服务,不会变得完全不可用。这允许系统在面临问题时继续对外提供核心功能,确保用户体验。

2. Soft State(软状态): BASE 理论承认在一定时间内,分布式系统的数据可以处于不一致的中间状态。这是因为各个节点在进行数据同步或处理时可能存在延迟、不同步的情况,导致数据不完全一致。允许出现软状态意味着系统可以容忍一段时间内的数据不一致,但要求最终达到一致状态。

3. Eventually Consistent(最终一致性): 最终一致性是 BASE 理论的核心概念,它强调虽然分布式系统不能保证强一致性,但最终所有节点的数据将达到一致状态。系统会采取一系列措施来保证数据最终一致,例如定期数据同步、修复数据不一致等。这种方法可以在面临一致性挑战的同时,保持分布式系统的可用性和性能。

BASE 理论的思想在分布式系统中得到了广泛应用,特别是对于大规模、高可用性的系统。它提供了一种权衡可用性和一致性的方法,允许根据具体需求和应用场景来选择适当的数据一致性模型(如最终一致性),以满足不同业务的要求。这使得分布式系统更具弹性、可伸缩性和容错性,同时在最终实现数据一致性。

因此分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴 CAP 定理和 BASE 理论:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。

  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

2.4 分布式事务模型

要解决分布式事务的问题,各个子系统之间必须能够感知彼此的事务状态,以确保状态一致性。为实现这一目标,通常需要引入一个事务协调者,它的职责是协调每个事务的参与者(子系统内的事务)。这些子系统内的事务通常被称为分支事务,而涉及多个分支事务的全局事务需要协调者来确保一致性。

以上述微服务为例,引入一个事务协调者后的架构如下:

分布式事务架构

在这种架构中,事务协调者负责协调每个分支事务的执行。当某一分支事务(例如库存服务)由于库存不足而导致业务失败时,事务协调者可以通知所有分支事务进行回滚,以确保所有事务状态的一致性。

分布式事务模型的关键点包括:

  • 事务协调者(Coordinator): 负责协调全局事务的执行和状态管理。它监控每个分支事务的执行情况,并根据需要发出提交或回滚命令。

  • 分支事务(Branch Transaction): 每个子系统内部的事务,负责执行具体的业务操作。分支事务会根据协调者的指示执行提交或回滚操作。

  • 全局事务(Global Transaction): 涉及多个子系统内的一组分支事务,全局事务由协调者协调管理,以确保所有分支事务的状态一致性。

引入事务协调者后,分布式系统可以更好地处理各个子系统之间的事务一致性问题,保证全局事务的正确执行。这种模型有助于应对网络故障、部分事务失败等情况,以确保分布式系统的数据一致性和完整性。

三、分布式事务解决方案 —— Seata

3.1 什么是 Seata

Seata(前身为Fescar)是一个分布式事务解决方案,最早由蚂蚁金服和阿里巴巴共同开源于2019年1月。Seata 的目标是提供高性能、简单易用的分布式事务服务,旨在为用户提供一站式的分布式解决方案。

Seata的主要功能和特点包括:

  • 分布式事务协调: Seata充当分布式事务的协调者,负责管理和协调多个分支事务,以确保它们的一致性和完整性。

  • 高性能: Seata通过优化事务日志存储和协调算法,提供高性能的分布式事务处理能力。

  • 简单易用: Seata提供了简单的API和配置方式,使开发人员能够轻松地集成和使用分布式事务功能。

  • 支持多种存储后端: Seata支持多种存储后端,包括MySQL、Oracle、PostgreSQL等,以满足不同环境的需求。

  • 分布式事务模式: Seata支持两阶段提交(2PC)和补偿模式,可以根据业务需求选择合适的事务模式。

  • 跨框架和跨语言: Seata可以与各种编程语言和框架集成,包括Java、Spring Cloud、Dubbo等,以及Node.js、Python等非Java语言。

Seata 的官方网站(http://seata.io/)提供了详细的文档、博客和源码分析,为用户提供了丰富的资源和支持,帮助开发人员更好地理解和使用分布式事务解决方案。Seata 的开源性质使得它成为解决分布式事务挑战的重要工具之一,广泛应用于云原生和微服务架构中。

3.2 Seata 的架构

Seata 的架构涉及三个重要的角色,它们分别是:

  • TC (Transaction Coordinator) - 事务协调者: TC 是 Seata 中的核心组件,负责维护全局事务和分支事务的状态,协调全局事务的提交或回滚。TC通过全局事务的唯一标识来管理多个分支事务,确保它们的状态一致性,并根据协调结果决定是提交还是回滚全局事务。

  • TM (Transaction Manager) - 事务管理器: TM 定义了全局事务的范围,它负责启动全局事务、提交或回滚全局事务。TM 与 TC 进行通信,以协调全局事务的状态和最终结果。TM可以是应用程序的一部分,用于启动和管理分布式事务。

  • RM (Resource Manager) - 资源管理器: RM 管理分支事务处理的资源,包括数据库、消息队列、缓存等。RM 与 TC 进行通信以注册分支事务、报告分支事务的状态,并根据 TC 的指示来驱动分支事务的提交或回滚。RM 负责协调资源的一致性,以确保全局事务的一致性。

这三个角色的架构图如下:

这三个角色共同协作,构成了 Seata 的分布式事务管理架构。TC 作为协调者负责全局事务的管理,TM 负责事务的启动和控制,RM 负责资源的管理和一致性保障。通过这种分布式事务管理架构,Seata能够有效地管理分布式事务的状态和保证一致性,为分布式系统提供可靠的事务支持。

3.3 Seata 的四种分布式事务解决方案

Seata 提供了四种不同的分布式事务解决方案,以满足不同业务场景的需求。这些解决方案分别是:

  1. XA 模式(eXtended Architecture): XA模式是一种强一致性分阶段事务模式,它允许分布式事务在多个资源管理器(例如数据库)之间进行协调。在XA模式中,事务协调者(TC)协调多个RM(Resource Manager)来确保事务的一致性。虽然XA模式提供了强一致性,但通常会牺牲一定的可用性,并且需要支持XA协议的资源管理器。XA模式不需要业务侵入。

  2. TCC 模式(Try-Confirm-Cancel): TCC模式是一种最终一致性的分阶段事务模式,它要求业务代码显式地定义“尝试”、“确认”和“取消”三个阶段的操作。TCC模式通过在每个参与者(分支事务)上执行这些操作来实现最终一致性。虽然TCC模式具有一定的业务侵入,但它提供了更灵活的事务控制和适应性。

  3. AT 模式(Automatic Transaction): AT模式是一种最终一致性的分阶段事务模式,它无需业务代码显式地定义阶段操作,而是通过自动代理来管理分支事务。AT模式是Seata的默认模式,它提供了最终一致性的分布式事务解决方案,并且无需业务侵入。AT模式适用于大多数业务场景。

  4. SAGA 模式: SAGA模式是一种长事务模式,它将分布式事务分解成多个连续的步骤,每个步骤都是一个本地事务。SAGA模式适用于需要跨多个微服务的长时间事务。虽然SAGA模式具有业务侵入,但它提供了更高级别的事务控制和业务流程管理。

这四种分布式事务解决方案使 Seata 能够适应不同的应用场景,从强一致性到最终一致性,从无业务侵入到有业务侵入,满足了多样化的分布式事务需求。根据具体的业务要求和架构设计,开发人员可以选择适当的 Seata 模式来实现分布式事务管理。

四、Seata 服务的部署和集成

4.1 部署 Seata 的 TC 服务

  1. 首先我们要下载 seata-server (TC 服务)压缩包,下载地址:http://seata.io/zh-cn/blog/download.html。这里我选择的版本是 1.4.2

  2. 将这个压缩包解压到非中文目录下,其目录结构如下:

  3. 修改conf目录下的registry.conf文件,这里我们选择将 seata-server 服务注册到 Nacos 中:

    registry {
      # 注册中心类型:file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
      type = "nacos"
    
      nacos {
        application = "seata-tc-server"
        serverAddr = "127.0.0.1:8848"
        group = "DEFAULT_GROUP"
        namespace = ""
        cluster = "CD"
        username = "nacos"
        password = "nacos"
      }
    }
    
    config {
      # file、nacos 、apollo、zk、consul、etcd3
      type = "nacos"
    
      nacos {
        serverAddr = "127.0.0.1:8848"
        namespace = ""
        group = "SEATA_GROUP"
        username = "nacos"
        password = "nacos"
        dataId = "seataServer.properties"
      }
    }
    
  4. 在 Nacos 中添加seataServer.properties配置文件。为了让 TC 服务的集群可以共享配置,所以选择了 Nacos 作为统一配置中心。因此服务端配置文件 seataServer.properties 文件需要添加到 Nacos 中。文件内容如下:

    # 数据存储方式,db代表数据库
    store.mode=db
    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&rewriteBatchedStatements=true
    store.db.user=root
    store.db.password=passwd
    store.db.minConn=5
    store.db.maxConn=30
    store.db.globalTable=global_table
    store.db.branchTable=branch_table
    store.db.queryLimit=100
    store.db.lockTable=lock_table
    store.db.maxWait=5000
    # 事务、日志等配置
    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.undo.logSaveDays=7
    server.undo.logDeletePeriod=86400000
    
    # 客户端与服务端传输方式
    transport.serialization=seata
    transport.compressor=none
    # 关闭metrics功能,提高性能
    metrics.enabled=false
    metrics.registryType=compact
    metrics.exporterList=prometheus
    metrics.exporterPrometheusPort=9898
    
  5. 创建数据库表
    TC 服务在管理分布式事务时,需要记录事务相关数据到数据库中,需要提前创建好这些表。因此新建一个名为 seata 的数据库,然后创建一张分支事务表和一张全局事务表。这些表主要记录全局事务、分支事务、全局锁信息:

    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- 分支事务表
    -- ----------------------------
    DROP TABLE IF EXISTS `branch_table`;
    CREATE TABLE `branch_table`  (
      `branch_id` bigint(20) NOT NULL,
      `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
      `transaction_id` bigint(20) NULL DEFAULT NULL,
      `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `status` tinyint(4) NULL DEFAULT NULL,
      `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `gmt_create` datetime(6) NULL DEFAULT NULL,
      `gmt_modified` datetime(6) NULL DEFAULT NULL,
      PRIMARY KEY (`branch_id`) USING BTREE,
      INDEX `idx_xid`(`xid`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- 全局事务表
    -- ----------------------------
    DROP TABLE IF EXISTS `global_table`;
    CREATE TABLE `global_table`  (
      `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
      `transaction_id` bigint(20) NULL DEFAULT NULL,
      `status` tinyint(4) NOT NULL,
      `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `timeout` int(11) NULL DEFAULT NULL,
      `begin_time` bigint(20) NULL DEFAULT NULL,
      `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `gmt_create` datetime NULL DEFAULT NULL,
      `gmt_modified` datetime NULL DEFAULT NULL,
      PRIMARY KEY (`xid`) USING BTREE,
      INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
      INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
  6. 启动 TC 服务,进入 seata-serverbin 目录,运行其中的 seata-server.bat 即可:

    启动成功后,可以发现 seata-server默认的端口号是 8091, 并且此时也应该注册到 Nacos 注册中心了。打开浏览器,访问 nacos 的控制台,然后进入服务列表页面,可以看到 seata-tc-server 的信息:

4.2 微服务集成 Seata

  1. 首先,我们需要在微服务中引入 seata 依赖:

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    </dependency>
    <dependency>
        <groupId>io.seata</groupId>
        <artifactId>seata-spring-boot-starter</artifactId>
        <version>1.4.2</version>
    </dependency>
    

    注意,引入的依赖版本要和 seata-server 版本匹配。

  2. 修改配置文件,需要修改所有微服务的application.yml文件,添加下面的配置:

    seata:
      registry: # TC 服务注册中心的配置,微服务根据这些信息去注册中心获取 tc 服务地址
        # 参考 tc 服务的 registry.conf 中的配置
        type: nacos
        nacos: # tc
          server-addr: 127.0.0.1:8848
          namespace: ""
          group: DEFAULT_GROUP
          application: seata-tc-server # tc服务在nacos中的服务名称
      tx-service-group: seata-demo # 事务组,根据这个获取 tc 服务的cluster名称
      service:
        vgroup-mapping: # 事务组与TC服务cluster的映射关系
          seata-demo: CD
    

    注意,Seata 客户端获取 TC 服务的集群名称 cluster 是通过 tx-service-groupvgroup-mapping 的映射来获取的,即以 tx-service-group 为 key ,以 vgroup-mapping 为 value:

  3. 完成了上面的所有配置之后,重启这三个微服务,就可以在 seata-server 的控制台中看到如下的日志:


通过这些日志可以发现,seata-server 成功为微服务注册了资源管理器和事务管理器了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE-博客系统3(功能设计)

本部分内容为&#xff1a;实现登录功能&#xff1b;强制要求用户登录&#xff1b;实现显示用户信息&#xff1b;退出登录&#xff1b;发布博客 该部分的后端代码如下&#xff1a; Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Ser…

信息系统项目管理师第四版:第5章 信息系统工程

请点击↑关注、收藏&#xff0c;本博客免费为你获取精彩知识分享&#xff01;有惊喜哟&#xff01;&#xff01; 信息系统工程是用系统工程的原理、方法来指导信息系统建设与管理的一门工程技术学科&#xff0c;它是信息科学、管理科学、系统科学、计算机科学与通信技术相结合…

Visual Interpretability for Deep Learning: a Survey

Visual Interpretability for Deep Learning: a Survey----《深度学习的视觉可解释性:综述》 摘要 本文回顾了最近在理解神经网络表示以及学习具有可解释性/解耦的中间层表示的神经网络方面的研究。尽管深度神经网络在各种任务中表现出了优越的性能&#xff0c;但可解释性始终…

抖音双11进入决赛圈,爆款王炸单品竟是.....

今年&#xff0c;抖音将双11战线拉长&#xff0c;给足品牌和消费者时间备战&#xff0c;第一轮抢跑期战绩亮眼&#xff0c;多项双11销售增长记录被刷新&#xff0c;引爆全域流量。最后几天&#xff0c;抖音商城全面进入终局厮杀阶段&#xff0c;爆发期下半程对比抢跑期增速放缓…

通信原理板块——图像压缩编码

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、图像压缩编码 图像压缩编码可以…

Jmeter 基本使用以及性能测试基本流程使用总结

使用场景 需要对一部分接口做性能测试&#xff0c;并检验修改后的效果下载安装 搜索 Apache JMeter - Download Apache JMeter 或直接到官网 https://jmeter.apache.org/download_jmeter.cgi?cm_mc_uid15063477198714828218851&cm_mc_sid_502000001483277541下载 选择 zi…

2023年11月数据库流行度最新排名

点击查看最新数据库流行度最新排名&#xff08;每月更新&#xff09; 2023年11月数据库流行度最新排名 TOP DB顶级数据库索引是通过分析在谷歌上搜索数据库名称的频率来创建的 一个数据库被搜索的次数越多&#xff0c;这个数据库就被认为越受欢迎。这是一个领先指标。原始数…

Linux系统环境变量

Linux系统环境变量 1. 环境变量1.1 定义环境变量1.2 使用环境变量 2. 环境变量作用2.1 PATH 3. 设置环境变量3.1 设置系统级环境变量3.2 设置用户级环境变量3.3 设置临时环境变量 1. 环境变量 在Linux系统中&#xff0c;常用的关键信息以键值对&#xff08;KeyValue&#xff09…

用C++编写动画+音频版极乐净土

#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<graphics.h> #include<Windows.h> #include<MMSystem.h>//播放音乐所需要的头文件 #pragma comment(lib,"winmm.lib")//告诉编译器&#xff0c;加载winmm.lib库文件 #define C…

[OS]11.9.2023 中断

中断向量表 CPU的设计者必须在中断信息和其处理程序的入口地址之间建立某种联系&#xff0c;使得CPU根据中断信息可以找到要执行的处理程序。 中断信息中包含有标识中断源的类型码。根据CPU的设计&#xff0c;中断类型码的作用就是用来定位中断处理程序。 比如CPU 根据中断类型…

【数据结构】 二叉树理论概念!一文了解二叉树!

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; 数据结构解析 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言&#x1f324;️树的概念☁️树的结构☁️树的小知识☁️树的表示与运用 &#x1f324…

python定时任务scheduler根据参数执行

python执行定时任务请参考&#xff1a;python使用apscheduler每隔一段时间自动化运行程序 传入参数时&#xff1a; 使用add_job函数中添加参数&#xff1a;args[参数1, 参数2]....传入参数顺序与对应位置一致 示例程序 import datetime from apscheduler.schedulers.backg…

一键批量删除文件名中的空格,高效整理您的文件

你是否曾经因为文件名中多余的空格而烦恼&#xff1f;这些空格不仅影响了文件的美观&#xff0c;还可能导致一些不必要的错误。现在&#xff0c;我们向您介绍一款全新的工具&#xff0c;它可以帮助您一键批量删除文件名中的空格&#xff0c;让您的文件整理更加轻松、高效&#…

【Java笔试强训】Day9(CM72 另类加法、HJ91 走方格的方案数)

CM72 另类加法 链接&#xff1a;另类加法 题目&#xff1a; 给定两个int A和B。编写一个函数返回AB的值&#xff0c;但不得使用或其他算数运算符。 题目分析&#xff1a; 代码实现&#xff1a; package Day9;public class Day9_1 {public int addAB(int A, int B) {// wr…

软件测评中心▏软件功能测试和非功能测试的区别和联系简析

在软件开发的过程中&#xff0c;功能测试和非功能测试是两个重要的环节。功能测试是指对软件的各项功能进行验证和确认&#xff0c;关注软件是否按照需求规格说明书进行了实现&#xff0c;是否满足了用户的功能需求。而非功能测试是指对软件的性能、可靠性、安全性等方面进行测…

异地传输大文件最快且安全稳定的办法

无论是企业还是个人&#xff0c;都会有传输大文件的需求&#xff0c;特别是在异地时&#xff0c;工作中最典型的就是项目资料、合同文档、视频素材等都是有一定的及时性的&#xff0c;那么在传输过程中&#xff0c;没有好的传输方式会间接性的影响到整体工作的进行&#xff0c;…

vue项目electron打包

1.设置国内镜像 npm config edit 命令行输入后会弹出npm的配置文档&#xff0c;需要文档末尾加入 electron_mirrorhttps://npm.taobao.org/mirrors/electron/ electron-builder-binaries_mirrorhttps://npm.taobao.org/mirrors/electron-builder-binaries/ 2.全局安装electron …

linux基础指令上篇

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 引用 01. ls 指令2. pwd命…

目标检测算法 - YOLOv1

文章目录 1. 作者简介2. 目标检测综述3. YOLOv1算法3.1 预测阶段3.2 预测阶段后处理3.3 训练阶段 YOLO的全称是you only look once&#xff0c;指只需要浏览一次就可以识别出图中的物体的类别和位置。 YOLO是目标检测模型。目标检测是计算机视觉中比较简单的任务&#xff0c;用…