版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
java千萬(wàn)級(jí)別數(shù)據(jù)生成文件思路和優(yōu)化博客分類(lèi):
java大數(shù)據(jù)處理javajava大數(shù)據(jù)java數(shù)據(jù)處理千萬(wàn)級(jí)別數(shù)據(jù)
一年前寫(xiě)過(guò)一個(gè)百萬(wàn)級(jí)別數(shù)據(jù)庫(kù)數(shù)據(jù)生成配置xml文件的程序,程序目的是用來(lái)把數(shù)據(jù)庫(kù)里面的數(shù)據(jù)生成xml文件.程序可以配置多少文件生成到一個(gè)文件中去.
程序剛開(kāi)始設(shè)計(jì)的時(shí)候說(shuō)的是最多百萬(wàn)級(jí)別數(shù)據(jù),最多50W數(shù)據(jù)生成到一個(gè)xml文件里面去,所以在做測(cè)試的時(shí)候自己也只是造了100W的數(shù)據(jù)并沒(méi)有做過(guò)多數(shù)據(jù)量的測(cè)試,然后問(wèn)題就來(lái)了....由于程序使用的局點(diǎn)數(shù)據(jù)量巨大,需要生成xml文件的客戶(hù)資料接近千萬(wàn)級(jí)別的程度,而現(xiàn)場(chǎng)對(duì)程序的配置大約是100W條數(shù)據(jù)生成一個(gè)xml文件里面去,程序在這樣的大數(shù)據(jù)量下面偶爾會(huì)有崩潰.
最近幾天現(xiàn)場(chǎng)催的比較緊,最近抽空把這個(gè)問(wèn)題處理了一下,在解決問(wèn)題的過(guò)程中我把解決的步驟和方法記錄了下來(lái),正好和大家共享一下
現(xiàn)場(chǎng)提的問(wèn)題概況:
數(shù)據(jù)量:生成xml,每個(gè)文件100W+條的數(shù)據(jù)
內(nèi)存控制:最好不要超過(guò)512M
問(wèn)題詳情:在處理70W左右的時(shí)候內(nèi)存溢出一、先來(lái)看一下程序要生成的xml文件的結(jié)構(gòu)Xml代碼
<File>
<FileType>1</FileType>
<RType>12</RType>
<Version>03</Version>
<BNo>004</BNo>
<FileQ>5</FileQ>
<FNo>0006</FNo>
<RecordNum>1000000</RecordNum>
<!--
上面是文件頭
下面是百萬(wàn)個(gè)<RecordList>
-->
<RecordList>
<Msisdn>10350719507</Msisdn>
<State>1</State>
<StartDate>20110303</StartDate>
<Date>20110419</Date>
<Balance>45000</Balance>
</RecordList>
...
<!--
可能百萬(wàn)個(gè)
<RecordList>
塊-->
</File>
二、給大家說(shuō)一下如何把大數(shù)據(jù)生成xml文件
1、小數(shù)據(jù)量的情況下
<
1W條數(shù)據(jù)
比較好用的方法是使用開(kāi)源框架,比如XStream直接把javabean生成xml
優(yōu)點(diǎn):api操作簡(jiǎn)單,方便維護(hù)
缺點(diǎn):數(shù)據(jù)量大的情況下太消耗內(nèi)存
2、大數(shù)據(jù)量生成一個(gè)xml文件(本程序采用的方法)
自己做的一個(gè)可以使用極少的內(nèi)存生成無(wú)限制大的xml文件框架由3部分生成xml文件
第一部分:生成文件頭
例如:xxx.toXML(Objectobj,StringfileName)
第二部分:通過(guò)每次向文件里面追加3000(可配置)條數(shù)據(jù)的形式生成文件塊
5、專(zhuān)門(mén)把批處理代碼提取出來(lái)通過(guò)JProfile內(nèi)存分析.最終問(wèn)題定位完畢.
原因如下:100W數(shù)據(jù)生成一個(gè)文件的過(guò)程中,等文件生成完畢之后才能把數(shù)據(jù)庫(kù)中的數(shù)據(jù)備份到歷史表中,這個(gè)時(shí)候才能進(jìn)行事務(wù)的提交,也就是執(zhí)行commit(),并且刪除原表數(shù)據(jù),100W數(shù)據(jù)按照3000一批寫(xiě)入文件,每批次只是通過(guò)PreparedStatement.addBatch();加入到批次里面去,并沒(méi)有執(zhí)行PreparedStatement.executeBatch(),而是在commit()之前統(tǒng)一調(diào)用的PreparedStatement.executeBatch(),這樣的話(huà)PreparedStatement就會(huì)緩存100W條數(shù)據(jù)信息,造成了內(nèi)存溢出.錯(cuò)誤的方法如下:Java代碼
try{
conn.setAutoCommit(false);
pst
=
conn.prepareStatement(insertSql);
pstDel
=
conn.prepareStatement(delSql);
pstUpdate
=
conn.prepareStatement(sql);
...
//totalSize
=
100W數(shù)據(jù)
/
3000一批次
for
(int
i
=
1;
i
<=
totalSize;
i++)
{
client.appendXML(list);
}
//
錯(cuò)誤的使用方法
client.finishXML();
pst.executeBatch();
pstDel.executeBatch();
}
...
finally
{
try
{
if
(isError)
{
conn.rollback();
}
else
mit();
...
}
...
}
正確的方法如下
try{Java代碼
conn.setAutoCommit(false);
pst
=
conn.prepareStatement(insertSql);
pstDel
=
conn.prepareStatement(delSql);
pstUpdate
=
conn.prepareStatement(sql);
...
//totalSize
=
100W數(shù)據(jù)
/
3000一批次
for
(int
i
=
1;
i
<=
totalSize;
i++)
{
list
=
從數(shù)據(jù)庫(kù)中查詢(xún)3000條數(shù)據(jù)
client.appendXML(list);
pst.executeBatch();
pstDel.executeBatch();
}
client.finishXML();
...
inally
{
try
{
if
(isError)
{
conn.rollback();
}
else
mit();
...
}
...
如果碰到和我一樣的需要給大家一個(gè)提醒.
oracle在每次執(zhí)行executeBatch();進(jìn)行批處理的時(shí)候,當(dāng)前connection對(duì)應(yīng)的rownum會(huì)根據(jù)操作的結(jié)果發(fā)生變化.
在執(zhí)行pst.executeBatch();之后,當(dāng)前連接的rownum數(shù)就會(huì)發(fā)生變化.因此凡是通過(guò)rownum查詢(xún)數(shù)據(jù)的程序都要小心這一點(diǎn)java千萬(wàn)級(jí)別數(shù)據(jù)處理(2)-千萬(wàn)級(jí)別FTP下載博客分類(lèi):
Java開(kāi)發(fā)經(jīng)驗(yàn)javaFTP下載千萬(wàn)級(jí)別數(shù)據(jù)處理
這個(gè)也是以前做過(guò)的一個(gè)程序,目的主要是去ftp主機(jī)(最多100左右)去取xx數(shù)據(jù)文件.
千萬(wàn)級(jí)別只是個(gè)概念,代表數(shù)據(jù)量等于千萬(wàn)或者大于千萬(wàn)的數(shù)據(jù)
本分享不牽扯分布式采集存儲(chǔ)之類(lèi)的.是在一臺(tái)機(jī)器上處理數(shù)據(jù),如果數(shù)據(jù)量很大很大的話(huà),可以考慮分布式處理,如果以后我有這方面的經(jīng)驗(yàn),會(huì)及時(shí)分享的.1、程序采用的ftp工具,apache的commons-net-ftp-2.0.jar
2、千萬(wàn)級(jí)別ftp核心關(guān)鍵的部分--列目錄到文件,只要是這塊做好了,基本上性能就沒(méi)有太大的問(wèn)題了.
可以通過(guò)apache發(fā)送ftp命令"NLST"的方式列目錄到文件中去
#ftp列目錄執(zhí)行的命令以環(huán)境變量的配置優(yōu)先,不配置則使用默認(rèn)的列目錄方式NLSTJava代碼
#
DS_LIST_CMD
=
NLST
public
File
sendCommandAndListToFile(String
command,String
localPathName)
throws
IOException
{
try
{
return
client.createFile(command,
localPathName);
}
catch
(IOException
e)
{
log.error(e);
throw
new
IOException("the
command
"+command
+"
is
incorrect");
}
}
當(dāng)然應(yīng)該還有其他形式的,大家可以自己研究一下
十萬(wàn)級(jí)別以上的數(shù)據(jù)量的話(huà)千萬(wàn)不要使用下面這種方式,如果用的話(huà)====找死
FTPFile[]dirList=client.listFiles();
3、分批次從文件中讀取要下載的文件名.
加載到內(nèi)存中處理,或者讀取一個(gè)文件名就下載一個(gè)文件,不要把所有的數(shù)據(jù)都加載到內(nèi)存,如果很多的話(huà)會(huì)出問(wèn)題
為啥要分批次?
因?yàn)槭谴髷?shù)據(jù)量,如果有1000W條記錄,列出來(lái)的目錄文件的大小1G以上吧4、文件下載的核心代碼----關(guān)于文件的斷點(diǎn)續(xù)傳,獲得ftp文件的大小和本地文件的大小進(jìn)行判斷,然后使用ftp提供的斷點(diǎn)續(xù)傳功能
下載文件一定要使用二進(jìn)制的形式
client.enterLocalPassiveMode();//設(shè)置為被動(dòng)模式
ftpclient.binary();
//一定要使用二進(jìn)制模式
Java代碼
/**
下載所需的文件并支持?jǐn)帱c(diǎn)續(xù)傳,下載后刪除FTP文件,以免重復(fù)
*
@param
pathName
遠(yuǎn)程文件
*
@param
localPath
本地文件
*
@param
registerFileName
記錄本文件名稱(chēng)目錄
*
@param
size
上傳文件大小
*
@return
true
下載及刪除成功
*
@throws
IOException
*
@throws
Exception
*/
public
boolean
downLoad(String
pathName,
String
localPath)
throws
IOException
{
boolean
flag
=
false;
File
file
=
new
File(localPath+".tmp");//設(shè)置臨時(shí)文件
FileOutputStream
out
=
null;
try{
client.enterLocalPassiveMode();//
設(shè)置為被動(dòng)模式
client.setFileType(FTP.BINARY_FILE_TYPE);//設(shè)置為二進(jìn)制傳輸
if(lff.getIsFileExists(file)){//判斷本地文件是否存在,如果存在并且長(zhǎng)度小于FTP文件的長(zhǎng)度時(shí)斷點(diǎn)續(xù)傳;返之新增
long
size
=
this.getSize(pathName);
long
localFileSize
=
lff.getSize(file);
if(localFileSize
>
size){
return
false;
}
out
=
new
FileOutputStream(file,true);
client.setRestartOffset(localFileSize);
flag
=
client.retrieveFile(new
String(pathName.getBytes(),client.getControlEncoding()),out);
out.flush();
}
else{
out
=
new
FileOutputStream(file);
flag
=
client.retrieveFile(new
String(pathName.getBytes(),client.getControlEncoding()),out);
out.flush();
}
}catch(IOException
e){
log.error(e);
log.error("file
download
error
!");
throw
e;
}finally{
try{
if(null!=out)
out.close();
if(flag)
lff.rename(file,
localPath);
}catch(IOException
e){
throw
e;
}
}
return
flag;
}
/**
*
獲取文件長(zhǎng)度
*
@param
fileNamepath
本機(jī)文件
*
@return
*
@throws
IOException
*/
public
long
getSize(String
fileNamepath)
throws
IOException{
FTPFile
[]
ftp
=
client.listFiles(new
String(fileNamepath.getBytes(),client.getControlEncoding()));
return
ftp.length==0
?
0
:
ftp[0].getSize();
}
檢測(cè)本地文件是否已經(jīng)下載,如果下載文件的大小.
/**
*本地文件的
獲取文件的大小
*
@param
file
*
@return
*/
public
long
getSize(File
file){
long
size
=
0;
if(getIsFileExists(file)){
size
=
file.length();
}
return
size;
}
5、因?yàn)槌绦蛞茏疃?00多個(gè)線程,在線程監(jiān)控上做了一些處理,可以
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年南寧客運(yùn)從業(yè)資格證考試題目和答案圖片
- 2024年三亞駕駛員客運(yùn)從業(yè)資格證模擬考試題庫(kù)
- 2024年延安辦理客運(yùn)從業(yè)資格證理論考試題
- 2024年從業(yè)資格證考客運(yùn)
- 2024年濟(jì)南汽車(chē)駕駛員客運(yùn)資格證考試題及答案
- 智能教育機(jī)器人行業(yè)消費(fèi)者群體特征分析
- 區(qū)塊鏈醫(yī)療數(shù)據(jù)共享行業(yè)的消費(fèi)心理分析
- 育嬰員(五級(jí))考試題庫(kù)及答案
- 藝術(shù)品保險(xiǎn)行業(yè)的消費(fèi)心理分析
- 低碳汽車(chē)行業(yè)投資機(jī)會(huì)分析與策略研究報(bào)告
- 淺談在小學(xué)數(shù)學(xué)教學(xué)中如何培養(yǎng)學(xué)生的數(shù)學(xué)思維能力
- 名中醫(yī)醫(yī)案100例
- 消化道出血PPT優(yōu)秀課件
- 授 權(quán) 委 托 書(shū)天津北方網(wǎng)——權(quán)威媒體 天津門(mén)戶(hù)
- 消防中控室操作流程
- 《冠狀動(dòng)脈旁路移植術(shù)圍術(shù)期抗血小板治療專(zhuān)家共識(shí)》(2020)要點(diǎn)匯總
- 對(duì)提高初三年級(jí)教學(xué)質(zhì)量的幾點(diǎn)建議
- 臺(tái)燈設(shè)計(jì)方案
- 隨機(jī)波浪理論
- 祭母文農(nóng)村最好祭母文3篇
- 15_Oracle EBS 應(yīng)收模塊設(shè)置文檔
評(píng)論
0/150
提交評(píng)論