Redis篇--常见问题篇7--缓存一致性2(分布式事务框架Seata)

news2024/12/24 21:42:16

1、概述

在传统的单体应用中,事务管理相对简单,通常使用数据库的本地事务(如MySQL的BEGIN和COMMIT)来保证数据的一致性。然而,在微服务架构中,由于每个服务都有自己的数据库,跨服务的事务管理变得复杂。Seata正是为了解决这一问题而设计的,它提供了一种轻量级的分布式事务解决方案,能够在多个微服务之间协调事务,确保数据的一致性。

Seata是阿里巴巴开源的一款分布式事务解决方案,旨在解决微服务架构中的分布式事务问题。它提供了ACID(原子性、一致性、隔离性、持久性)事务的分布式实现,确保在多个微服务之间进行跨服务调用时,事务能够保持一致性和可靠性。

2、Seata的4种工作模式

AT(Automatic Transaction Mode)模式:

AT模式是Seata 默认的分布式事务模式,它基于SQL解析和拦截器机制,自动处理全局事务,无需我们编码,适用于大多数关系型数据库(如MySQL、Oracle、PostgreSQL等)。在AT模式下,Seata会自动记录数据库操作的前后镜像(before image和after image),并在事务提交或回滚时进行数据的一致性检查。开发者不需要编写额外的补偿逻辑,适合大多数场景。也是Seata最常用的一种模式。

TCC(Try-Confirm-Cancel Mode)模式:

TCC模式一般用于适合对性能要求较高的场景。是一种显式的两阶段提交协议,开发者需要为每个业务操作定义三个方法:

  • try:尝试执行业务操作,预留资源。
  • confirm:确认操作,正式提交资源。
  • cancel:取消操作,回滚资源。
    TCC模式适用于复杂的业务场景,尤其是跨多个服务的分布式事务。开发者需要手动编写补偿逻辑,确保事务的一致性。

SAGA(Saga Orchestration Mode)模式:

SAGA模式是一种长事务模式,是基于状态机驱动的分布式事务。适用于涉及多个服务需要长时间运行的业务流程。SAGA模式将整个业务流程拆分为多个子事务,每个子事务都有对应的补偿操作。如果某个子事务失败,SAGA会依次执行前面子事务的补偿操作,确保事务的一致性。
SAGA 模式有两种实现方式:

  • Orchestration(编排模式):由一个中央控制器(Orchestrator)负责协调各个子事务的执行。
  • Choreography(编舞模式):各个子事务通过事件驱动的方式协同工作,没有中央控制器。

XA(X/Open XA Mode)模式:

XA模式是传统的两阶段提交协议,兼容XA规范,广泛应用于传统的关系型数据库系统。Seata支持XA模式,允许开发者使用XA协议来管理分布式事务。XA模式依赖于数据库的XA支持,因此需要数据库和JDBC驱动的支持。适合对一致性要求极高的场景,但性能较低。

3、Seata的核心特性

(1)、支持多种分布式事务模式(AT,TCC,SAGA,XA)。
(2)、轻量级:Seata不依赖于任何特定的中间件或框架,可以与Spring Cloud、Dubbo等微服务框架无缝集成。
(3)、高可用性和扩展性:Seata的事务协调器(TC)和事务管理器(TM)都可以水平扩展,支持集群部署,确保系统的高可用性和可扩展性。
(4)、多语言支持:Seata支持多种编程语言,包括Java、Go、C等,方便不同技术栈的团队使用。
(5)、丰富的生态:Seata提供了与主流数据库、消息队列、缓存等组件的集成,能够满足复杂的业务需求。

4、两阶段提交

XA协议的核心是两阶段提交(Two-Phase Commit,2PC)机制:

(1)、第一阶段(准备阶段):

全局事务协调者向所有参与者发送准备请求,每个参与者执行本地事务并返回确认信息给协调者。如果所有参与者都返回成功,那么协调器进入第二阶段。如果任何一个参与者返回失败,协调者将发送回滚请求。

(2)、第二阶段(提交/回滚阶段):

