当前位置: 首页 > news >正文

seate TCC模式案例

场景描述

  1. 用户下单时,需要创建订单并从用户账户中扣除相应的余额。
  2. 如果订单创建成功但余额划扣失败,则需要回滚订单创建操作。
  3. 使用 Seata 的 TCC 模式来保证分布式事务的一致性。

1. 项目结构

假设我们有两个微服务:

  • Order Service:负责创建订单。
  • Account Service:负责扣除用户余额。

此外,还需要一个 Seata Server 来协调分布式事务。


2. 数据库设计

Order 表
CREATE TABLE `orders` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY,`user_id` VARCHAR(32) NOT NULL,`product_id` VARCHAR(32) NOT NULL,`amount` DECIMAL(10, 2) NOT NULL,`status` VARCHAR(16) DEFAULT 'INIT' -- 状态:INIT(初始化)、CONFIRMED(确认)、CANCELLED(取消)
);
Account 表
CREATE TABLE `accounts` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY,`user_id` VARCHAR(32) NOT NULL,`balance` DECIMAL(10, 2) NOT NULL
);

3. Order Service

(1) 定义 TCC 接口

OrderService 中定义 Try、Confirm 和 Cancel 方法。

@LocalTCC
public interface OrderTccService {@TwoPhaseBusinessAction(name = "createOrder", commitMethod = "confirmOrder", rollbackMethod = "cancelOrder")boolean createOrder(BusinessActionContext context, String userId, String productId, BigDecimal amount);boolean confirmOrder(BusinessActionContext context);boolean cancelOrder(BusinessActionContext context);
}
(2) 实现 TCC 方法
@Service
public class OrderTccServiceImpl implements OrderTccService {@Autowiredprivate OrderMapper orderMapper;@Overridepublic boolean createOrder(BusinessActionContext context, String userId, String productId, BigDecimal amount) {// Try 阶段:创建订单,状态为 INITOrder order = new Order();order.setUserId(userId);order.setProductId(productId);order.setAmount(amount);order.setStatus("INIT");orderMapper.insert(order);// 将订单 ID 存入上下文,供 Confirm 和 Cancel 使用context.getActionContext().put("orderId", order.getId());return true;}@Overridepublic boolean confirmOrder(BusinessActionContext context) {// Confirm 阶段:将订单状态更新为 CONFIRMEDLong orderId = (Long) context.getActionContext("orderId");orderMapper.updateStatus(orderId, "CONFIRMED");return true;}@Overridepublic boolean cancelOrder(BusinessActionContext context) {// Cancel 阶段:将订单状态更新为 CANCELLEDLong orderId = (Long) context.getActionContext("orderId");orderMapper.updateStatus(orderId, "CANCELLED");return true;}
}
(3) Mapper 定义
@Mapper
public interface OrderMapper {void insert(Order order);void updateStatus(Long orderId, String status);
}

4. Account Service

(1) 定义 TCC 接口

AccountService 中定义 Try、Confirm 和 Cancel 方法。

@LocalTCC
public interface AccountTccService {@TwoPhaseBusinessAction(name = "deductBalance", commitMethod = "confirmDeduct", rollbackMethod = "cancelDeduct")boolean deductBalance(BusinessActionContext context, String userId, BigDecimal amount);boolean confirmDeduct(BusinessActionContext context);boolean cancelDeduct(BusinessActionContext context);
}
(2) 实现 TCC 方法
@Service
public class AccountTccServiceImpl implements AccountTccService {@Autowiredprivate AccountMapper accountMapper;@Overridepublic boolean deductBalance(BusinessActionContext context, String userId, BigDecimal amount) {// Try 阶段:检查余额是否足够,并冻结相应金额Account account = accountMapper.findByUserId(userId);if (account.getBalance().compareTo(amount) < 0) {throw new RuntimeException("Insufficient balance");}accountMapper.freezeBalance(userId, amount);// 将冻结金额存入上下文,供 Confirm 和 Cancel 使用context.getActionContext().put("userId", userId);context.getActionContext().put("amount", amount);return true;}@Overridepublic boolean confirmDeduct(BusinessActionContext context) {// Confirm 阶段:扣除已冻结的金额String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountMapper.confirmDeduct(userId, amount);return true;}@Overridepublic boolean cancelDeduct(BusinessActionContext context) {// Cancel 阶段:释放已冻结的金额String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountMapper.cancelDeduct(userId, amount);return true;}
}
(3) Mapper 定义
@Mapper
public interface AccountMapper {Account findByUserId(String userId);void freezeBalance(String userId, BigDecimal amount);void confirmDeduct(String userId, BigDecimal amount);void cancelDeduct(String userId, BigDecimal amount);
}

5. 调用方(API Gateway 或其他服务)

在调用方使用 @GlobalTransactional 注解开启全局事务。

@RestController
@RequestMapping("/api/orders")
public class OrderController {@Autowiredprivate OrderTccService orderTccService;@Autowiredprivate AccountTccService accountTccService;@PostMapping("/create")@GlobalTransactionalpublic ResponseEntity<String> createOrder(@RequestBody CreateOrderRequest request) {try {// 创建订单orderTccService.createOrder(null, request.getUserId(), request.getProductId(), request.getAmount());// 扣除余额accountTccService.deductBalance(null, request.getUserId(), request.getAmount());return ResponseEntity.ok("Order created successfully");} catch (Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to create order: " + e.getMessage());}}
}

6. 测试流程

