背景
有一个1300w的record.csv
文件,其内容示例如下,文件大小2G。csv文件用逗号分隔,第一部分是唯一id,第二部分是爬取地址。
recordid,entranceimage
adfa-20932-ada-daf1a,http://xxxxx
adfa-20932-ada-dafa2,http://xxxxx
需求:
- 单机爬取文件,具有容灾机制
- 性能要高,具有稳定性
- 部署使用起来要简单,遂不依赖mysql,mongodb等记录,纯文件
需求分解
- 要有容灾机制,遂使用status.txt记录上一次执行到record.csv文件多少行。方便服务重启后能继续上一次的记录跑。
- 要具有稳定性,不能跑不起来吧。单文件2G不能一次加载到内存中,遂采用nio按行(readLine)读取
record.csv
文件 - 性能要高 => 采用多线程工作。又因为容灾需要从上一次跑,遂不能丢失。采用生产者将Task放到线程池里,消费者
LinkedBlockingQueue<Future<T>>
用队列有序消费。记录日志和status.txt文件行。 - 稳定性高,减少项目GC次数,对于频繁创建对象,情况允许创建对象池。
- 爬取数据的结果是图片,直接存储到本地文件,遂采用
零拷贝
InputStream is2 = httpUrlConn.getInputStream();
Path target = Paths.get("",imageData.getPath());
Files.createDirectories(target.getParent());
Files.copy(is2, target, StandardCopyOption.REPLACE_EXISTING);
相关资料总结
优化方案