全局事务协调者根据第一阶段的反馈情况,决定提交或回滚全局事务。首先,协调者发送提交或回滚指令给所有参与者,然后参与者按照指令执行相应的操作。
在这里插入图片描述
通过两阶段提交,XA协议保证了分布式事务的原子性和一致性。每个参与者在第一阶段确认准备之后,就无法单独执行本地事务的提交或回滚操作,而是依赖于全局事务协调的指令。
简单说:
第一阶段是所有服务执行各自的事务代码并记录了执行结果。
第二阶段是事务协调者根据所有服务第一阶段的结果决定是否提交全局事务。第一阶段中每一个服务都记录了自身的undo_log日志,在第二阶段中,事务协调者如果发现有一个服务失败了,就会通知所有的服务执行undo_log日志,实现全局回滚。如果全部服务都成功了,那么就直接提交全局事务,结束本次事务处理。不论第二阶段是成功还是失败,TC(事务协调器)都会清理本次全局事务的状态,并释放资源。

5、Seata的架构及原理

(1)、架构

Seata的工作原理基于“三者分离”的架构设计,分别是:

事务协调器(Transaction Coordinator, TC):
  • 负责维护全局事务的状态,协调各个分支事务的提交或回滚。
  • 作为独立的服务部署,通常是一个集群,确保高可用性和容错能力。
事务管理器(Transaction Manager, TM):
  • 负责开启全局事务,并向TC注册全局事务。
  • 当所有分支事务完成后,TM会根据业务逻辑决定是提交还是回滚全局事务。
资源管理器(Resource Manager, RM):
  • 负责管理分支事务,通常是微服务中的数据库连接。
  • RM会将本地事务注册到TC,并在全局事务提交或回滚时执行相应的操作。

架构示例如下:
在这里插入图片描述
简单理解下:
TC就相当于我们部署的Seata服务,用于管理所有的全局事务信息。TM就相当于我们用注解标注的方法,RM内就相当于注解方法内使用的每一个微服务的任务。
当执行到标识全局事务的方法时,TM就会往TC注册全局事务的信息并开启全局事务,同时会通知TC本次全局任务有哪些RM的任务。
之后程序会运行方法中的代码,执行每一个RM任务并记录执行结果。TC会监听这些子任务的结果,如果全部RM都运行成功,全局任务就会通过。如果有一个失败,就会通知所有的RM去回滚服务。

(2)、以AT模式为例,Seata的工作流程如下

第一步:开启全局事务
  • TM向TC发起请求,开启一个新的全局事务,并获取全局事务ID(XID)。
第二步:执行分支事务
  • 在每个微服务中,RM会拦截SQL语句,解析并生成对应的undo_log,用于记录事务的回滚信息。
  • RM将本地事务注册到TC,并将XID传递给下游服务。
第三步:执行全局事务(提交或回滚)
  • 当所有分支事务执行完毕后,TM根据业务逻辑决定是提交还是回滚全局事务。
  • 如果提交,TC会通知所有RM提交本地事务;如果回滚,TC会通知所有RM使用undo_log回滚本地事务。
第四步:清理资源
  • 全局事务提交或回滚后,TC会清理相关的事务状态,释放资源。

6、Seata的优势

- 无侵入性:在AT模式下,Seata可以通过AOP(面向切面编程)自动拦截SQL语句,生成undo_log,而不需要修改业务代码。这使得开发者可以专注于业务逻辑,而不必关心事务的实现细节。
- 高性能:Seata的AT模式基于SQL解析和两阶段提交,避免了传统XA协议的性能瓶颈。它只在必要的时候生成undo_log,减少了对数据库的压力。
- 强一致性:Seata通过两阶段提交协议,确保了分布式事务的强一致性。即使某个分支事务失败,整个全局事务也会回滚,保证数据的一致性。
- 灵活的事务模式:Seata提供了多种事务模式(AT、TCC、SAGA、XA),可以根据不同的业务场景选择最适合的模式。例如,对于简单的CRUD操作,可以使用AT模式;对于复杂的业务流程,可以使用TCC或SAGA模式。

7、Seata的应用场景

- 微服务之间的数据一致性:当多个微服务需要协同完成一个业务操作时,Seata可以确保这些服务之间的数据一致性。例如,订单系统和库存系统之间的扣减库存操作。
- 跨库事务:当同一个微服务需要操作多个数据库时,Seata可以确保这些数据库之间的事务一致性。例如,一个微服务需要操作更新用户库和订单库。
- 异步事务:Seata的SAGA模式支持长事务,适用于需要长时间运行的业务流程。例如,复杂的审批流程或订单处理流程。
- 跨服务的消息队列事务:Seata可以与消息队列(如RocketMQ、Kafka)结合使用,确保消息的发送和接收在一个全局事务中。例如,订单创建成功后,发送一条消息通知库存系统扣减库存。

