【分布式事务】初步探索分布式事务的概率和理论,初识分布式事的解决方案 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、sofatype = "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、etcd3type = "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: nacosnacos: # tcserver-addr: 127.0.0.1:8848namespace: ""group: DEFAULT_GROUPapplication: 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 成功为微服务注册了资源管理器和事务管理器了。

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

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

相关文章

2023中国视频云市场报告:腾讯云音视频解决方案份额连续六次蝉联榜首,加速全球化布局

近日&#xff0c;国际数据公司&#xff08;IDC&#xff09;发布了《中国视频云市场跟踪&#xff08;2023上半年&#xff09;》报告&#xff0c;腾讯云音视频的解决方案份额连续六次蝉联榜首&#xff0c;并在视频生产创作与媒资管理市场份额中排名第一。同时&#xff0c;在实时音…

深入理解 Django 模板系统

概要 在任何 Web 开发过程中&#xff0c;渲染和展示数据是不可或缺的一部分。Django 作为一个高效的 Python Web 框架&#xff0c;提供了一个强大且灵活的模板系统。本文将详细介绍 Django 模板系统的核心概念、语法和高级功能。 一、Django 模板系统简介 Django 的模板系统允…

Android修行手册 - 模板匹配函数matchTemplate详解,从N张图片中找到是否包含五星

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

Qt OpenGL相机系统