  1. 启动 Seata Server。
  2. 启动 Order Service 和 Account Service。
  3. 发送请求到 /api/orders/create 接口,创建订单并扣除余额。
  4. 如果任意一个步骤失败,Seata 会自动触发回滚逻辑。

7. 关键点总结

  1. TCC 模式的核心

    • Try:预留资源。
    • Confirm:确认操作。
    • Cancel:补偿操作。
  2. Spring Cloud 集成

    • 使用 @LocalTCC 和 @TwoPhaseBusinessAction 注解定义 TCC 接口。
    • 使用 @GlobalTransactional 开启全局事务。
  3. 事务一致性

    • 如果任意一步失败,Seata 会自动调用 Cancel 方法进行回滚,确保数据一致。

TCC模式还会存在空回滚,幂等,悬挂等问题 

1. 空回滚

问题描述

  • 定义:在 TCC 模式中,如果 Try 阶段没有执行(例如由于网络超时或服务不可用),但 Cancel 阶段被调用了,则会导致空回滚。
  • 原因
    • Try 请求未到达服务端,或者未成功执行。
    • Seata Server 在协调事务时检测到失败,直接触发了 Cancel 阶段。

解决方案

  • 解决思路:在 Cancel 方法中判断是否需要执行回滚操作。
  • 实现方式
    • 在数据库中增加一个状态字段,用于标记资源是否已经被预留(Try 阶段是否执行过)。
    • 如果状态字段表明资源未被预留,则直接跳过 Cancel 操作。
示例代码
@Override
public boolean cancelDeduct(BusinessActionContext context) {String userId = (String) context.getActionContext("userId");Account account = accountMapper.findByUserId(userId);// 判断是否需要回滚(账户是否有冻结金额)if (account.getFrozenAmount().compareTo(BigDecimal.ZERO) == 0) {return true; // 跳过空回滚}// 执行取消逻辑accountMapper.cancelDeduct(userId, (BigDecimal) context.getActionContext("amount"));return true;
}

2. 幂等性

问题描述

  • 定义:TCC 的 Confirm 或 Cancel 方法可能因为网络重试等原因被多次调用,导致重复操作。
  • 原因
    • Seata Server 可能会多次尝试调用 Confirm 或 Cancel 方法。
    • 客户端或网络层可能引发重复请求。

解决方案

  • 解决思路:确保 Confirm 和 Cancel 方法是幂等的。
  • 实现方式
    • 使用数据库的状态字段来记录操作是否已经完成。
    • 如果某个操作已经完成,则直接返回成功,不再重复执行。
示例代码
@Override
public boolean confirmDeduct(BusinessActionContext context) {String userId = (String) context.getActionContext("userId");Account account = accountMapper.findByUserId(userId);// 判断是否已经确认if ("CONFIRMED".equals(account.getStatus())) {return true; // 已经确认,直接返回}// 执行确认逻辑accountMapper.confirmDeduct(userId, (BigDecimal) context.getActionContext("amount"));accountMapper.updateStatus(userId, "CONFIRMED");return true;
}@Override
public boolean cancelDeduct(BusinessActionContext context) {String userId = (String) context.getActionContext("userId");Account account = accountMapper.findByUserId(userId);// 判断是否已经取消if ("CANCELLED".equals(account.getStatus())) {return true; // 已经取消,直接返回}// 执行取消逻辑accountMapper.cancelDeduct(userId, (BigDecimal) context.getActionContext("amount"));accountMapper.updateStatus(userId, "CANCELLED");return true;
}

3. 悬挂

问题描述