8、Seata使用示例

(1)、安装,配置及使用

主要包括以下几个步骤:
第一步:下载

  • 你可以从Seata官方GitHub下载最新的Seata Server。
    目录如:
    在这里插入图片描述
    第二步:配置Seata Server
    • 编辑conf/file.conf文件,配置Seata Server的存储方式(如文件存储、数据库存储等)。
    • 编辑registry.conf文件,配置Seata的注册中心(如Nacos、Eureka、Zookeeper等)。

第三步:启动服务
在bin目录下有启动脚本,解压后启动seata-server.sh或seata-server.bat。
在这里插入图片描述
第四步:配置客户端:

  • 在微服务中引入Seata的依赖项(如seata-spring-boot-starter),并在application.yml中配置Seata的相关参数,如事务模式、Seata Server地址等。

第五步:编写业务代码:

  • 在业务代码中使用@GlobalTransactional注解来开启全局事务。Seata会自动拦截SQL语句,生成undo_log,并协调各个分支事务的提交或回滚。

(2)、四种模式代码示例

AT模式(Automatic Transaction Mode)

概述:
AT模式是Seata默认的分布式事务模式,它基于SQL解析和拦截器机制,自动处理全局事务。在AT模式下,Seata会自动记录数据库操作的前后镜像(before image和after image),并在事务提交或回滚时进行数据的一致性检查。开发者不需要编写额外的补偿逻辑,适合大多数场景。

适用场景:

  • 适用于标准的SQL操作,如INSERT、UPDATE、DELETE。
  • 不需要手动编写补偿逻辑,适合对事务一致性要求较高的场景。

代码示例

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private AccountService accountService;

    // 创建订单并扣减账户余额
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public void createOrder(Long userId, Double amount) {
        try {
            // 1. 扣减账户余额
            accountService.decreaseBalance(userId, amount);

            // 2. 创建订单
            Order order = new Order();
            order.setUserId(userId);
            order.setAmount(amount);
            order.setStatus("CREATED");
            orderRepository.save(order);

            // 3. 模拟异常(用于测试回滚)
            // if (true) throw new RuntimeException("Simulated error");

            System.out.println("Order created successfully.");
        } catch (Exception e) {
            System.err.println("Error creating order: " + e.getMessage());
            throw e;  // 抛出异常以触发事务回滚
        }
    }
}

解释:

  • @GlobalTransactional:标记该方法为全局事务,确保所有参与的方法(如:扣减账户余额和创建订单)都在同一个事务中执行。
  • 自动处理:Seata会自动记录SQL操作的前后镜像,并在事务提交或回滚时进行数据的一致性检查。
  • 无需补偿逻辑:开发者不需要编写额外的补偿逻辑,Seata会自动处理事务的提交和回滚。
TCC模式(Try-Confirm-Cancel Mode)

概述
TCC模式是一种显式的两阶段提交协议,开发者需要为每个业务操作定义三个方法:

  • try:尝试执行业务操作,预留资源。
  • confirm:确认操作,正式提交资源。
  • cancel:取消操作,回滚资源。
    TCC模式适用于复杂的业务场景,尤其是跨多个服务的分布式事务。开发者需要手动编写补偿逻辑,确保事务的一致性。

适用场景

  • 适用于复杂的业务场景,尤其是跨多个服务的分布式事务。
  • 需要手动编写补偿逻辑,适合对性能和灵活性有较高要求的场景。

代码示例

import com.alibaba.fastjson.JSONObject;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

@LocalTCC
public class AccountService {

// Try 阶段:尝试扣减账户余额
// 通常在try阶段通过使用二阶段提交注解,指定提交的方法和回滚的方法,如下:
    @TwoPhaseBusinessAction(name = "decreaseBalance", commitMethod = "confirmDecreaseBalance", rollbackMethod = "cancelDecreaseBalance")
    public boolean tryDecreaseBalance(@BusinessActionContextParameter(paramName = "userId") Long userId,
                                      @BusinessActionContextParameter(paramName = "amount") Double amount) {
        // 检查账户余额是否足够
        if (checkBalance(userId, amount)) {
            // 预留资源(例如,冻结金额)
            freezeBalance(userId, amount);
            return true;
        }
        return false;
    }

