天天看点

基于三千万行数据统计的效率比较

   先说一下场景,日志文件中有大约三千万行数据,大小为1.2G,格式为IP,TIME,现在要针对IP字段进行数量统计重复的次数,以便制定规则来控制用户的恶意注册。

关于如何读取,并统计这三千万的数据,有三个思路:

第一个:使用JAVA的BufferedReader,分批读取数据,然后再利用map统计结果。

第二个:使用JAVA的BufferedReader,分批读取数据,然后把结果直接存入到redis的sorted set中。

第三个:多线程环境下,结合第二个思路。

第一个思路,执行不到三分钟,内存已经溢出。

第二个思路,一秒钟大约能存入到redis中1667条数据,速度还不错,一小时能统计600万左右,但要统计完成,大约需要5个小时,考虑到数据越多,读写Redis的速度就越慢,估计要6个小时左右。

第三个思路,由于redis是单线程工作,此次又全部是写入的工作,所以多线程对性能提高的能力有限,如果是有读有写,可利用Redis的主从模式,写主库,读从库,多线程也能提高效率。

三个思路都行不通,最终向一个刚来加班的大牛请教,结果利用linux命令行,15分钟统计完成。于是,我就有了时间写下这篇文章,记录一下。下面附上第二个思路的JAVA实现,以及请教大牛后的linux命令行实现。

shell版【15分钟统计完成】

date

cat regIp.txt | awk -F'\t' '{ print $1}' | sort | uniq -c | sort -rn | head -n100

date

JAVA版本【6小时统计完成】:

import java.io.BufferedInputStream;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Date;

import redis.clients.jedis.Jedis;

public class ReadLogFile {

private static Jedis jedis;

static {

jedis = new Jedis("192.168.1.100");

   jedis.connect();

   jedis.auth("redisPwd#");

   jedis.select(10);

}

public static void main(String[] args) throws IOException {

readFile();

}

private static void readFile() throws IOException {

long start = System.currentTimeMillis();

System.out.println(new Date());

String fileName = "log.txt";

File file = new File(fileName);    

BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));

BufferedReader reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),100*1024*1024);// 用100M的缓冲读取文本文件   

String keyTotal = "ipInfo";

String line = ""; 

while((line = reader.readLine()) != null){ 

if(line.indexOf("state") >=0){

continue;

}

String[] arrs = line.split("\t");

if(arrs == null || arrs.length != 2){

continue;

}

jedis.zincrby(keyTotal, 1, arrs[0]);

}

long cost = (System.currentTimeMillis() - start);

System.out.println("cost = " + cost + "ms, means " + (cost/1000.0) + " s");

if(reader != null){

reader.close();

}

}

}

继续阅读