文章目录 一、简介二、实现代码三、实现效果参考资料效果展示 一、简介 一直偷懒没有学习OpenGL,乘着这段有点时间重新学习一下OpenGL,做一个简单的小工具,有助于后面理解OSG。我们都知道OpenGL中存在着下面几个坐标空间:模型空间(物体空间)、世界空间、观察空间(或者称…

五、计算机网络

&#xff08;一&#xff09;OSI/RM 七层模型 七层模型是计算机网络的基石&#xff0c;整个计算机网络是构建与七层模型之上的。 在数据链路层&#xff0c;数据开始以帧为单位&#xff0c;网卡的 MAC 地址就是数据帧的地址&#xff0c;数据的传输开始有地址了。 局域网是工作…

JavaWeb Day05 前后端请求响应与分层解耦

目录 一、请求与响应 &#xff08;一&#xff09;请求的参数接收 ①数组参数 ②集合参数 ③日期参数 ④json参数 ⑤路径参数 总结 &#xff08;二&#xff09;响应 ①简单文本text ②数组 ③列表 ④同一响应数据格式 ⑤总结 二、三层架构与分层解耦 &#xff0…

昇腾CANN 7.0 黑科技:大模型推理部署技术解密

CANN作为最接近昇腾AI系列硬件产品的一层&#xff0c;通过软硬件联合设计&#xff0c;打造出适合昇腾AI处理器的软件架构&#xff0c;充分使能和释放昇腾硬件的澎湃算力。针对大模型推理场景&#xff0c;CANN最新发布的CANN 7.0版本有机整合各内部组件&#xff0c;支持大模型的…

Vue路由介绍及使用

一、单页应用程序介绍 1.概念 单页应用程序&#xff1a;SPA【Single Page Application】是指所有的功能都在一个html页面上实现&#xff0c;当切换不同的功能时&#xff0c;页面不会进行刷新&#xff0c;类似Ajax请求&#xff0c;但请求地址会发生部分变化。 2.具体示例 单…

深度学习环境搭建入门环境搭建(pytorch版本)

从Python安装到深度学习环境搭建 1. Anaconda安装 python可以通过官网下载exe&#xff0c;这里提供的是使用anaconda创建多个虚拟 的python环境&#xff0c;使用Anaconda Prompt管理虚拟环境更方便。 官网地址&#xff1a;Free Download|Anaconda 下载到本地后双击此文…

WPF中数据绑定验证深入讲解

WPF中数据绑定验证深入讲解 WPF在用户输入时&#xff0c;提供了验证功能&#xff0c;通常验证使用以下两种方式来实现&#xff1a; 在数据对象中引发错误。通常是在属性设置过程中抛出异常&#xff0c;或者在数据类中实现INotifyDataErrorInfo或IDataErrorInfo接口。在绑定级…

技术分享 | 测试平台开发-前端开发之数据展示与分析

测试平台的数据展示与分析&#xff0c;我们主要使用开源工具ECharts来进行数据的展示与分析。 ECharts简介与安装 ECharts是一款基于JavaScript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表&#xff…

Appium —— 初识移动APP自动化测试框架Appium

说到移动APP自动化测试&#xff0c;代表性的测试框架非Appium莫属&#xff0c;从今天开始我们将从APP结构解析、Appium框架学习、安卓/iOS自动化测试实战、自动遍历回归测试、自动化测试平台及持续集成&#xff0c;多个维度一起由浅入深的学废Appium 今天我们先来初步认识Appi…

C++中将数据添加到文件的末尾

参考:https://blog.csdn.net/qq_23880193/article/details/44279283 C中文件的读取需要包含fstream文件&#xff0c;即&#xff1a;#include 文件的读取和写入是是通过流操作来的&#xff0c;这不像输入、输出流那样&#xff0c;库中已经定义了对象cin和cout 文件的读取需要声…

加速度jsudo:小企业会遇到哪些瓶颈期?

什么是瓶颈期&#xff1f;瓶颈期&#xff0c;就是你无论怎么努力&#xff0c;成绩都是上不去&#xff0c;还是停留在原地&#xff1b;而自己表现的还是很匆忙&#xff0c;却不知道如何下手&#xff1f;就像水桶效益一样&#xff0c;水桶的木板高度层次不齐&#xff0c;像极了自…

Spark Core

Spark Core 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 第一章 RDD详解 1.1 为什么需要RDD 分布式计算需要 分区控制shuffle控制数据存储、序列化、发送数据计算API等一系列功能 这些功能&#xff0c;不能简单的通过Python内置的本地集合对象&#xff08;如…

在外包干了3年,彻底废了...

前言 先简单说下&#xff0c;我18年的大专生&#xff0c;通过校招去了一家软件公司&#xff0c;在里面干了快3年的功能测试&#xff0c;后面我感觉自己不能够在这样下去了&#xff0c;长时间重复性工作且呆在一个舒适的环境会毁掉一个人&#xff0c;而我已经在一个企业干了3年…

技术分享 | Appium 用例录制

下载及安装 下载地址&#xff1a; github.com/appium/appi… 下载对应系统的 Appium 版本&#xff0c;安装完成之后&#xff0c;点击 “Start Server”&#xff0c;就启动了 Appium Server。 在启动成功页面点击右上角的放大镜&#xff0c;进入到创建 Session 页面。配置好…

PostCSS通过px2rem插件和lib-flexible将px单位转换为rem(root em)单位实现大屏适配

目录 文档postcss中使用postcss-plugin-px2rem安装postcss-plugin-px2rem示例默认配置 webpack中使用postcss-plugin-px2rem项目结构安装依赖文件内容 大屏适配参考文章 文档 类似的插件 postcss-plugin-px2rem https://www.npmjs.com/package/postcss-plugin-px2remhttps://g…

嵌入式系统设计与应用---ARM指令集(学习笔记)

目录 本文图片截取自书本和老师的ppt 概述 指令格式 指令的条件码 ARM的寻址方式 立即寻址 寄存器寻址 寄存器间接寻址 寄存器移位寻址 变址寻址 多寄存器寻址 相对寻址 堆栈寻址 块复制寻址 ARM指令集简介 跳转指令 1.B指令 2.BL指令 数据处理指令 1.数据传…

南昌大学漏洞报送证书

获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;https://src.sjtu.edu.cn/ 兑换价格&#xff1a;20金币 获取条件&#xff1a;南昌大学任意中危或以上级别漏洞