  • 定义:Confirm 或 Cancel 方法比 Try 方法先执行,导致业务逻辑异常。
  • 原因
    • Try 请求在网络传输中延迟,而 Seata Server 认为 Try 失败并提前触发了 Confirm 或 Cancel。
    • Try 请求最终到达服务端时,发现 Confirm 或 Cancel 已经执行。

解决方案

  • 解决思路:通过状态字段和事务上下文信息,避免悬挂问题。
  • 实现方式
    • 在数据库中记录事务的执行状态。
    • 在 Try 方法中检查是否存在对应的 Confirm 或 Cancel 操作。如果有,则直接跳过 Try 操作。
示例代码
@Override
public boolean deductBalance(BusinessActionContext context, String userId, BigDecimal amount) {Account account = accountMapper.findByUserId(userId);// 判断是否已经确认或取消if ("CONFIRMED".equals(account.getStatus()) || "CANCELLED".equals(account.getStatus())) {return true; // 悬挂处理:直接返回}// 执行 Try 逻辑if (account.getBalance().compareTo(amount) < 0) {throw new RuntimeException("Insufficient balance");}accountMapper.freezeBalance(userId, amount);return true;
}

4. 总结

问题原因解决方案
空回滚Try 未执行,但 Cancel 被调用在 Cancel 方法中检查 Try 是否已执行,未执行则跳过。
幂等性Confirm 或 Cancel 方法被多次调用使用状态字段记录操作是否已完成,避免重复执行。
悬挂Confirm 或 Cancel 比 Try 先执行在 Try 方法中检查 Confirm 或 Cancel 是否已执行,已执行则跳过 Try。

通过以上方法,可以有效解决 TCC 模式中的空回滚、幂等性和悬挂问题,从而保证分布式事务的一致性和可靠性。


用字段状态检测以上问题,程序并不健壮,如果在高并发情况下还会出现一些问题,为了程序健壮性,达到强一致,我们还需要引入令牌和分布式锁


1. 状态字段的作用

  • 状态字段 是最基础的幂等性保障方式。
  • 它通过记录操作的状态(如 INITCONFIRMEDCANCELLED)来判断某个操作是否已经完成。
  • 优点:简单直观,易于实现。
  • 缺点:在高并发场景下可能会出现竞争条件(race condition),导致状态更新不一致。

2. 引入令牌机制

为什么需要令牌?

  • 定义:令牌是一种唯一标识符,用于确保每个请求只被执行一次。
  • 在分布式系统中,网络重试可能导致同一个请求被多次发送到服务端。如果服务端无法区分这些重复请求,则会导致重复操作。
  • 适用场景
    • 请求可能因为网络问题被重复发送。
    • 需要严格避免重复操作的场景(如支付、扣款等)。

实现方式