    // Confirm 阶段:正式扣减账户余额
    public boolean confirmDecreaseBalance(BusinessActionContext actionContext) {
        // 从上下文中获取参数
        JSONObject params = actionContext.getActionContext();
        Long userId = params.getLong("userId");
        Double amount = params.getDouble("amount");

        // 正式扣减余额
        decreaseBalance(userId, amount);
        return true;
    }

    / / Cancel 阶段:取消扣减账户余额
    public boolean cancelDecreaseBalance(BusinessActionContext actionContext) {
        // 从上下文中获取参数
        JSONObject params = actionContext.getActionContext();
        Long userId = params.getLong("userId");
        Double amount = params.getDouble("amount");

        // 取消预留的资源(例如,解冻金额)
        unfreezeBalance(userId, amount);
        return true;
    }

    // 辅助方法
    private boolean checkBalance(Long userId, Double amount) {
        // 检查账户余额是否足够
        return true;  // 简化示例
    }

    private void freezeBalance(Long userId, Double amount) {
        // 冻结余额
        System.out.println("Freezing balance for user " + userId + " with amount " + amount);
    }

    private void decreaseBalance(Long userId, Double amount) {
        // 扣减余额
        System.out.println("Decreasing balance for user " + userId + " with amount " + amount);
    }

    private void unfreezeBalance(Long userId, Double amount) {
        // 解冻余额
        System.out.println("Unfreezing balance for user " + userId + " with amount " + amount);
    }
}

解释:

  • @LocalTCC:标记该类为 TCC 模式的本地事务参与者。
  • @TwoPhaseBusinessAction:定义TCC模式的三步操作:try、confirm和cancel。
  • 手动编写补偿逻辑:开发者需要为每个业务操作编写try、confirm和cancel方法,确保事务的一致性。
  • 资源预留:try阶段只预留资源,不真正修改数据;confirm阶段正式提交资源;cancel阶段回滚资源。
SAGA模式(Saga Orchestration Mode)

概述
SAGA模式是一种长事务模式,适用于涉及多个服务的复杂业务流程。SAGA模式将整个业务流程拆分为多个子事务,每个子事务都有对应的补偿操作。如果某个子事务失败,SAGA会依次执行前面子事务的补偿操作,确保事务的一致性。

SAGA 模式有两种实现方式:

  • Orchestration(编排模式):由一个中央控制器(Orchestrator)负责协调各个子事务的执行。
  • Choreography(编舞模式):各个子事务通过事件驱动的方式协同工作,没有中央控制器。

适用场景

  • 适用于涉及多个服务的复杂业务流程。
  • 适合长事务场景,允许部分子事务成功后继续执行后续操作。
  • 适合对最终一致性要求较高的场景。

代码示例:(Orchestration模式)

import io.seata.saga.statelang.domain.StateMachineInstance;
import io.seata.saga.statelang.domain.StateMachineStatus;
import io.seata.saga.statelang.service.StateMachineEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SagaOrderService {

    @Autowired
    private StateMachineEngine stateMachineEngine;

    // 创建订单并扣减账户余额
    public void createOrder(Long userId, Double amount) {
        // 定义SAGA流程的状态机ID
        String stateMachineId = "orderStateMachine";

        // 创建状态机实例
        StateMachineInstance instance = new StateMachineInstance();
        instance.setStateMachineId(stateMachineId);
        instance.setBizKey("order_" + System.currentTimeMillis());

        // 设置输入参数
        instance.setInputData(new JSONObject().fluentPut("userId", userId).fluentPut("amount", amount));

        // 启动SAGA流程
        StateMachineStatus status = stateMachineEngine.start(instance);

        if (status == StateMachineStatus.EXECUTED) {
            System.out.println("SAGA流程执行成功。");
        } else {
            System.err.println("SAGA流程执行失败。");
        }
    }
}

解释

  • StateMachineEngine:SAGA模式的状态机引擎,负责协调各个子事务的执行。
  • StateMachineInstance:表示SAGA流程的一个实例,包含状态机ID、业务键和输入参数。
  • start():启动SAGA流程,执行一系列子事务。
  • 补偿机制:如果某个子事务失败,SAGA会自动执行前面子事务的补偿操作,确保事务的一致性。
