




已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
java千萬級別數據生成文件思路和優(yōu)化博客分類: java大數據處理javajava大數據java數據處理千萬級別數據 一年前寫過一個百萬級別數據庫數據生成配置xml文件的程序,程序目的是用來把數據庫里面的數據生成xml文件.程序可以配置多少文件生成到一個文件中去. 程序剛開始設計的時候說的是最多百萬級別數據,最多50W數據生成到一個xml文件里面去,所以在做測試的時候自己也只是造了100W的數據并沒有做過多數據量的測試,然后問題就來了.由于程序使用的局點數據量巨大,需要生成xml文件的客戶資料接近千萬級別的程度,而現場對程序的配置大約是100W條數據生成一個xml文件里面去,程序在這樣的大數據量下面偶爾會有崩潰. 最近幾天現場催的比較緊,最近抽空把這個問題處理了一下,在解決問題的過程中我把解決的步驟和方法記錄了下來,正好和大家共享一下現場提的問題概況: 數據量:生成xml,每個文件100W+ 條的數據 內存控制:最好不要超過512M 問題詳情:在處理70W左右的時候內存溢出一、先來看一下程序要生成的xml文件的結構Xml代碼1. 2. 13. 124. 035. 0046. 57. 00068. 10000009. !-上面是文件頭下面是百萬個-10. 11. 1035071950712. 113. 2011030314. 2011041915. 4500016. 17. .!-可能百萬個塊-18. 二、給大家說一下如何把大數據生成xml文件 1、小數據量的情況下 1W條數據 比較好用的方法是使用開源框架,比如XStream 直接把javabean 生成 xml 優(yōu)點:api操作簡單,方便維護 缺點:數據量大的情況下太消耗內存 2、大數據量生成一個xml文件(本程序采用的方法) 自己做的一個可以使用極少的內存生成無限制大的xml文件框架由3部分生成xml文件 第一部分:生成文件頭 例如: xxx.toXML(Object obj, String fileName) 第二部分:通過每次向文件里面追加3000(可配置)條數據的形式生成文件塊 例如:xxx.appendXML(Object object); /object 可以是ArrayList 或者一個單獨的javaBean 第三部分:生成xml文件尾巴 例如:xxx.finishXML(); 程序中的調用:調用xxx.toXML(Object obj, String fileName) 生成文件頭之后,可以循環(huán)從數據庫中讀取數據生成ArrayList,通過xxx.appendXML(Object object) 方法追加到xml文件里面,xxx.finishXML() 對文件進行收尾 對框架說明:我上面提供的例子有文件頭 + 文件塊 + 文件尾巴. 如果和你們的實際使用文件不太一致的話,可以參考上面提供的思路修改一下即可,主要的方法是把相同的文件塊部分分離出來通過追加的形式寫入xml文件. 有了思路之后,大家可以嘗試著自己寫一個類似的大數據處理框架(千萬級別以上),如何有什么需要幫助的可以直接聯系我,因為是公司的程序,不太敢放出來,怕. 三、我是如何測試性能和優(yōu)化的 1、手動排除 根據文件崩潰時候的日志發(fā)現是在生成xml的框架里面報的錯誤,第一想到的是框架有些資源沒有釋放.于是把自己做的文件生成框架整體的排查了一遍,并且自己寫個簡單程序生成200萬條數據,使用xml框架生成一個xml文件,整個生成過程中任務管理器(xp)查看程序對應的java進程使用的內存基本在20M左右,因此排除框架的問題.懷疑是數據庫查詢和調用框架的部門出現問題. 檢測了一遍主程序的關鍵部分代碼,優(yōu)化了一下字符串處理.手動的釋放一些對象的內存(例如:調用ArrayList.clear(),或者把對象置空等),分配512內存后運行程序,60萬數據的時候內存溢出,因為能主動釋放的對象都已經釋放掉了,還是沒有解決,果斷放棄看代碼,準備使用JProfile進行內存檢測. 2、手動排除沒有解決,借助內存分析工具JProfile進行排除 通過在數據庫中生成300W條數據,在JProfile上面多跑程序,一邊運行,一邊調用JProfile 提供的執(zhí)行GC按鈕主動運行垃圾回收,運行50W數據后,通過檢測中發(fā)現 java.long.String 和 oracle.jdbc.driver.Binder 兩個對象的數目一直保持在自增狀態(tài),而且數目基本上差不多,對象數目 都在200W以上,由于java.long.String對象是需要依賴對象而存在的,因此斷定問題就出在oracle.jdbc.driver.Binder上面,由于改對象存在引用導致String不能正?;厥? 3、通過在JProfile對象查看對象的管理 檢測到oracle.jdbc.driver.Binder 被 oracle.jdbc.driver.T4CPreparedStatement 引起,而T4CPreparedStatement正好是Oracle對jdbc OraclePreparedStatement的具體實現,因此斷定是在數據庫處理方面出現的問題導致oracle.jdbc.driver.Binder對象不能正常釋放,通過再一次有目的的檢測代碼,排查jdbc數據查詢的問題,把問題的矛頭直至數據庫的批處理和事務處理.因此程序是每生成一個文件成功后,會把已經處理的數據轉移到對應的歷史表中進行備份,而再個表操作的過程中使用了批處理和事務,使用批處理主要是保證執(zhí)行速度,使用事務主要是保證同時成功和失敗。 4、又因此程序每次從數據庫中查詢3000條數據處理,所以準備監(jiān)控oracle.jdbc.driver.Binder的對象數目是否和查詢次數對應.,通過在程序中Sysout輸出查詢次數 + JProfile運行GC測試 Binder,數據匹配,證實是java在數據庫批處理的過程中有些問題. 5、專門把批處理代碼提取出來通過JProfile內存分析.最終問題定位完畢. 原因如下:100W數據生成一個文件的過程中,等文件生成完畢之后才能把數據庫中的數據備份到歷史表中,這個時候才能進行事務的提交,也就是執(zhí)行commit(), 并且刪除原表數據,100W數據按照3000一批寫入文件,每批次只是通過 PreparedStatement.addBatch();加入到批次里面去,并沒有執(zhí)行PreparedStatement.executeBatch(),而是在commit()之前統(tǒng)一調用的PreparedStatement.executeBatch(),這樣的話PreparedStatement就會緩存100W條數據信息,造成了內存溢出.錯誤的方法如下:Java代碼1. try2. conn.setAutoCommit(false);3. pst=conn.prepareStatement(insertSql);4. pstDel=conn.prepareStatement(delSql);5. pstUpdate=conn.prepareStatement(sql);6. .7. /totalSize=100W數據/3000一批次8. for(inti=1;i=totalSize;i+)9. 10. client.appendXML(list);11. 12. 13. /錯誤的使用方法14. client.finishXML();15. pst.executeBatch();16. pstDel.executeBatch();17. 18. .19. finally20. try21. if(isError)22. conn.rollback();23. 24. else25. mit();26. .27. 28. .29. 正確的方法如下 tryJava代碼1. conn.setAutoCommit(false);2. pst=conn.prepareStatement(insertSql);3. pstDel=conn.prepareStatement(delSql);4. pstUpdate=conn.prepareStatement(sql);5. .6. /totalSize=100W數據/3000一批次7. for(inti=1;isize)21. returnfalse;22. 23. out=newFileOutputStream(file,true);24. client.setRestartOffset(localFileSize);25. flag=client.retrieveFile(newString(pathName.getBytes(),client.getControlEncoding(),out);26. 27. out.flush();28. else29. out=newFileOutputStream(file);30. flag=client.retrieveFile(newString(pathName.getBytes(),client.getControlEncoding(),out);31. 32. out.flush();33. 34. 35. catch(IOExceptione)36. log.error(e);37. log.error(filedownloaderror!);38. throwe;39. finally40. try41. if(null!=out)42. out.close();43. if(flag)44. lff.rename(file,localPath);45. catch(IOExceptione)46. throwe;47. 48. 49. returnflag;50. 51. /*52. *獲取文件長度53. *paramfileNamepath本機文件54. *return55. *throwsIOException56. */57. publiclonggetSize(StringfileNamepath)throwsIOException58. FTPFileftp=client.listFiles(newString(fileNamepath.getBytes(),client.getControlEncoding();59. returnftp.length=0?0:ftp0.getSize();60. 61. 62. 檢測本地文件是否已經下載,如果下載文件的大小.63. 64. /*65. *本地文件的獲取文件的大小66. *paramfile67. *return68. */69. publiclonggetSize(Filefile)70. longsize=0;71. if(getIsFileExists(file)72. size=file.length();73. 74. returnsize;75. 5、因為程序要跑最多100多個線程,在線程監(jiān)控上做了一些處理,可以檢測那些死掉的線程,并及時的拉起來。 t.setUncaughtExceptionHandler(new ThreadException(exList);原理:給每個線程添加 UncaughtExceptionHandler,死掉的時候把線程對應的信息加入到一個list里面,然后讓主線程每隔一段時間掃描一下list,如果有數據,直接重新建一個線程運行即可6、如果程序是常駐內存的話,別忘記了在finally中關閉掉 不用的ftp連接7、做大數據庫采集程序必須考慮到的一件事情 磁盤空間已滿的處理 java虛擬機對于磁盤空間已滿,在英文環(huán)境下的 linux aix 機器上 一般報 There is not enough space in the file system 中文環(huán)境下 一般報 磁盤空間已滿 大家可以使用下面的代碼進行驗證 Java代碼1. /檢測磁盤控件是否已滿的異常Java代碼1. /
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件設計師核心概念梳理試題及答案
- 2024年蘭州市榆中縣中醫(yī)醫(yī)院招聘筆試真題
- 2024年安徽省市場監(jiān)管局下屬事業(yè)單位真題
- 游戲行業(yè)會計個人工作計劃
- 江蘇省常州市鐘樓區(qū)二十四中學2025年七年級數學第二學期期末質量跟蹤監(jiān)視試題含解析
- 保安工作總結計劃廣告宣傳行業(yè)保安工作的廣告位保護
- 2024年濱州市環(huán)境衛(wèi)生清運大隊招聘筆試真題
- 教育在幼兒園的實踐計劃
- 風險管理體系中的評估方法試題及答案
- 四川省成都市龍泉驛區(qū)2025年七下數學期末教學質量檢測試題含解析
- 運輸供應商年度評價表
- 2023年海南省財金集團有限公司招聘筆試題庫及答案解析
- 信息系統(tǒng)項目管理師論文8篇
- 北京中考英語詞匯表(1600詞匯)
- 超市消防監(jiān)控系統(tǒng)設計
- 封樣管理規(guī)定
- 黃腐酸鉀項目可行性研究報告-用于立項備案
- 管理人員責任追究制度
- 自動旋轉門PLC控制
- 電影場記表(雙機位)
- 畢設高密電法探測及數據處理解釋
評論
0/150
提交評論