每天批次導入 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.pswp.cn/bicheng/80373.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80373.shtml
英文地址,請注明出處:http://en.pswp.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;例如圖片、文本等。…