最近提交了一個專利,是基於去年做的一個異步數據導出的項目,平穩支撐了16/17年的雙十一,抽時間把其中的細節分享出來
- 背景
數據導出excel的傳統方法一般都是先將數據生成到內存中,然后利用excel的一些工具類生成excel文件通過http請求或者ftp返回給用戶。但是在數據量很大或者並發量很高的場景中,往往會導致內存飆高或者頻繁的FullGC,嚴重時會導致宕機。如果分批進行導出則導出數據量的大小與用戶等待時間成正比,用戶體驗較差。
我們的初衷就是要解決數據導出造成的內存溢出。本文將介紹一種分布式的分片數據導出方法,解決了系統的內存壓力,能支撐大數據量及高並發的數據導出,具有較高的效率及擴展性。
- 現有方案比較
- 方案一:在一台機器中,一個請求使用多個線程進行導出,最終生成excel文件,提高數據導出的效率
- 方案二:將用戶的查詢語句分成多個可執行語句,進行分批導出,同時數據是分批發送給用戶
方案分析
第一種方案中,雖然使用了多線程進行導出,但是數據最終還是需要在內存中轉換生成excel文件,這樣不能真正解決內存壓力問題。
第二種方案中,雖然解決了大數據量的內存問題,但是數據是分批輸送給用戶的,體驗較差,同時不能解決高並發的問題,具有局限性。
同時,現有的方案中,一般都是在一台機器上進行分批導出,本質上都用增加導出時間的方式來緩解內存壓力,是一種用時間換空間的方式。用戶需要等待較長的時間,體驗較差。
- 方案細節
我們同樣也是基於分治的思想,但是采用了分布式的解決方案,將一個大數據的導出分片並分成多個子任務在不同的機器上進行導出,並且數據存儲為csv格式文件,可以以追加的方式進行存儲
希望達到的技術效果:
- 解決單點導出的內存壓力
- 提高導出效率,用戶不用等待太久
- 具有較高的擴展性,可以不斷地提高導出的並發度及數據量
方案實現
一方面,數據量很大的情況下,不能將數據全部緩存在內存中,需要分片進行導出;另一方面並發量很大時,一台機器也不能滿足需求,需要在分布式環境下分散每台機器的壓力,這樣就擁有了良好的擴展性。
這種分片及分布式的數據導出方法,用於解決大數據量或高並發場景下數據導出問題,能夠減輕系統內存壓力,同時具有良好的擴展性。
總體流程如下:

- 第一步:用戶向業務系統發出導出http請求;
- 第二步:業務系統向導出系統發起一個數據導出的RPC調用;
- 第三步:導出系統從各種存儲系統(例如數據庫、搜索等)中分片獲取數據;
- 第四步:多台機器分片獲取到的數據分別上傳到文件存儲系統中進行組合;
- 第五步:在文件系統中組合成csv文件;
- 第六步:用戶從文件系統中下載文件;
分布式分片導出方法:

說明
- 首先主任務將數據分片,每個分片是一個子任務;
- 將所有子任務分發到不同的機器去並行執行,每台機器可以限制並行的子任務數量,來保證內存壓力在可空范圍。
- 當每台機器的子任務都達到閾值上限之后就會將任務緩存在主任務的阻塞隊列中,直到所有任務分發完畢。
- 每個子任務拼裝當前需要處理的數據,我們並不關心數據從哪里獲取,可以從DB、搜索、Hbase等存儲獲取,同時可以在子任務中處理業務邏輯。然后將處理完的數據上傳至文件存儲系統中。
- 當所有子任務執行完畢之后主任務會向文件存儲系統發送請求,將所有的分片合並成csv文件。此時主任務會更新任務狀態並獲取到文件下載鏈接。
- 總結
這種數據導出架構的核心思想有4個:
- 數據導出異步化,先用時間換空間
- 一個高並發及大數據量場景下的導出可以分而治之,分散內存壓力
- 子任務(數據分片)分發到不同的機器,一方面分布式環境下均衡內存壓力,另一方面用空間換時間
- 導出的數據文件可追加,基於流式化的導出
