每天批次导入 100 万对账数据到 MySQL 时出现死锁

一、死锁原因及优化策略

1.1 死锁原因分析

  1. 批量插入事务过大
    • Spring Batch 默认将整个 chunk(批量数据块)作为一个事务提交,100 万数据可能导致事务过长,增加锁竞争。
  2. 并发写入冲突
    • 多个线程或批处理作业同时写入同一表,争夺行锁或表锁。
  3. 索引缺失或不当
    • 缺少主键或唯一索引,导致插入时全表扫描。
    • 索引过多导致更新锁冲突。
  4. 分库分表未优化
    • 单表数据量过大(如超过千万),查询和插入性能下降。
    • 分片键设计不合理,导致热点数据集中。
  5. 拒绝策略或线程池配置不当
    • 动态线程池(如 Dynamic TP)配置不当,导致任务积压或拒绝,间接增加事务等待时间。
  6. 事务隔离级别
    • MySQL 默认 REPEATABLE_READ 可能引发间隙锁,尤其在范围更新或插入时。

1.2 优化策略

  1. 分批提交
    • 将 100 万数据拆分为小批量(如每 1000 条一个事务),减少事务持有锁时间。
  2. 动态线程池优化
    • 使用动态线程池(如 Dynamic TP)控制并发,限制同时写入的线程数。
    • 配置合理的拒绝策略(如 CallerRunsPolicy)避免任务丢失。
  3. 分库分表
    • 使用 ShardingSphere 按对账 ID 或日期分片,分散数据压力。
    • 优化分片键,避免热点。
  4. 索引优化
    • 确保主键和必要索引存在,避免全表扫描。
    • 移除冗余索引,减少锁冲突。
  5. 事务隔离级别调整
    • 评估是否可降低为 READ_COMMITTED,减少间隙锁。
  6. 死锁检测与重试
    • 配置 MySQL 死锁检测(innodb_deadlock_detect)。
    • 在代码中实现重试机制。
  7. AOP 监控
    • 使用 AOP 记录批量导入性能和死锁异常,便于定位问题。
  8. 日志与监控
    • 集成 ActiveMQ 记录操作日志,Actuator 监控线程池和数据库性能。

二、在 Spring Boot 中实现优化方案

以下是在 Spring Boot 中实现批量导入 100 万对账数据的示例,使用 Spring BatchShardingSphere(分库分表)、Dynamic TP(动态线程池)、AOP 监控等,解决死锁问题。

2.1 环境搭建

2.1.1 配置步骤
  1. 创建 Spring Boot 项目

    • 使用 Spring Initializr 添加依赖:
      • spring-boot-starter-web
      • spring-boot-starter-data-jpa
      • mysql-connector-java
      • shardingsphere-jdbc-core
      • dynamic-tp-spring-boot-starter
      • spring-boot-starter-activemq
      • spring-boot-starter-batch
      • spring-boot-starter-aop
    <project><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version></parent><groupId>com.example</groupId><artifactId>batch-import-demo</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>5.4.0</version></dependency><dependency><groupId>cn.dynamictp</groupId><artifactId>dynamic-tp-spring-boot-starter</artifactId><version>1.1.5</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-batch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies>
    </project>
    
  2. 准备数据库

    • 创建两个 MySQL 数据库:recon_db_0recon_db_1
    • 每个数据库包含两个表:reconciliation_0reconciliation_1
    • 表结构:
      CREATE TABLE reconciliation_0 (id BIGINT PRIMARY KEY,account_id VARCHAR(50),amount DECIMAL(10,2),recon_date DATE,INDEX idx_account_id (account_id),INDEX idx_recon_date (recon_date)
      );
      CREATE TABLE reconciliation_1 (id BIGINT PRIMARY KEY,account_id VARCHAR(50),amount DECIMAL(10,2),recon_date DATE,INDEX idx_account_id (account_id),INDEX idx_recon_date (recon_date)
      );
      
  3. 配置 application.yml

    spring:profiles:active: devapplication:name: batch-import-demoshardingsphere:datasource:names: db0,db1db0:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/recon_db_0?useSSL=false&serverTimezone=UTCusername: rootpassword: rootdb1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/recon_db_1?useSSL=false&serverTimezone=UTCusername: rootpassword: rootrules:sharding:tables:reconciliation:actual-data-nodes: db${0..1}.reconciliation_${0..1}table-strategy:standard:sharding-column: idsharding-algorithm-name: recon-table-algodatabase-strategy:standard:sharding-column: idsharding-algorithm-name: recon-db-algosharding-algorithms:recon-table-algo:type: INLINEprops:algorithm-expression: reconciliation_${id % 2}recon-db-algo:type: INLINEprops:algorithm-expression: db${id % 2}props:sql-show: truejpa:hibernate:ddl-auto: noneshow-sql: truebatch:job:enabled: falseinitialize-schema: alwaysactivemq:broker-url: tcp://localhost:61616user: adminpassword: admin
    server:port: 8081
    management:endpoints:web:exposure:include: health,metrics,threadpool
    dynamic-tp:enabled: trueexecutors:- thread-pool-name: batchImportPoolcore-pool-size: 4max-pool-size: 8queue-capacity: 1000queue-type: LinkedBlockingQueuerejected-handler-type: CallerRunsPolicykeep-alive-time: 60thread-name-prefix: batch-import-
    logging:level:root: INFOcom.example.demo: DEBUG
    
  4. MySQL 配置

    • 确保死锁检测启用:
      SET GLOBAL innodb_deadlock_detect = ON;
      
    • 调整事务隔离级别(可选):
      SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
      