  • 每个请求生成一个唯一的令牌(如 UUID)。
  • 服务端在接收到请求时,先检查该令牌是否已经被处理过。
  • 如果已处理过,则直接返回成功;否则执行业务逻辑并记录该令牌。
示例代码
@Override
public boolean confirmDeduct(BusinessActionContext context) {String token = (String) context.getActionContext("token");if (StringUtils.isEmpty(token)) {throw new RuntimeException("Token is missing");}// 检查令牌是否已经处理过if (deductTokenRepository.existsByToken(token)) {return true; // 幂等性处理:直接返回}// 执行确认逻辑String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountMapper.confirmDeduct(userId, amount);// 记录令牌DeductToken deductToken = new DeductToken();deductToken.setToken(token);deductToken.setStatus("CONFIRMED");deductTokenRepository.save(deductToken);return true;
}
数据库表设计
CREATE TABLE `deduct_token` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY,`token` VARCHAR(64) NOT NULL UNIQUE,`status` VARCHAR(16) NOT NULL,`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

3. 引入分布式锁

为什么需要分布式锁?

  • 定义:分布式锁是一种协调机制,用于保证多个节点对共享资源的操作是互斥的。
  • 在高并发场景下,即使有状态字段或令牌机制,也可能因为多个线程同时访问同一资源而导致数据不一致。
  • 适用场景
    • 多个服务实例同时处理同一个请求。
    • 需要强一致性保障的场景。

实现方式

  • 使用 Redis 或 Zookeeper 实现分布式锁。
  • 在业务逻辑执行前获取锁,在业务逻辑完成后释放锁。
  • 如果无法获取锁,则等待或直接返回失败。
示例代码(基于 Redis)
@Autowired
private RedisTemplate<String, String> redisTemplate;@Override
public boolean confirmDeduct(BusinessActionContext context) {String lockKey = "lock:confirmDeduct:" + context.getXid(); // XID 是全局事务 IDString userId = (String) context.getActionContext("userId");// 尝试获取分布式锁Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, userId, 10, TimeUnit.SECONDS);if (Boolean.FALSE.equals(locked)) {throw new RuntimeException("Failed to acquire lock");}try {// 检查状态字段Account account = accountMapper.findByUserId(userId);if ("CONFIRMED".equals(account.getStatus())) {return true; // 已经确认,直接返回}// 执行确认逻辑accountMapper.confirmDeduct(userId, (BigDecimal) context.getActionContext("amount"));accountMapper.updateStatus(userId, "CONFIRMED");return true;} finally {// 释放分布式锁redisTemplate.delete(lockKey);}
}

4. 综合解决方案

在实际项目中,通常会结合 状态字段令牌机制分布式锁 来实现全面的幂等性保障:

  1. 状态字段
    • 用来记录操作的状态,避免重复执行。
  2. 令牌机制
    • 为每个请求分配唯一标识符,确保每个请求只被执行一次。
  3. 分布式锁
    • 在高并发场景下,使用分布式锁保护共享资源,避免竞争条件。
示例流程
  1. 客户端生成令牌
    • 客户端在发送请求时生成一个唯一的令牌(如 UUID),并将令牌附加到请求中。
  2. 服务端校验令牌
    • 服务端接收到请求后,首先检查令牌是否存在。
    • 如果令牌已存在,则直接返回成功。
  3. 获取分布式锁
    • 如果令牌不存在,则尝试获取分布式锁。
    • 如果锁获取成功,则继续执行业务逻辑;否则返回失败或等待。
  4. 更新状态字段
    • 执行业务逻辑后,更新状态字段以标记操作已完成。
  5. 记录令牌
    • 将令牌保存到数据库中,以便后续重复请求可以直接跳过。

5. 总结

方法适用场景优缺点
状态字段基础的幂等性保障,适用于大多数场景。优点:简单易用;缺点:高并发下可能存在问题。
令牌机制适用于需要严格避免重复操作的场景(如支付、扣款)。优点:能有效防止重复请求;缺点:需要额外存储令牌信息。
分布式锁适用于高并发场景,需要强一致性保障的场景。优点:避免竞争条件;缺点:增加了系统复杂性和性能开销。

通过结合 状态字段令牌机制分布式锁,可以构建一个健壮的幂等性保障机制,从而更好地应对分布式事务中的各种挑战。

相关文章:

seate TCC模式案例

场景描述 用户下单时&#xff0c;需要创建订单并从用户账户中扣除相应的余额。如果订单创建成功但余额划扣失败&#xff0c;则需要回滚订单创建操作。使用 Seata 的 TCC 模式来保证分布式事务的一致性。 1. 项目结构 假设我们有两个微服务&#xff1a; Order Service&#x…...

Transfomer的本质

Transformer是一个基于自注意力机制的深度学习模型&#xff0c;用于处理序列数据&#xff0c;主要结构包括编码器和解码器&#xff0c;每个部分由多头自注意力和前馈网络组成&#xff0c;加上残差连接和层归一化&#xff0c;以及位置编码。它解决了RNN的并行处理问题&#xff0…...

final修饰变量的注意

在Java中&#xff0c;使用final修饰变量时&#xff0c;需注意以下关键事项&#xff1a; 1. 初始化规则 实例变量&#xff1a; 必须在声明时、构造器或实例初始化块中初始化。所有构造器分支必须保证初始化。 class Example {final int x; // 实例变量final int y;public Exampl…...

前端与传统接口的桥梁:JSONP解决方案

1.JSONP原理 1.1.动态脚本注入 说明&#xff1a;通过创建 <script> 标签绕过浏览器同源策略 1.2.回调约定 说明&#xff1a;服务端返回 函数名(JSON数据) 格式的JS代码 1.3.自动执行 说明&#xff1a;浏览器加载脚本后立即触发前端预定义的回调函数&#xff08;现代开…...

SQL注入 01

0x01 用户、脚本、数据库之间的关系 首先客户端发出了ID36的请求&#xff0c;脚本引擎收到后将ID36的请求先代入脚本的sql查询语句Select * from A where id 36 &#xff0c; 然后将此代入到数据库中进行查询&#xff0c;查到后将返回查询到的所有记录给脚本引擎&#xff0c;接…...

Java之封装(学习笔记)

封装定义&#xff08;个人理解&#xff1a;&#xff09; 封装就像电视遥控器的按钮&#xff0c;比如音量键&#xff0c;对于我们使用者来说就是可以直接按下去调控音量&#xff0c;对于代码写作者来说就是封装了调控音量的方法&#xff0c;使得我们只能去调控&#xff0c;不能改…...

每天学一个 Linux 命令(27):head

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/27/index.html head 是 Linux 中用于查看文件开头部分内容的命令,默认显示文件前 10 行,适合快速预览文件结构或日志头部信息。 命令格式 head [选项] [文件]常用选项 选项说明-n <行数>指定显示前 N 行(如…...

山东大学软件学院创新项目实训开发日志(20)之中医知识问答自动生成对话标题bug修改

在原代码中存在一个bug&#xff1a;当前对话的标题不是现有对话的用户的第一段的前几个字&#xff0c;而是历史对话的第一段的前几个字。 这是生成标题的逻辑出了错误&#xff1a; 当改成size()-1即可...

论文阅读:2024 ICML Is DPO Superior to PPO for LLM Alignment? A Comprehensive Study

Is DPO Superior to PPO for LLM Alignment? A Comprehensive Study https://www.doubao.com/chat/3506902534329346 https://arxiv.org/pdf/2404.10719 速览 这篇论文主要探讨了大语言模型对齐中两种主流方法——**DPO&#xff08;直接偏好优化&#xff09;和PPO&#xf…...

2025年人工智能指数报告:技术突破与社会变革的全景透视

《2025年人工智能指数报告》作为斯坦福大学人工智能实验室与多方合作的年度重磅研究&#xff0c;以超过千页的篇幅全景式展现了人工智能技术在全球范围内的发展轨迹与深远影响。这份报告不仅延续了对AI技术性能、科研进展与产业应用的追踪&#xff0c;更首次深入探讨了AI硬件的…...

【Python笔记 01】变量、标识符

一、 变量 1、变量的作用 计算机存储空间&#xff0c;用于保存数据。 2、定义变量的格式 格式&#xff1a;变量名 值 示例&#xff1a; num1 3 # num1就是一个变量&#xff0c;保存蛋糕的价格 num2 10 #num2也是一个变量&#xff0c;保存雪碧的价格 total num1 num2 …...

WebSocket启用备忘

一&#xff1a;引入依赖&#xff1a; <!--WebSocket专用--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org…...

文件管理详解(曼波脑图版)

(✪ω✪)曼波来啦&#xff01;文件管理的知识曼波这就为你详细讲解哟~ 记得要准备好小本本做笔记哦&#xff01;(๑˃̵ᴗ˂̵)و &#x1f31f; 文件读写操作 &#x1f31f; // 最可爱的文件读取写法 (✧∇✧) try (BufferedReader reader new BufferedReader(new FileRead…...

学习笔记十九——Rust多态

&#x1f9e9; Rust 多态终极通俗指南 &#x1f4da; 目录导航 多态一句话概念静态分派 vs 动态分派——根本差异参数化多态&#xff08;泛型&#xff09; 3.1 函数里的泛型 3.2 结构体里的泛型 3.3 方法里的泛型 3.4 枚举里的泛型Ad hoc 多态&#xff08;特例多态&#xff0…...

在 Linux 上部署 .NET Core 应用并配置为开机自动启动

在本文中&#xff0c;我们将详细介绍如何在 Linux 系统上部署 .NET Core 应用程序&#xff0c;并配置为开机自动启动。以下是一步一步的详细部署过程&#xff0c;适用于将 .NET Core Web 应用部署到生产环境中。 1. 安装 .NET 运行时和 SDK 首先&#xff0c;确保 Linux 系统上…...

dubbo SPI插件扩展点使用

参考&#xff1a;SPI插件扩展点 Dubbo SPI概述 使用IoC容器帮助管理组件的生命周期、依赖关系注入等是很多开发框架的常用设计&#xff0c;Dubbo中内置了一个轻量版本的IoC容器&#xff0c;用来管理框架内部的插件&#xff0c;实现包括插件实例化、生命周期、依赖关系自动注入…...

P8512 [Ynoi Easy Round 2021] TEST_152 Solution

Description 有一序列 c ( c 1 , c 2 , ⋯ , c m ) c(c_1,c_2,\cdots,c_m) c(c1​,c2​,⋯,cm​) 和 n n n 个三元组 ( l i , r i , v i ) (l_i,r_i,v_i) (li​,ri​,vi​). 回答 q q q 次形如 ( L , R ) (L,R) (L,R) 的询问&#xff0c;具体如下&#xff1a; 将 c c …...

开源项目FastAPI-MCP:一键API转换MCP服务

在当今AI开发的世界中,应用程序与AI模型之间的无缝集成至关重要。 模型上下文协议(Model Context Protocol, MCP)通过允许AI模型访问外部工具和数据源,弥合了这一差距。 FastAPI MCP是一个强大的工具,它可以通过最少的配置将您现有的FastAPI端点转换为MCP兼容的工具。 本…...

8、constexpr if、inline、类模版参数推导、lambda的this捕获---c++17

一、constexpr if&#xff1a;编译时条件分支 作用&#xff1a;在模板编程中&#xff0c;根据条件在编译时选择不同的代码路径&#xff0c;无需特化版本或复杂SFINAE技巧[替代SFINAE]。[SFINAE将在模版元编程再讲。下个月了。]基本语法 if constexpr (condition) {// 如果 co…...

github新建一个远程仓库并添加了README.md,本地git仓库无法push

1.本地git仓库与远程仓库绑定 2.push时报错&#xff0c;本地的 main 分支落后于远程仓库的 main 分支&#xff08;即远程有更新&#xff0c;但你本地没有&#xff09;&#xff0c;需要拉取远程的仓库--->在merge合并&#xff08;解决冲突&#xff09;--->push 3.但是git …...

贝叶斯分类器:原理、算法与应用详解

内容摘要 本文聚焦贝叶斯分类器&#xff0c;介绍其在各类分类器中分类错误概率最小的特性。详细阐述贝叶斯分类器的基本原理、朴素贝叶斯和半朴素贝叶斯分类器的算法&#xff0c;结合西瓜数据集实例说明朴素贝叶斯的应用。此外&#xff0c;还深入探讨极大似然估计和贝叶斯估计…...

算法篇之单调栈

单调栈算法入门 单调栈是一种特殊的数据结构应用&#xff0c;它的核心在于维护一个栈&#xff0c;使得栈内元素保持单调递增或者单调递减的顺序。这种数据结构在解决很多算法问题时非常有效&#xff0c;例如求数组中每个元素的下一个更大元素、每日温度问题等。 一、单调栈的…...

用python + PIL 实现图片格式转换工具

用python PIL 实现图片格式转换工具 要运行该程序&#xff0c;需要使用第三方库PIL&#xff08;pillow&#xff09;&#xff0c;详情可见https://blog.csdn.net/cnds123/article/details/126141838 格式支持&#xff1a; 支持常见图片格式转换&#xff08;JPEG, PNG, BMP, GIF…...

【数据库】事务

目录 1. 什么是事务&#xff1f; 2. 事务的ACID特性 3. 为什么使用事务&#xff1f; 4. 如何使用事务 4.1 查看支持事务的存储引擎 4.2 语法 4.3 保存点 4.4 自动/手动提交事务 5. 事物的隔离性和隔离级别 5.1 什么是隔离性 5.2 隔离级别 5.3 查看和设置隔离级别 1…...

C++:详解命名空间

目录 前言 一、命名空间是什么&#xff1f; 1.1命名空间域的定义 二、为什么有命名空间&#xff1f; 三、命名空间的用法 总结 前言 主要讲解命名空间是什么&#xff1f;为什么有命名空间&#xff1f;以及它的用法 一、命名空间是什么&#xff1f; 命名空间域&#xff08;nam…...

ClickHouse核心架构设计

列式存储原理与数据压缩 列式存储原理 列式存储 vs 行式存储 特性行式存储&#xff08;如MySQL&#xff09;列式存储&#xff08;ClickHouse&#xff09;数据排列按行连续存储&#xff08;所有字段相邻&#xff09;按列连续存储&#xff08;单列数据紧密排列&#xff09;适用场…...

K8s-Pod详解

Pod介绍 Pod是Kubernetes中能够创建和部署的最小单元&#xff0c;是Kubernetes集群中的一个应用实例&#xff0c;总是部署在同一个节点Node上。&#xff08;程序运行部署在容器中&#xff0c;容器必须存在pod中。pod可以认为是容器的封装&#xff0c;一个pod中可以存在一个或者…...

SSM(SpringMVC+spring+mybatis)整合的步骤以及相关依赖

目录 &#xff08;一&#xff09;导入SSM框架相关的依赖 ①创建一个新的web工程&#xff08;idea2023版&#xff09; ②思考三者之间的联系&#xff0c;回忆依赖 ③在pom.xml文件中引入依赖坐标 &#xff08;二&#xff09;使用注解开发&#xff0c;编写Spring的配置类&am…...

【LeetCode】算法详解#5 ---轮转数组

1.题目介绍 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 1 < nums.length < 105-231 < nums[i] < 231 - 10 < k < 105 2.解决思路 这道题的解决方法有很多&#xff0c;我这里给大家介绍我使用的方法。…...

LeetCode 打家劫舍+删除并获得点数

题目描述 打家劫舍题目传送门1 删除并获得点数传送门2 思路 这两道题看似毫无关系&#xff0c;但竟然可以用桶数组联系起来&#xff01;&#xff01; 先说打家劫舍这道题 限制条件是不能走相邻的屋&#xff0c;再联想到跳台阶&#xff08;走一格或两格&#xff09;&#x…...

【计量地理学】实验四 主成分分析与莫兰指数

一、实验内容 &#xff08;一&#xff09; 某地区35个城市2004年的7项经济统计指标数据见&#xff08;数据中的“题目1”sheet&#xff09;。 &#xff08;1&#xff09;试用最短距离聚类法对35个城市综合实力进行系统聚类分析&#xff0c;并画出聚类谱系图: 在此次实验内容…...

TDengine 性能监控与调优实战指南(二)

四、TDengine 性能调优实战 4.1 硬件层面优化 硬件是 TDengine 运行的基础&#xff0c;其性能直接影响着 TDengine 的整体表现。在硬件层面进行优化&#xff0c;就如同为高楼大厦打下坚实的地基&#xff0c;能够为 TDengine 的高效运行提供有力支持。 CPU&#xff1a;CPU 作…...

Linux `init 5` 相关命令的完整使用指南

Linux init 5 相关命令的完整使用指南—目录 一、init 系统简介二、init 5 的含义与作用三、不同 Init 系统下的 init 5 行为1. SysVinit&#xff08;如 CentOS 6、Debian 7&#xff09;2. systemd&#xff08;如 CentOS 7、Ubuntu 16.04&#xff09;3. Upstart&#xff08;如 …...

uni-app中map的使用

uni-app中map的使用 一、基本使用步骤 1. 引入 map 组件 在 .vue 文件的 template 中直接使用 <map> 标签&#xff1a; <template><view><map :latitude"latitude" :longitude"longitude" :markers"markers" style&quo…...

备战2025年全国信息素养大赛图形化大赛——绘制雪花

以上题目点击下方地址&#xff0c;可查看答案或者在线编程&#xff5e; 绘制雪花_scratch_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/scratch/show-5775.html?_shareid3 程序演示可点击下方地址&#xff0c;支持源码和素材获取&#xff0c;方便高效&#xff…...

1Panel - 基于Web的Linux服务器管理工具

本文翻译整理自&#xff1a;https://github.com/1Panel-dev/1Panel 文章目录 一、关于 1Panel相关链接资源关键功能特性 二、安装系统要求安装脚本 三、基本使用&#xff08;快速开始&#xff09;1、快速安装2、访问面板 四、界面展示五、专业版六、安全信息感谢 一、关于 1Pan…...

基于SpringAI Alibaba实现RAG架构的深度解析与实践指南

一、RAG技术概述 1.1 什么是RAG技术 RAG&#xff08;Retrieval-Augmented Generation&#xff09;检索增强生成是一种将信息检索技术与生成式AI相结合的创新架构。它通过以下方式实现智能化内容生成&#xff1a; 知识检索阶段&#xff1a;从结构化/非结构化数据源中检索相关…...

SpringBoot Actuator指标收集:Micrometer与Prometheus集成

文章目录 引言一、Spring Boot Actuator基础二、Micrometer简介与集成三、基本指标收集与配置四、自定义业务指标实现五、与Prometheus集成六、实战案例&#xff1a;API性能监控总结 引言 在现代微服务架构中&#xff0c;监控应用程序的健康状况和性能指标变得至关重要。Sprin…...

Spring Boot 集成 Kafka 及实战技巧总结

Spring Boot 集成 Kafka 及实战技巧总结 一、Spring Boot 集成 Kafka 添加依赖 <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId> </dependency>配置 Kafka 在 application.yml 中配置生产…...

LeetCode hot 100—分割等和子集

题目 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以分割成 [1, 5, 5] 和 [11] 。…...

JUC复习及面试题学习

资源来自沉默王二、小林coding、竹子爱熊猫、代码随想录 一、JUC 1、进程与线程 进程是对运行程序的封装&#xff0c;是系统进行资源调度和分配的最小单位。 线程是进程的子任务&#xff0c;是CPU调度分配的基本单位 不同的进程之间很难数据共享&#xff0c;同进程下的不同线…...

The_Planets_Earth靶场笔记(VulnHub)

环境说明&#xff1a; kali地址&#xff1a;192.168.144.128 靶机地址&#xff1a;192.168.144.181 靶机网卡改为NAT模式。 靶机下载地址&#xff1a; https://download.vulnhub.com/theplanets/Earth.ova 一.信息收集&#xff1a; 1.主机探测&#xff1a; 使用如下命令…...

dawgctf 2025 writeup

dawgctf 2025 writeup 赛事信息pwnJust Parry Lol miscDont Touch My FoneThe BirdsMystery Signal IinternsProjectSuspicious scriptSpectral SecretsCaddyshack forensicsKeeping on ScheduleJust Packets CryptoCipher For Good osintEs ist alles in ButterLook Long and …...

机器学习(神经网络基础篇)——个人理解篇6(概念+代码)———参数优化篇

1 在声明一个类中&#xff0c;构建一个属于类的函数&#xff0c;前面为什要加上“self”&#xff1f; 就像下面这一串代码&#xff1a; class TwoLayerNet:def __init__(self, input_size, hidden_size, output_size,weight_init_std0.01):# 初始化权重self.params {}self.p…...

AI速读:解锁LLM下Game Agent的奇妙世界

在 AI 浪潮中&#xff0c;大语言模型&#xff08;LLMs&#xff09;正重塑游戏智能体格局。想知道基于 LLMs 的游戏智能体如何运作&#xff0c;在各类游戏中有何惊艳表现&#xff0c;未来又将走向何方&#xff1f; 大型语言模型&#xff08;LLMs&#xff09;的兴起为游戏智能体的…...

个人所得税

文章目录 一、名词解释二、个人所得税计算方法 (举例)1.累计预扣预缴应纳税所得额、本期应预扣预缴税额2.个人所得税预扣率表一3.个人所得税计算举例 三、专项附加扣除政策介绍四、年度汇算清缴政策介绍五、常见问答 一、名词解释 累计预扣法是指扣缴义务人在一个纳税年度内预…...

DEA-Net:基于细节增强卷积和内容引导注意力的单图像去雾

IEEE TIP 2024 | DEA-Net&#xff1a;基于细节增强卷积和内容引导注意力的单图像去雾 DEA-Net: Single image dehazing based on detail-enhanced convolution and content-guided attention paper name: DEA-Net: Single image dehazing based on detail-enhanced convolutio…...

StringEscapeUtils:给你的字符串穿上“防弹衣“——转义工具类深度解析

各位代码勇士们好&#xff01;今天我们要聊的是Apache Commons Lang3中的StringEscapeUtils工具类。如果说StringUtils是瑞士军刀&#xff0c;那StringEscapeUtils就是你的字符串保镖&#xff0c;专门负责在各种危险场合保护你的字符串安全&#xff01; 一、为什么需要字符串转…...

Sharding-JDBC 系列专题 - 第二篇:广播表(Broadcast Tables)

Sharding-JDBC 系列专题 - 第二篇:广播表(Broadcast Tables) 本系列专题旨在帮助开发者深入掌握 Sharding-JDBC,一个轻量级的分布式数据库中间件。本篇作为系列的第二篇文章,将详细讲解 广播表(Broadcast Tables) 的概念、配置、使用场景、工作原理以及实战案例。广播表…...

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类矩阵QRect)

文章目录 一、构造与初始化方法二、坐标与尺寸获取三、坐标与尺寸设置四、几何运算方法五、移动与调整方法六、状态判断方法七、类型转换方法八、操作符重载九、静态方法十、特殊方法附录方法速查表注意的问题交集和并集图解 &#x1f4d8; PySide6.QtCore.QRect 使用整数精度定…...