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

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 {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate 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 {@Autowiredprivate StateMachineEngine stateMachineEngine;// 创建订单并扣减账户余额public void createOrder(Long userId, Double amount) {// 定义SAGA流程的状态机IDString 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 {@Autowiredprivate DataSource dataSource;// 配置XA模式的数据源代理@Beanpublic DataSource xaDataSource() {return new DataSourceProxy(dataSource);}// 配置事务管理器@Beanpublic 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 {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate AccountService accountService;// 创建订单并扣减账户余额@Transactionalpublic 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 {@Autowiredprivate 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 {@Autowiredprivate OrderRepository orderRepository;  // MySQL 订单表的操作@Autowiredprivate 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. 获取订单 IDLong 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. 获取订单 IDLong 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.rhkb.cn/news/494759.html

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

相关文章

如何评估一个股票API接口

评估一个股票 API 接口的质量&#xff0c;可以从以下几个方面进行&#xff1a; 数据准确性 行情数据&#xff1a;实时价格、历史价格、成交量、成交额等数据应与证券交易所或权威金融数据提供商的官方数据高度一致&#xff0c;确保没有明显的错误。财务数据&#xff1a;企业的…

某集团GIF动态验证码识别

注意&#xff0c;本文只提供学习的思路&#xff0c;严禁违反法律以及破坏信息系统等行为&#xff0c;本文只提供思路 如有侵犯&#xff0c;请联系作者下架 本文识别已同步上线至OCR识别网站&#xff1a; http://yxlocr.nat300.top/ocr/other/16 最近某集团更新了验证码&#x…

数据库系统原理:数据恢复与备份策略

3.1可行性分析 开发者在进行开发系统之前&#xff0c;都需要进行可行性分析&#xff0c;保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该《数据库系统原理》课程平台所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识…

CPU算法分析LiteAIServer裸土检测算法如何应用在农田科学管理中?

农田是农业生产的基础&#xff0c;是保障国家粮食安全和农业可持续发展的关键。随着人口增长和城市化进程的加快&#xff0c;农田保护和治理面临着前所未有的挑战。如今农田土壤依旧面临着巨大挑战&#xff1a; 1、‌土壤侵蚀‌&#xff1a;长期的风蚀、水蚀等自然因素&#x…

Marscode AI辅助编程

直接使用Marscode的云服务来开发&#xff0c;也是很方便的&#xff0c;不用担心配置环境的问题&#xff0c;很适合初步学习&#xff0c;在任何设备都能开发。 番茄钟 请你基于html、tailwind css和javascript&#xff0c;帮我设计一个“番茄时钟”。要求UI简洁美观大方&#x…

Debian 12 安装配置 fail2ban 保护 SSH 访问

背景介绍 双十一的时候薅羊毛租了台腾讯云的虚机, 是真便宜, 只是没想到才跑了一个月, 系统里面就收集到了巨多的 SSH 恶意登录失败记录. 只能说, 互联网真的是太不安全了. 之前有用过 fail2ban 在 CentOS 7 上面做过防护, 不过那已经是好久好久之前的故事了, 好多方法已经不…

idea2024创建JavaWeb项目以及配置Tomcat详解

今天呢&#xff0c;博主的学习进度也是步入了JavaWeb&#xff0c;目前正在逐步杨帆旗航&#xff0c;迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正…

Canoe E2E校验自定义Checksum算法

文章目录 一、添加 DBC文件二、导入要仿真的ECU节点三、编写 CAPL脚本1. 创建 .can 文件2. 设置counter递增3. 设置 CRC 算法&#xff0c;以profile01 8-bit SAE J1850 CRC校验为例 四、开始仿真五、运行结果CRC在线校验 当E2E的 CRC算法非常规算法&#xff0c;则需要自己编写代…

PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程

PyTorch 神经网络回归&#xff08;Regression&#xff09;任务&#xff1a;关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合&#xff0c;具体演示了从数据准备到模型训练和可视化的完整过程。首先&#xff0c;利用一维线性空间生成带噪…

【uni-app】2025最新uni-app一键登录保姆级教程(包含前后端获取手机号方法)(超强避坑指南)

前言&#xff1a; 最近在配置uni-app一键登录时遇到了不少坑&#xff0c;uni-app的配套文档较为混乱&#xff0c;并且有部分更新的内容也没有及时更改在文档上&#xff0c;导致部分开发者跟着uni-app配套文档踩坑&#xff01;而目前市面上的文章质量也层次不齐&#xff0c;有的…

干货分享:ISO 20000认证的适用范围、认证资料清单、认证流程等问题详解

编辑&#xff1a;石芸姗 审核&#xff1a;贺兆普 在当今这个数字化时代&#xff0c;信息技术&#xff08;IT&#xff09;已成为企业运营与发展的核心驱动力。随着技术的不断进步和业务需求的日益复杂&#xff0c;企业对IT服务的质量、效率及安全性提出了更高要求。 信息技术服…

Element-plus表格使用总结

这里我使用的是Vue工程进行开发学习&#xff0c;安装需要通过包管理器进行下载 npm install element-plus --save 然后在main.js中配置文件即可使用&#xff0c;如果在引入index.css时没有提示&#xff0c;无需担心&#xff0c;直接写index.css即可导入样式。 Table表格 表格…

CNN和Transfomer介绍

文章目录 CNN和Transfomer介绍CNN和Transfomer的区别1. **基本概念**2. **数据处理方式**3. **模型结构差异**4. **应用场景区别** 自注意力机制1. **自注意力机制的概念**2. **自注意力机制的实现步骤**3. **自注意力机制的优势** Transformer结构组成1. **多头注意力层&#…

如何解决 ‘adb‘ 不是内部或外部命令,也不是可运行的程序或批处理文件的问题

在cmd中输入 adb &#xff0c;显示 ‘adc‘ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件的问题 解决办法&#xff1a;在环境变量中添加adb所在的路径 1、找到 adb.exe 的所在的文件路径&#xff0c;一般在 Android 安装目录下 \sdk\platform-tools\adb.exe…

数据结构---------二叉树前序遍历中序遍历后序遍历

以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例&#xff0c;包括递归和非递归&#xff08;借助栈实现&#xff09;两种方式&#xff1a; 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…

网络架构与IP技术:4K/IP演播室制作的关键支撑

随着科技的不断发展&#xff0c;广播电视行业也在不断迭代更新&#xff0c;其中4K/IP演播室技术的应用成了一个引人注目的焦点。4K超高清技术和IP网络技术的结合&#xff0c;不仅提升了节目制作的画质和效果&#xff0c;还为节目制作带来了更高的效率和灵活性。那么4K超高清技术…

MySQL 8.0:explain analyze 分析 SQL 执行过程

介绍 MySQL 8.0.16 引入一个实验特性&#xff1a;explain formattree &#xff0c;树状的输出执行过程&#xff0c;以及预估成本和预估返 回行数。在 MySQL 8.0.18 又引入了 EXPLAIN ANALYZE&#xff0c;在 formattree 基础上&#xff0c;使用时&#xff0c;会执行 SQL &#…

观察者模式(sigslot in C++)

大家&#xff0c;我是东风&#xff0c;今天抽点时间整理一下我很久前关注的一个不错的库&#xff0c;可以支持我们在使用标准C的时候使用信号槽机制进行观察者模式设计&#xff0c;sigslot 官网&#xff1a; http://sigslot.sourceforge.net/ 本文较为详尽探讨了一种观察者模…

【已解决】黑马点评项目Redis版本替换过程中误删数据库后前端显示出现的问题

为了实现基于Redis的Stream结构作为消息队列&#xff0c;实现异步秒杀下单的功能&#xff0c;换Redis版本 Redis版本太旧了&#xff0c;所以从3.2.1换成了5.0.14 此时犯了一个大忌&#xff0c;因为新的Redis打开后&#xff0c;没有缓存&#xff0c;不知道出了什么问题&#xf…

基于Spring Boot的九州美食城商户一体化系统

一、系统背景与目标 随着美食城行业的快速发展&#xff0c;传统的管理方式已经难以满足日益增长的管理需求和用户体验要求。因此&#xff0c;九州美食城商户一体化系统应运而生&#xff0c;旨在通过信息化、智能化的管理方式&#xff0c;实现美食城的商户管理、菜品管理、订单…