场景:文件过大,包含上百万条数据,甚至峰值能达近千万,文件过大,处理起来很慢。
解决思路:切割文件,多线程处理小文件。
方案:(java伪代码)
1、文件切割
//现根据切割后的文件前缀删除历史切割文件
String rmFileCmd = "rm" + filePath + fileNamePrefix + "-rf";
//java代码执行linux命令
Runtime.getRuntime().exec(rmFileCmd );
//睡眠等待删除临时文件完成(具体睡眠时间可以根据执行的效率改变设置)
Thread.sleep(10000);
//按照设置的行数进行切割
String splitFileCmd = "split -l" + splitLineNum + " " + originFile + " -d -a 5 " + filePath + fileNamePrefix;
//java代码执行linux命令
Runtime.getRuntime().exec(splitFileCmd);
//睡眠等待文件切割命令执行完成
Thread.sleep(10000);
//将切割后的目录下的文件,用前缀筛选后返回文件名称集合
List<String> fileNameList = new ArrayList<String>();
File[] fileParts = new File(filePath).listFiles();
if(fileParts.length > 0){
for(File filePart : fileParts){
if(filePart.isFile()){
String filePartName = filePart.getName();
String filePartPath = filePart.getPath();
File partFile = new File(path);
if(partFile.exists()){
if(filePartName.startsWith(fileNamePrefix)){
if(!fileNameList.contains(path)){
fileNameList.add(filePartPath);
}
}
}
}
}
}
2、多线程处理文件(主要是读取文件后入库)
//线程计数器,采用的是CountDownLatch
CountDownLatch latch = new CountDownLatch(fileNameList.size());
for(String fileName : fileNameList){
threadExecutor.execute( new Runnable(){
@Override
public void run(){
//处理单个文件
method(fileName);
//执行完后,调用countDownLatch减一
latch.countDown();
}
});
}
//等待所有线程执行完
latch.await();