2.1.2 原理
  • ShardingSphere:按 ID 哈希分片,分散数据到 db0.reconciliation_0, db0.reconciliation_1, db1.reconciliation_0, db1.reconciliation_1
  • Dynamic TP:控制批量导入的并发线程数,优化资源利用。
  • Spring Batch:分 chunk 处理数据,减少事务大小。
  • AOP:监控导入性能和死锁。
2.1.3 优点
  • 分库分表降低单表压力。
  • 动态线程池优化并发。
  • 小批量事务减少锁竞争。
2.1.4 缺点
  • 配置复杂,需熟悉 ShardingSphere 和 Dynamic TP。
  • 跨库事务需额外支持。
  • 死锁监控增加少量开销。
2.1.5 适用场景
  • 高并发批量数据导入。
  • 大数据量对账系统。
  • 微服务数据库优化。

2.2 实现批量导入

实现 100 万对账数据的批量导入,优化死锁问题。

2.2.1 配置步骤
  1. 实体类Reconciliation.java):

    package com.example.demo.entity;import jakarta.persistence.Entity;
    import jakarta.persistence.Id;
    import java.math.BigDecimal;
    import java.time.LocalDate;@Entity
    public class Reconciliation {@Idprivate Long id;private String accountId;private BigDecimal amount;private LocalDate reconDate;// Getters and Setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getAccountId() { return accountId; }public void setAccountId(String accountId) { this.accountId = accountId; }public BigDecimal getAmount() { return amount; }public void setAmount(BigDecimal amount) { this.amount = amount; }public LocalDate getReconDate() { return reconDate; }public void setReconDate(LocalDate reconDate) { this.reconDate = reconDate; }
    }
    
  2. RepositoryReconciliationRepository.java):

    package com.example.demo.repository;import com.example.demo.entity.Reconciliation;
    import org.springframework.data.jpa.repository.JpaRepository;public interface ReconciliationRepository extends JpaRepository<Reconciliation, Long> {
    }
    
  3. 服务层ReconciliationService.java):

    package com.example.demo.service;import com.example.demo.entity.Reconciliation;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.JobParametersBuilder;
    import org.springframework.batch.core.launch.JobLauncher;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.util.JdbcUtils;
    import org.springframework.stereotype.Service;import java.sql.SQLException;@Service
    public class ReconciliationService {private static final Logger logger = LoggerFactory.getLogger(ReconciliationService.class);private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();@Autowiredprivate JobLauncher jobLauncher;@Autowiredprivate Job importReconJob;public void startImportJob() {try {CONTEXT.set("Import-" + Thread.currentThread().getName());logger.info("Starting batch import job");JobParametersBuilder params = new JobParametersBuilder().addLong("timestamp", System.currentTimeMillis());jobLauncher.run(importReconJob, params.build());} catch (Exception e) {logger.error("Failed to start import job", e);} finally {CONTEXT.remove();}}public void retryOnDeadlock(Runnable task, int maxRetries) {int retries = 0;while (retries < maxRetries) {try {task.run();return;} catch (Exception e) {if (isDeadlock(e)) {retries++;logger.warn("Deadlock detected, retrying {}/{}", retries, maxRetries);try {Thread.sleep(100 * retries); // 指数退避} catch (InterruptedException ie) {Thread.currentThread().interrupt();}} else {throw e;}}}throw new RuntimeException("Max retries reached for deadlock");}private boolean isDeadlock(Exception e) {return e.getCause() instanceof SQLException &&((SQLException) e.getCause()).getErrorCode() == 1213;}
    }
    
  4. Spring Batch 配置BatchConfig.java):

    package com.example.demo.config;import com.example.demo.entity.Reconciliation;
    import org.dynamictp.core.DtpRegistry;
    import org.dynamictp.core.executor.DtpExecutor;
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.Step;
    import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
    import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
    import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
    import org.springframework.batch.item.ItemProcessor;
    import org.springframework.batch.item.ItemReader;
    import org.springframework.batch.item.ItemWriter;
    import org.springframework.batch.item.database.JpaItemWriter;
    import org.springframework.batch.item.support.ListItemReader;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import jakarta.persistence.EntityManagerFactory;
    import java.math.BigDecimal;
    import java.time.LocalDate;
    import java.util.ArrayList;
    import java.util.List;@Configuration
    @EnableBatchProcessing
    public class BatchConfig {@Autowiredprivate JobBuilderFactory jobBuilderFactory;@Autowiredprivate StepBuilderFactory stepBuilderFactory;@Autowiredprivate EntityManagerFactory entityManagerFactory;@Beanpublic ItemReader<Reconciliation> reader() {// 模拟 100 万数据List<Reconciliation> data = new ArrayList<>();for (long i = 1; i <= 1_000_000; i++) {Reconciliation recon = new Reconciliation();recon.setId(i);recon.setAccountId("ACC" + i);recon.setAmount(new BigDecimal("100.00"));recon.setReconDate(LocalDate.now());data.add(recon);}return new ListItemReader<>(data);}@Beanpublic ItemProcessor<Reconciliation, Reconciliation> processor() {return item -> {// 简单处理return item;};}@Beanpublic ItemWriter<Reconciliation> writer() {JpaItemWriter<Reconciliation> writer = new JpaItemWriter<>();writer.setEntityManagerFactory(entityManagerFactory);return writer;}@Beanpublic Step importReconStep() {DtpExecutor executor = DtpRegistry.getExecutor("batchImportPool");return stepBuilderFactory.get("importReconStep").<Reconciliation, Reconciliation>chunk(1000) // 小批量提交.reader(reader()).processor(processor()).writer(writer()).taskExecutor(executor).throttleLimit(4) // 限制并发.build();}@Beanpublic Job importReconJob() {return jobBuilderFactory.get("importReconJob").start(importReconStep()).build();}
    }
    
  5. 控制器ReconController.java):

    package com.example.demo.controller;import com.example.demo.service.ReconciliationService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;@RestController
    public class ReconController {@Autowiredprivate ReconciliationService reconciliationService;@PostMapping("/import")public String startImport() {reconciliationService.startImportJob();return "Batch import started";}
    }
    
  6. AOP 切面BatchMonitoringAspect.java):

    package com.example.demo.aspect;import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;@Aspect
    @Component
    public class BatchMonitoringAspect {private static final Logger logger = LoggerFactory.getLogger(BatchMonitoringAspect.class);@Pointcut("execution(* com.example.demo.service.ReconciliationService.*(..))")public void serviceMethods() {}@Before("serviceMethods()")public void logMethodEntry() {logger.info("Entering batch service method");}@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")public void logException(Exception ex) {logger.error("Batch error: {}", ex.getMessage());}
    }
    
  7. 死锁重试机制(已集成在 ReconciliationService)。

  8. 运行并验证

    • 启动 MySQL 和 ActiveMQ。
    • 启动应用:mvn spring-boot:run
    • 触发导入:
      curl -X POST http://localhost:8081/import
      
      • 确认数据分片存储到 recon_db_0.reconciliation_0, recon_db_0.reconciliation_1, 等。
      • 检查 ActiveMQ 日志。
      • 访问 /actuator/threadpool 监控线程池状态。
    • 检查 MySQL 死锁日志:
      SHOW ENGINE INNODB STATUS;
      
2.2.2 原理
  • 分库分表:ShardingSphere 按 ID 哈希分片,分散锁竞争。
  • 小批量事务:Spring Batch 每 1000 条提交一次,减少锁时间。
  • 动态线程池:Dynamic TP 限制并发(4 个线程),避免过多事务。
  • 死lock 重试:检测死锁(MySQL 错误码 1213),自动重试。
  • AOP:记录性能和异常,便于定位。
2.2.3 优点
  • 显著降低死锁概率。
  • 高性能导入(100 万数据约 5-10 分钟)。
  • 动态调整线程池,优化资源。
2.2.4 缺点
  • 配置复杂,需熟悉 Spring Batch 和 ShardingSphere。
  • 重试机制可能增加延迟。
  • 分片查询需优化。
2.2.5 适用场景
  • 大数据量批量导入。
  • 高并发对账系统。
  • 分布式数据库优化。

2.3 集成先前查询

结合分页、Swagger、ActiveMQ、Spring Profiles、Spring Security、FreeMarker、热加载、ThreadLocal、Actuator 安全性、CSRF、WebSockets、异常处理、Web 标准、AOP、动态线程池、分库分表。

2.3.1 配置步骤
  1. 分页与排序

    • 添加分页查询:
      @Service
      public class ReconciliationService {@Autowiredprivate ReconciliationRepository reconciliationRepository;public Page<Reconciliation> searchRecon(String accountId, int page, int size, String sortBy, String direction) {try {CONTEXT.set("Query-" + Thread.currentThread().getName());Sort sort = Sort.by(Sort.Direction.fromString(direction), sortBy);PageRequest pageable = PageRequest.of(page, size, sort);return reconciliationRepository.findAll(pageable); // 简化示例} finally {CONTEXT.remove();}}
      }
      
  2. Swagger

    • 添加 Swagger 文档:
      @RestController
      @Tag(name = "对账管理", description = "对账数据导入和查询")
      public class ReconController {@Operation(summary = "触发批量导入")@PostMapping("/import")public String startImport() {reconciliationService.startImportJob();return "Batch import started";}@Operation(summary = "分页查询对账数据")@GetMapping("/reconciliations")public Page<Reconciliation> searchRecon(@RequestParam(defaultValue = "") String accountId,@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size,@RequestParam(defaultValue = "id") String sortBy,@RequestParam(defaultValue = "asc") String direction) {return reconciliationService.searchRecon(accountId, page, size, sortBy, direction);}
      }
      
  3. ActiveMQ

    • 已记录导入日志。
  4. Spring Profiles

    • 配置 application-dev.ymlapplication-prod.yml
      # application-dev.yml
      spring:shardingsphere:props:sql-show: truedynamic-tp:executors:- thread-pool-name: batchImportPoolcore-pool-size: 4max-pool-size: 8queue-capacity: 1000
      logging:level:root: DEBUG
      
      # application-prod.yml
      spring:shardingsphere:props:sql-show: falsedynamic-tp:executors:- thread-pool-name: batchImportPoolcore-pool-size: 8max-pool-size: 16queue-capacity: 2000
      logging:level:root: INFO
      
  5. Spring Security

    • 保护 API:
      @Configuration
      public class SecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(auth -> auth.requestMatchers("/import", "/reconciliations").authenticated().requestMatchers("/actuator/health").permitAll().requestMatchers("/actuator/**").hasRole("ADMIN").anyRequest().permitAll()).httpBasic().and().csrf().ignoringRequestMatchers("/ws");return http.build();}@Beanpublic UserDetailsService userDetailsService() {var user = User.withDefaultPasswordEncoder().username("admin").password("admin").roles("ADMIN").build();return new InMemoryUserDetailsManager(user);}
      }
      
  6. FreeMarker

    • 对账管理页面:
      @Controller
      public class WebController {@Autowiredprivate ReconciliationService reconciliationService;@GetMapping("/web/reconciliations")public String getReconciliations(@RequestParam(defaultValue = "") String accountId,@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size,Model model) {Page<Reconciliation> reconPage = reconciliationService.searchRecon(accountId, page, size, "id", "asc");model.addAttribute("reconciliations", reconPage.getContent());return "reconciliations";}
      }
      
      <!-- src/main/resources/templates/reconciliations.ftl -->
      <!DOCTYPE html>
      <html lang="zh-CN">
      <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>对账管理</title>
      </head>
      <body><h1>对账数据</h1><table><tr><th>ID</th><th>账户ID</th><th>金额</th><th>日期</th></tr><#list reconciliations as recon><tr><td>${recon.id}</td><td>${recon.accountId?html}</td><td>${recon.amount}</td><td>${recon.reconDate}</td></tr></#list></table>
      </body>
      </html>
      
  7. 热加载

    • 已启用 DevTools。
  8. ThreadLocal

    • 已清理 ThreadLocal(见 ReconciliationService)。
  9. Actuator 安全性

    • 已限制 /actuator/**
  10. CSRF

    • WebSocket 端点禁用 CSRF。
  11. WebSockets

    • 实时推送导入状态:
      @Controller
      public class WebSocketController {@Autowiredprivate SimpMessagingTemplate messagingTemplate;@MessageMapping("/import-status")public void sendImportStatus() {messagingTemplate.convertAndSend("/topic/import", "Batch import running");}
      }
      
  12. 异常处理

    • 处理死锁异常(已集成重试机制)。
  13. Web 标准

    • FreeMarker 模板遵循语义化 HTML。
  14. 动态线程池

    • 已使用 Dynamic TP 优化并发。
  15. 分库分表

    • 已集成 ShardingSphere。
  16. 运行并验证

    • 开发环境
      java -jar demo.jar --spring.profiles.active=dev
      
      • 触发导入,验证无死锁。
      • 检查分片表数据分布。
      • 监控 /actuator/threadpool 和 WebSocket 推送。
    • 生产环境
      java -jar demo.jar --spring.profiles.active=prod
      
      • 确认安全性、线程池配置。
2.3.2 原理
  • 分页:ShardingSphere 聚合跨库结果。
  • Swagger:文档化导入 API。
  • ActiveMQ:异步记录日志。
  • Profiles:控制线程池和日志级别。
  • Security:保护导入操作。
  • Batch:小批量事务降低死锁。
  • FreeMarker:渲染查询结果。
  • WebSockets:推送导入状态。
2.3.3 优点
  • 高效导入,消除死锁。
  • 集成 Spring Boot 生态。
  • 动态优化性能。
2.3.4 缺点
  • 配置复杂,需多组件协调。
  • 跨库查询需优化。
  • 重试增加少量延迟。
2.3.5 适用场景
  • 高并发批处理。
  • 大数据量对账。
  • 分布式系统优化。

三、性能与适用性分析

3.1 性能影响

  • 批量导入:100 万数据约 5-10 分钟(4 线程,1000 条/chunk)。
  • 死锁重试:每次重试增加 100-300ms。
  • 查询:50ms(1000 条,跨库)。
  • WebSocket 推送:2ms/消息。

3.2 性能测试

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BatchImportTest {@Autowiredprivate TestRestTemplate restTemplate;@Testpublic void testImportPerformance() {long startTime = System.currentTimeMillis();restTemplate.postForEntity("/import", null, String.class);long duration = System.currentTimeMillis() - startTime;System.out.println("Batch import: " + duration + " ms");}
}

测试结果(Java 17,8 核 CPU,16GB 内存):

  • 导入:约 300,000ms(100 万数据)。
  • 重试:0-3 次/导入。
  • 查询:50ms。

结论:优化后死锁显著减少,性能稳定。

3.3 适用性对比

方法死锁概率性能适用场景
单事务导入小数据量
分批+分库分表大数据量、高并发
云数据库云原生应用

四、常见问题与解决方案

  1. 问题1:死锁仍发生

    • 场景:高并发下死锁频繁。
    • 解决方案
      • 进一步降低 chunk 大小(如 500)。
      • 减少线程数(如 2)。
  2. 问题2:导入性能慢

    • 场景:100 万数据耗时过长。
    • 解决方案
      • 增加分片库/表数量。
      • 优化索引,移除冗余。
  3. 问题3:ThreadLocal 泄漏

    • 场景/actuator/threaddump 显示泄漏。
    • 解决方案
      • 确认 ThreadLocal 清理。
  4. 问题4:跨库查询慢

    • 场景:分页查询性能低。
    • 解决方案
      • 添加缓存(如 Redis)。
      • 优化分片键。

五、总结

通过分库分表(ShardingSphere)、小批量事务(Spring Batch)、动态线程池(Dynamic TP)和死锁重试机制,显著降低了批量导入 100 万对账数据的死锁问题。示例集成分页、Swagger、ActiveMQ、Profiles、Security、FreeMarker、WebSockets、AOP 等,性能稳定(5-10 分钟导入)。针对您的查询(ThreadLocal、Actuator、热加载、CSRF),通过清理、Security 和 DevTools 解决。

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

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

相关文章

DeepResearch深度搜索实现方法调研

DeepResearch深度搜索实现方法调研 Deep Research 有三个核心能力 能力一&#xff1a;自主规划解决问题的搜索路径&#xff08;生成子问题&#xff0c;queries&#xff0c;检索&#xff09;能力二&#xff1a;在探索路径时动态调整搜索方向&#xff08;刘亦菲最好的一部电影是…

跟我学C++中级篇——STL容器的查找对比

一、C标准库的查找 在C的STL中&#xff0c;对容器或相关序列的查找中&#xff0c;有两种方式&#xff0c;一种是std::find&#xff0c;另外一种是std::search。而且在它们的基础上&#xff0c;还衍生出std::find_if、std::find_if_not、std::find_end等和std::search_n、range…

SpringAI框架中的RAG知识库检索与增强生成模型详解

SpringAI框架中的RAG知识库检索与增强生成模型详解 一、RAG简介 RAG&#xff08;Retrieval-Augmented Generation&#xff09;可以通过检索知识库&#xff0c;克服大模型训练完成后参数冻结的局限性&#xff0c;携带知识让大模型根据知识进行回答。 二、SpringAI框架支持的R…

Delphi12安装Android开发的配置

Delphi12如果要开发android和Linux系统,需要在安装的时候安装这两个选项,否则,就找不到开发平台。 1、Adroid开发三剑客必须是指: JDK,SDK,NDK三洋,其中JDK是必须要安装的,最好使用Installer安装,否则自解压的免安装版在安装过程中会退出。 2、开始安装Delphi12. …

OpenHarmony launcher开发——删除dock栏

开发环境 OpenHarmony 5.0.0 代码修改 效果

FreeRTOS如何实现100%的硬实时性?

实时系统在嵌入式应用中至关重要&#xff0c;其核心在于确保任务在指定时间内完成。根据截止时间满足的严格程度&#xff0c;实时系统分为硬实时和软实时。硬实时系统要求任务100%满足截止时间&#xff0c;否则可能导致灾难性后果&#xff0c;例如汽车安全系统或医疗设备。软实…

微软推动智能体协同运作:支持 A2A、MCP 协议

今日凌晨&#xff0c;微软宣布 Azure AI Foundry 和 Microsoft Copilot Studio 两大开发平台支持最新 Agent 开发协议 A2A&#xff0c;并与谷歌合作开发扩大该协议&#xff0c;这一举措对智能体赛道意义重大。 现状与变革意义 当前智能体领域类似战国时代&#xff0c;各家技术…

从“山谷论坛”看AI七剑下天山

始于2023年的美国山谷论坛(Hill and Valley Forum)峰会,以“国会山与硅谷”命名,寓意连接科技界与国家安全战略。以人工智能为代表的高科技,在逆全球化时代已成为大国的致胜高点。 论坛创办者Jacob Helberg,现在是华府的副国务卿,具体负责经济、环境和能源事务。早先曾任…

Docker封装深度学习模型

1.安装Docker Desktop 从官网下载DockerDesktop&#xff0c;安装。&#xff08;默认安装位置在C盘&#xff0c;可进行修改&#xff09; "D:\Program Files (x86)\Docker\Docker Desktop Installer.exe" install --installation-dir"D:\Program Files (x86)\Do…

Linux 内核中的 security_sk_free:安全模块与 Socket 释放机制解析

引言 在 Linux 内核中,网络通信和进程间交互(IPC)的核心数据结构之一是 struct sock(即 socket)。其生命周期管理涉及复杂的资源分配与释放逻辑。本文聚焦于 security_sk_free 这一函数,探讨其作用、调用场景以及与安全模块的交互机制,并解答一个常见疑问:在单机间 TC…

工业与协议融合篇:如何将多个协议集成进一个系统?

🏭 本文为《嵌入式通信协议全解析》第六篇,深入探讨如何在工业或物联网系统中同时集成 BLE、CAN、LoRa、MQTT、RS485 等多种通信协议,实现一个高效、可控、稳定运行的嵌入式通信架构。 🧭 一、为什么需要多协议融合? 在真实产品中,单一通信协议往往无法满足所有业务需…

手撕红黑树的 左旋 与 右旋

一、为什么需要旋转&#xff1f; 在红黑树中&#xff0c;插入或删除节点可能会破坏其五条性质&#xff0c;比如高度不平衡或连续红节点。 为了恢复红黑性质&#xff0c;我们采用局部旋转来“调整树形结构”&#xff0c;保持平衡。 二、旋转本质是“局部变形” 左旋和右旋不会…

不用官方EDA怎么开发FPGA?

目前FPGA的开发和官方的EDA工具是高度绑定的&#xff0c;用哪家的芯片只能用其配套的EDA工具进行开发&#xff08;综合可选工具&#xff0c;布局布线没有可选的工具&#xff09;&#xff0c;那么有没有其他的开发方式呢&#xff1f;今天就介绍一个使用开源工具链来开发FPGA的方…

QuecPython+Aws:快速连接亚马逊 IoT 平台

提供一个可接入亚马逊 Iot 平台的客户端&#xff0c;用于管理亚马逊 MQTT 连接和影子设备。 初始化客户端 Aws class Aws(client_id,server,port,keep_alive,ssl,ssl_params)参数&#xff1a; client_id (str) - 客户端唯一标识。server (str) - 亚马逊 Iot 平台服务器地址…

44.辐射发射整改简易摸底测试方法

辐射发射整改简易摸底测试方法 1. 正式摸底预测试2. 简易方法预测试3. 分析频谱4. 探查传播路径5. 施加措施6. 与简易方法预测试效果对比 1. 正式摸底预测试 去正式实验室做一次预测试&#xff0c;取得频谱图&#xff1b;确定超标频点和超标量&#xff08;备用&#xff09;。 …

OpenCV中适用华为昇腾(Ascend)后端的逐元素操作(Per-element Operations)

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 针对华为昇腾&#xff08;Ascend&#xff09;后端的逐元素操作&#xff08;Per-element Operations&#xff09;&#xff0c;这些操作通常用于图…

Web前端VSCode如何解决打开html页面中文乱码的问题(方法2)

Web前端—VSCode如何解决打开html页面中文乱码的问题&#xff08;方法2&#xff09; 1.打开VScode后&#xff0c;依次点击 文件 >> 首选项 >> 设置 2.打开设置后&#xff0c;依次点击 文本编辑器 >> 文件&#xff08;或在搜索框直接搜索“files.autoGuessEnc…

【UltralyticsYolo11图像分类完整项目-04】代码重构

经过上一篇博客,我们实现 了一个cpp文件,可以预测单个图像和多个图像。为了更加简化代码,方便部署,我们需要对代码进行重构:将功能模块化到头文件中。 完整代码下载链接:点击这里 重构的优点 模块化设计:将不同功能分离到不同的类中,每个类有明确的职责更好的可维护性:…

Debezium RelationalSnapshotChangeEventSource详解

Debezium RelationalSnapshotChangeEventSource详解 1. 类的作用与功能 1.1 核心功能 RelationalSnapshotChangeEventSource是Debezium中用于关系型数据库快照的核心抽象类,主要负责: 数据快照:对数据库表进行全量数据快照模式捕获:捕获数据库表结构事务管理:确保快照过…

DeepInjectSQL - 基于 AI 生成对抗网络(GAN)的下一代 SQL 注入自动化漏洞猎手

概述 SQLMap本身是一个成熟的自动化SQL注入工具&#xff0c;可以与GAN结合起来&#xff0c;让GAN生成的Payload替代传统的手工或规则生成的测试用例&#xff0c;从而提高检测的覆盖率和效率。 分析可行性 GAN通常用于生成类似真实数据分布的数据&#xff0c;例如图片、文本等。…