今天我收集了一份大概有40万行的日志,为了充分利用这份日志,我决定把日志给解析,解析完了之后,再写入mysql数据库。

首先,对于40万行的日志,肯定不能一次性读取到内存。

所以我用了NodeJs内置的readline模块。

  1. const readline = require('readline')
  2. let line_no = 0
  3. let rl = readline.createInterface({
  4. input: fs.createReadStream('./my.log')
  5. })
  6. rl.on('line', function(line) {
  7. line_no++;
  8. console.log(line)
  9. })
  10. // end
  11. rl.on('close', function(line) {
  12. console.log('Total lines : ' + line_no);
  13. })

数据解析以及写入到这块我没有贴代码。代码的执行是正常的,但是一段时间之后,程序就报错Out Of Memory。

代码执行是在nodejs 10.16.3上运行的,谷歌搜了一下解决方案,看到有人说nodejs升级到12.x版本就可以解决这个问题。我抱着试试看的想法,升级了nodejs到最新版,果然没有再出现OOM的问题。

后来我想,我终于深刻理解了NodeJS官网上的这篇文章 Backpressuring in Streams,以前我也度过几遍,但是不太了解,这次接合实际情况。有了深刻理解。

NodeJS在按行读取本地文件时,大概可以达到每秒1000行的速度,然而数据写入到MySql,大概每秒100次插入的样子。

本身网络上存在的延迟就要比读取本地磁盘要慢,读到太多的数据无法处理,只能暂时积压到内存中,然而内存有限,最终OOM的异常就抛出了。

NodeJS 12.x应该解决了这个问题。

参考