XA模式(X/Open XA Mode)

概述
XA模式是传统的两阶段提交协议,广泛应用于传统的关系型数据库系统。Seata支持XA模式,允许开发者使用XA协议来管理分布式事务。XA模式依赖于数据库的XA支持,因此需要数据库和JDBC驱动的支持。

适用场景

  • 适用于传统的企业级应用,尤其是已经使用XA协议的系统。
  • 适合对事务一致性要求极高的场景,但性能相对较低。

代码示例
XA是比较传统的方式,功能实现的话和AT模式相似,通常还是建议使用AT模式,更加简单和方便。

import io.seata.rm.datasource.DataSourceProxy;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class XAConfig {

    @Autowired
    private DataSource dataSource;

    // 配置XA模式的数据源代理
    @Bean
    public DataSource xaDataSource() {
        return new DataSourceProxy(dataSource);
    }

    // 配置事务管理器
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(xaDataSource());
    }
}

// 使用 XA 模式的业务逻辑
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private AccountService accountService;

    // 创建订单并扣减账户余额
    @Transactional
    public void createOrder(Long userId, Double amount) {
        try {
            // 1. 扣减账户余额
            accountService.decreaseBalance(userId, amount);

            // 2. 创建订单
            Order order = new Order();
            order.setUserId(userId);
            order.setAmount(amount);
            order.setStatus("CREATED");
            orderRepository.save(order);

            // 3. 模拟异常(用于测试回滚)
            // if (true) throw new RuntimeException("Simulated error");

            System.out.println("Order created successfully.");
        } catch (Exception e) {
            System.err.println("Error creating order: " + e.getMessage());
            throw e;  // 抛出异常以触发事务回滚
        }
    }
}

解释

  • DataSourceProxy:Seata提供的数据源代理,用于包装原有的数据源,使其支持XA协议。
  • @Transactional:标记该方法为事务性方法,确保所有操作都在同一个事务中执行。
  • 依赖XA支持:XA模式依赖于数据库和JDBC驱动的支持,因此需要确保使用的数据库和驱动程序支持XA协议。

(3)、四种模式的区别

在这里插入图片描述

9、Seata实现缓存一致性

上面四种工作模式的介绍中,其实比较常用的也就是AT模式和TCC模式。
我们在回头看下缓存一致性的问题,想要想实现Redis和Mysql的分布式事务。AT模式显然不合适,AT模式通常是通过undo_log实现回滚,也就是每个任务都是数据库任务才行。
TCC模式刚好能实现,通过TCC模式,可以自定义实现回滚方法,可以保证Redis和mysql的一致性,但方法千万不能写错了啊。
代码示例:
Service调用层类

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private OrderTcc orderTcc;

    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public void createOrder(Long userId, Long productId, int quantity) {
        // 调用 TCC 模式的 Try 接口
        orderTcc.tryCreateOrder(userId, productId, quantity);
    }
}

实现类

import com.alibaba.ttl.TransmittableThreadLocal;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@LocalTCC     // TCC模式
public class OrderTcc {

    @Autowired
    private OrderRepository orderRepository;  // MySQL 订单表的操作

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;  // Redis 操作

    // Try 接口:预留资源
    @TwoPhaseBusinessAction(name = "create-order")
    public boolean tryCreateOrder(@BusinessActionContextParameter("userId") Long userId,
                                  @BusinessActionContextParameter("productId") Long productId,
                                  @BusinessActionContextParameter("quantity") int quantity) {
        // 1. 在 MySQL 中插入订单(预留资源)
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setQuantity(quantity);
        order.setStatus("PENDING");  // 订单状态为待确认
        orderRepository.save(order);

        // 2. 在 Redis 中设置临时键,表示库存已预留
        String tempKey = "temp:stock:" + productId;
        redisTemplate.opsForValue().set(tempKey, quantity, 60, TimeUnit.SECONDS);  // 设置 60 秒过期时间

        return true;
    }

