大數據量返回方案(非分頁)

一、普通方式返回100萬條數據

@RestController
@RequestMapping("/bad")
public class BadController {@Autowiredprivate UserRepository userRepository;/*** 危險!一次性加載 100 萬條到內存*/@GetMapping("/all-users")public List<User> getAllUsers() {// 問題1:把100萬條數據全查出來,加載到JVM堆內存List<User> users = userRepository.findAll(); // 問題2:序列化成JSON時還要再占一份內存return users; // 結果:可能占用 500MB~1GB 內存,多個請求就OOM!}
}

問題分析
1.內存爆炸(OutOfMemoryError)
2.接口超時(30s+)
3.數據庫壓力大
4.客戶端卡死


二、流式查詢:逐條處理(推薦用于導出、批處理)

核心思想:從數據庫讀取時不把所有數據加載到內存,而是"一條一條"地讀取和處理。

流式查詢(如 MyBatis + JDBC 流式)本質上是阻塞式的,但它可以避免內存溢出(OOM),卻仍然可能遇到連接或請求超時。

使用 MyBatis 流式查詢

// Mapper 接口
@Mapper
public interface UserMapper {@Select("SELECT id, name, age, email FROM user ORDER BY id")void streamAllUsers(ResultHandler<User> handler);
}
// Controller
@RestController
@RequestMapping("/streaming")
public class StreamingController {@Autowiredprivate UserMapper userMapper;/*** 流式返回:逐條寫入響應流,內存占用極低*/@GetMapping(value = "/users.csv", produces = "text/csv;charset=UTF-8")public void streamUsersAsCsv(HttpServletResponse response) throws IOException {response.setContentType("text/csv");response.setCharacterEncoding("UTF-8");response.setHeader("Content-Disposition", "attachment; filename=users.csv");PrintWriter writer = response.getWriter();// 寫入CSV頭writer.println("id,name,age,email");// 流式處理:每讀到一條,就寫入一次userMapper.streamAllUsers(resultContext -> {User user = resultContext.getResultObject();writer.printf("%d,%s,%d,%s%n", user.getId(), escapeCsv(user.getName()), user.getAge(), user.getEmail());writer.flush(); // 強制推送});}private String escapeCsv(String value) {if (value == null) return "";return value.replace("\"", "\"\"");}
}

優點
1.內存只保留當前一條數據
2.使用 Transfer-Encoding: chunked 分塊傳輸
3.適合導出 CSV、Excel 等大文件


三、響應式流:Reactive Stream(推薦用于高并發 API)

技術棧:Spring WebFlux、Spring Data R2DBC(響應式數據庫驅動)、Project Reactor

// Repository
@Repository
public interface UserReactiveRepository extends ReactiveCrudRepository<User, Long> {Flux<User> findAll(); // 返回響應式流
}
// Service
@Service
public class UserReactiveService {@Autowiredprivate UserReactiveRepository userRepository;public Flux<User> getAllUsers() {return userRepository.findAll();}
}
// Controller
@RestController
@RequestMapping("/reactive")
public class ReactiveController {@Autowiredprivate UserReactiveService userService;/*** ? 響應式流:非阻塞、背壓控制、持續推送*/@GetMapping(value = "/users", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<User> streamUsers() {// 返回 Flux<User>,Spring WebFlux 會自動流式推送return userService.getAllUsers();// 客戶端會一條一條收到數據}
}

配置 application.yml

spring:r2dbc:url: r2dbc:postgresql://localhost:5432/mydbusername: userpassword: pass

前端

// 使用 EventSource(SSE)
const eventSource = new EventSource('/reactive/users');eventSource.onmessage = (event) => {const user = JSON.parse(event.data);console.log('收到用戶:', user);// 可以實時顯示在頁面上
};eventSource.onerror = () => {eventSource.close();
};

優點
1.非阻塞 I/O,高并發
2.背壓(Backpressure)機制,客戶端慢?服務端自動減速
3.實時性好,適合“直播式”數據推送

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93081.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93081.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93081.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Casbin的微服務細粒度權限控制方案對比與實踐

基于Casbin的微服務細粒度權限控制方案對比與實踐 隨著微服務架構在互聯網和企業級應用中的廣泛應用&#xff0c;服務間的安全邊界愈發重要。傳統的集中式權限控制方式已難以滿足微服務的高并發、動態擴展和多語言支持等需求。本文將從主流的三種微服務權限控制方案入手&#x…

5G毫米波現狀概述(截止2025 年7月)

5G毫米波現狀概述(截止2025 年7月&#xff09; 原創 modem協議筆記 2025年07月25日 06:01 廣東 聽全文 當你在體育館看球賽時&#xff0c;想發段實時視頻到朋友圈卻總卡成PPT&#xff1b;當郊區的父母抱怨“光纖拉不到家&#xff0c;網速比蝸牛慢”—這些場景背后&#xff…

thymeleaf 日期格式化顯示

在Thymeleaf中處理日期格式化顯示主要有以下幾種方式&#xff1a; 1. 使用#dates.format()方法進行基礎格式化&#xff1a; <p th:text"${#dates.format(dateObj, yyyy-MM-dd HH:mm:ss)}"></p>這種方法支持自定義格式模式&#xff0c;如yyyy表示年份、MM…

【經驗分享】如何在Vscode的Jupyter Notebook中設置默認顯示行號

【經驗分享】如何在Vscode的Jupyter Notebook中設置默認顯示行號 打開設置&#xff0c;搜索&#xff1a;Notebook: Line Number&#xff0c;然后把這個設置為on

藍橋杯STL stack

STL stack 概述棧&#xff08;stack&#xff09;是一種遵循**后進先出&#xff08;LIFO&#xff09;**原則的線性數據結構&#xff0c;僅允許在棧頂進行插入和刪除操作。STL&#xff08;Standard Template Library&#xff09;中的 stack 是一個容器適配器&#xff0c;基于其他…

從0到1:飛算JavaAI如何用AI魔法重構MCP服務全生命周期?

摘要 本文詳細介紹了如何利用飛算JavaAI技術實現MCP&#xff08;Model Context Protocol&#xff09;服務的創建及通過的全過程。首先闡述了飛算JavaAI的基本概念、特點和優勢&#xff0c;接著對MCP服務的需求進行分析&#xff0c;然后按照軟件開發流程&#xff0c;從系統設計、…

Webpack Loader 完全指南:從原理到配置的深度解析

掌握 Webpack Loader 的核心機制&#xff0c;解鎖前端工程化進階技能前言&#xff1a;為什么需要理解 Loader&#xff1f; 在現代前端工程化體系中&#xff0c;Webpack 已成為構建工具的事實標準。然而面對非標準 JavaScript 文件或自定義語法時&#xff0c;你是否遇到過 Modul…

讀書筆記:《我看見的世界》

《我看見的世界.李飛飛自傳》李飛飛 著&#xff0c;趙燦 譯個人理解&#xff1a; 是本自傳&#xff0c;也是AI的發展史 堅持&#xff0c;總會轉機&#xff0c;“一不小心”也許就成了算法、大規模數據、原始算力人工智能似乎一夜之間從一個小眾的學術領域爆發成為推動全球變革的…

使用純NumPy實現回歸任務:深入理解機器學習本質

在深度學習框架普及的今天&#xff0c;回歸基礎用NumPy從頭實現機器學習模型具有特殊意義。本文將完整演示如何用純NumPy實現二次函數回歸任務&#xff0c;揭示機器學習底層原理。整個過程不使用任何深度學習框架&#xff0c;每一行代碼都透明可見。1. 環境配置與數據生成 impo…

java理解

springboot 打包 mvn install:install-file -Dfile=<path-to-jar> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=jar <path-to-jar> 是你的 JAR 文件的路徑。 <group-id> 是你的項目的組 ID。 <…

圖論核心算法詳解:從存儲結構到最短路徑(附C++實現)

目錄 一、圖的基礎概念與術語 二、圖的存儲結構 1. 鄰接矩陣 實現思路&#xff1a; 2. 鄰接表 實現思路&#xff1a; 應用場景&#xff1a; 時間復雜度分析&#xff1a; 三、圖的遍歷算法 1. 廣度優先搜索&#xff08;BFS&#xff09; 核心思想&#xff1a; 應用場…

力扣top100(day03-02)--圖論

本文為力扣TOP100刷題筆記 筆者根據數據結構理論加上最近刷題整理了一套 數據結構理論加常用方法以下為該文章&#xff1a; 力扣外傳之數據結構&#xff08;一篇文章搞定數據結構&#xff09; 200. 島嶼數量 class Solution {// DFS輔助方法&#xff0c;用于標記和"淹沒&q…

建造者模式:從“參數地獄”到優雅構建

深夜&#xff0c;一條緊急告警刺穿寂靜&#xff1a;核心報表服務因NullPointerException全線崩潰。排查根源&#xff0c;罪魁禍首竟是一個擁有10多個參數的“上帝構造函數”。本文將從這個災難現場出發&#xff0c;引入“鏈式建造者模式”進行重構&#xff0c;并深入Spring AI、…

jenkins在windows配置sshpass

我的服務器里jenkins是通過docker安裝的&#xff0c;jenkins與項目都部署在同一臺服務器上還好&#xff0c;但是當需要通過jenkins構建&#xff0c;再通過scp遠程推送到別的服務器上&#xff0c;就出問題了&#xff0c;畢竟不是手動執行scp命令&#xff0c;可以手動輸入密碼&am…

Linux操作系統從入門到實戰(十八)在Linux里面怎么查看進程

Linux操作系統從入門到實戰&#xff08;十八&#xff09;在Linux里面怎么查看進程前言一、如何識別一個進程&#xff1f;—— PID二、怎么查看進程的信息&#xff1f;方式1&#xff1a;通過/proc目錄方式2&#xff1a;用ps命令三、父進程是什么&#xff1f;—— PPID四、bash是…

[TryHackMe](知識學習)---基于堆棧得到緩沖區溢出

1.了解緩沖區溢出WINDOWS程序動態調試工具immunity debuggerhttps://www.immunityinc.com/products/debugger/2.Mona腳本#!/usr/bin/env python3import socket, time, sysip "10.201.99.37"port 1337 timeout 5 prefix "OVERFLOW1 "string prefix &q…

LRU算法與LFU算法

知識點&#xff1a; LRU是Least Recently Used的縮寫&#xff0c;意思是最近最少使用&#xff0c;它是一種Cache替換算法 Cache的容量有限&#xff0c;因此當Cache的容量用完后&#xff0c;而又有新的內容需要添加進來時&#xff0c; 就需要挑選 并舍棄原有的部分內容&#xf…

目標檢測公開數據集全解析:從經典到前沿

目標檢測公開數據集全解析&#xff1a;從經典到前沿 一、引言 目標檢測&#xff08;Object Detection&#xff09;是計算機視覺領域的核心任務之一&#xff0c;旨在在圖像或視頻中識別并定位感興趣的物體。與圖像分類不同&#xff0c;目標檢測不僅需要判斷物體的類別&#xf…

數據備份與進程管理

一、數據備份1.Linux服務器中需要備份的數據&#xff08;1&#xff09;Linux系統重要數據&#xff1a;/root/目錄&#xff0c;/home/目錄&#xff0c;/etc/目錄&#xff08;2&#xff09;安裝服務的數據&#xff1a;Apache&#xff08;配置文件&#xff0c;網頁主目錄&#xff…

docker volume卷入門教程

1. 基礎概念 Docker卷是專門用于持久化容器數據的存儲方案&#xff0c;獨立于容器生命周期。其核心優勢包括&#xff1a; 數據持久化&#xff1a;容器刪除后數據仍保留跨容器共享&#xff1a;多個容器可訪問同一卷備份與遷移&#xff1a;支持直接復制卷數據驅動支持&#xff1a…