    // Confirm 接口:确认提交
    public boolean commit(BusinessActionContext actionContext) {
        // 1. 获取订单 ID
        Long orderId = (Long) actionContext.getActionContext("orderId");

        // 2. 更新 MySQL 中的订单状态为已完成
        orderRepository.updateStatusById(orderId, "COMPLETED");

        // 3. 在 Redis 中设置正式的库存缓存
        Long productId = (Long) actionContext.getActionContext("productId");
        int quantity = (int) actionContext.getActionContext("quantity");
        redisTemplate.opsForValue().set("stock:" + productId, quantity);

        // 4. 删除临时键
        redisTemplate.delete("temp:stock:" + productId);

        return true;
    }

    // Cancel 接口:回滚资源
    public boolean rollback(BusinessActionContext actionContext) {
        // 1. 获取订单 ID
        Long orderId = (Long) actionContext.getActionContext("orderId");

        // 2. 回滚 MySQL 中的订单
        orderRepository.deleteById(orderId);

        // 3. 删除 Redis 中的临时键
        Long productId = (Long) actionContext.getActionContext("productId");
        redisTemplate.delete("temp:stock:" + productId);
        return true;
    }
}

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

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

相关文章

概率论得学习和整理32: 用EXCEL描述正态分布,用δ求累计概率,以及已知概率求X的区间

目录 1 正态分布相关 2 正态分布的函数和曲线 2.1 正态分布的函数值&#xff0c;用norm.dist() 函数求 2.2 正态分布的pdf 和 cdf 2.3 正态分布的图形随着u 和 δ^2的变化 3 正态分布最重要的3δ原则 3.0 注意&#xff0c;这里说的概率一定是累计概率CDF&#xff0c;而…

Day1 苍穹外卖前端 Vue基础、Vue基本使用方式、Vue-router、Vuex、TypeScript

目录 1.VUE 基础回顾 1.1 基于脚手架创建前端工程 1.1.1 环境要求 1.1.2 脚手架创建项目 1.1.3 工程结构 1.1.4 启动前端服务 1.2 vue基本使用方式 1.2.1 vue 组件 1.2.2 文本插值 1.2.3 属性绑定 1.2.4 事件绑定 1.2.5 双向绑定 1.2.6 条件渲染 1.2.7 跨域问题 1.2.8 axios 1.…

esp8266_TFTST7735语音识别UI界面虚拟小助手

文章目录 一 实现思路1 项目简介1.1 项目效果1.2 实现方式 2 项目构成2.1 软硬件环境2.2 完整流程总结&#xff08;重点整合&#xff09;(1) 功能逻辑图(2) 接线(3) 使用esp8266控制TFT屏(4)TFT_espI库配置方法(5) TFT_esp库常用代码详解(6)TFT屏显示图片(7) TFT屏显示汉字(8) …

java web springboot

0. 引言 SpringBoot对Spring的改善和优化&#xff0c;它基于约定优于配置的思想&#xff0c;提供了大量的默认配置和实现 使用SpringBoot之后&#xff0c;程序员只需按照它规定的方式去进行程序代码的开发即可&#xff0c;而无需再去编写一堆复杂的配置 SpringBoot的主要功能…

Windows下ESP32-IDF开发环境搭建

Windows下ESP32-IDF开发环境搭建 文章目录 Windows下ESP32-IDF开发环境搭建一、软件安装二、搭建IDF开发环境2.1 安装VS Code插件&#xff1a;2.2 配置ESP-IDF插件&#xff1a;2.3 下载例程源码&#xff1a; 三、编译和烧录代码四、Windows下使用命令行编译和烧录程序4.1 配置环…

6UCPCI板卡设计方案:8-基于双TMS320C6678 + XC7K420T的6U CPCI Express高速数据处理平台

基于双TMS320C6678 XC7K420T的6U CPCI Express高速数据处理平台 1、板卡概述 板卡由我公司自主研发&#xff0c;基于6UCPCI架构&#xff0c;处理板包含双片TI DSP TMS320C6678芯片&#xff1b;一片Xilinx公司FPGA XC7K420T-1FFG1156 芯片&#xff1b;六个千兆网口&#xff…

c++--------------------------------接口实现

引用参数 引用的基本概念 在C中&#xff0c;引用是一个别名&#xff0c;它为已存在的变量提供了另一个名字。引用的声明格式为类型& 引用名 变量名;。例如&#xff0c;int num 10; int& ref num;&#xff0c;这里ref就是num的引用&#xff0c;对ref的操作等价于对nu…

docker run命令大全

docker run命令大全 基本语法常用选项基础选项资源限制网络配置存储卷和挂载环境变量重启策略其他高级选项示例总结docker run 命令是 Docker 中最常用和强大的命令之一,用于创建并启动一个新的容器。该命令支持多种选项和参数,可以满足各种使用场景的需求。以下是 docker ru…

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入&#xff0c;3568采集并显示至hdmi RKVICAP 驱动框架说明 RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转&#xff0c;以及控制 subdevice(如 mipi dphy 及 sensor) 的上下电等功能。 对于RK356X 芯片而言&#xff0c; VICAP…

怎么在idea中创建springboot项目

最近想系统学习下springboot&#xff0c;尝试一下全栈路线 从零开始&#xff0c;下面将叙述下如何创建项目 环境 首先确保自己环境没问题 jdkMavenidea 创建springboot项目 1.打开idea&#xff0c;选择file->New->Project 2.选择Spring Initializr->设置JDK->…

springboot476基于vue篮球联盟管理系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统篮球联盟管理系统信息管理难度大&#xff0c;容错率低&am…

蓝桥杯嵌入式备赛教程(1、led,2、lcd,3、key)

一、工程模版创建流程 第一步 创建新项目 第二步 选择型号和管脚封装 第三步 RCC使能 外部时钟&#xff0c;高速外部时钟 第四步晶振时钟配置 由数据手册7.1可知外部晶振频率为24MHz 最后一项设置为80 按下回车他会自动配置时钟 第五步&#xff0c;如果不勾选可能程序只会…

步进电机位置速度双环控制实现

步进电机位置速度双环控制实现 野火stm32电机教学 提高部分-第11讲 步进电机位置速度双环控制实现(1)_哔哩哔哩_bilibili PID模型 位置环作为外环,速度环作为内环。设定目标位置和实际转轴位置的位置偏差,经过位置PID获得位置期望,然后讲位置期望(位置变化反映了转轴的速…

devops和ICCID简介

Devops DevOps&#xff08;Development 和 Operations 的组合&#xff09;是一种软件开发和 IT 运维的哲学&#xff0c;旨在促进开发、技术运营和质量保障&#xff08;QA&#xff09;部门之间的沟通、协作与整合。它强调自动化流程&#xff0c;持续集成&#xff08;CI&#xf…

Apache RocketMQ 5.1.3安装部署文档

官方文档不好使&#xff0c;可以说是一坨… 关键词&#xff1a;Apache RocketMQ 5.0 JDK 17 废话少说&#xff0c;开整。 1.版本 官网地址&#xff0c;版本如下。 https://rocketmq.apache.org/download2.配置文件 2.1namesrv端口 在ROCKETMQ_HOME/conf下 新增namesrv.pro…

数据结构:算法篇:快速排序;直接插入排序

目录 快速排序 直接插入排序 改良版冒泡排序 快速排序 理解&#xff1a; ①从待排序元素中选定一个基准元素&#xff1b; ②以基准元素将数据分为两部分&#xff1a;&#xff08;可以将&#xff1a;大于基准元素放左&#xff0c;小于基准元素放右&#xff09; ③对左半部分…

运维工程师面试系统监控与优化自动化与脚本云计算的理解虚拟化技术的优点和缺点

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

如何打造用户友好的维护页面:6个创意提升WordPress网站体验

在网站运营中&#xff0c;无论是个人博主还是大型企业网站的管理员&#xff0c;难免会遇到需要维护的情况。无论是服务器迁移、插件更新&#xff0c;还是突发的技术故障&#xff0c;都可能导致网站短暂无法访问。这时&#xff0c;设计维护页面能很好的缓解用户的不满&#xff0…

postman读取文件执行

要从文件获取的变量 text 在pre-request 中写从文件获取数据的脚本。脚本实现了&#xff0c;设置了text默认值&#xff0c;从文件读取text列&#xff0c;将text存入环境变量 //获取text参数 var text "济南天气"; if(data.text){ text data.text } pm.environment.…

37. Three.js案例-绘制部分球体

37. Three.js案例-绘制部分球体 实现效果 知识点 WebGLRenderer WebGLRenderer 是Three.js中的一个渲染器类&#xff0c;用于将3D场景渲染到网页上。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数&#xff0c;可选。 常用…