大数据实战

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/keep_moving_cqu/article/details/22689015

需求:现有一个1000万行数据的日志文件,每行数据用TAB来分割,它们是userId,gameId,gameScore(用户ID,游戏ID(1--10),该用户在该游戏的这次得分),当数据库中的数据出现丢失,现在要根据该日志文件的记录来恢复数据库中的数据,也就是将该日志中的数据插入到数据库中。数据库中有四个字段:userId,gameId,maxScore,times,这个times是该玩家玩这个游戏的次数,maxScore是玩这个游戏的最高分。

数据库采用分库分表方式,4个表,在两个数据库中,DB1(Table0,Table1),DB2(Table3,Table3)。表单元为:500万(Table0存放userId在0---500万的用户数据,Table1存放userId在500w---1000w的用户数据.....

解决方案一:

定义一个hashmap,用来存放要插入到数据库中的数据。HashMap<Key,Value> hashmap;Key类的字段:userId,gameId;Value类的字段:maxScore,times;

接下来就是读取日志文件,对每行进行处理:

如果hashmap中有该gameId和userId,那么根据该行的gameScore和maxScore进行比较,来更新maxScore,同时times++;

否则:hashmap.put(key,value);

最后得到一个统计所有数据的hashmap,再把数据批量插入到数据库中。

这是基本思路,但是这样好吗?1000万行数据啊。。且不说爆不爆内存,速度也是非常慢的,也许你会说hashmap不是查找很快么,但是存在hash冲突啊。1000万行数据要冲突多少次,每个链表 有多长啊!!查找还会快么。

解决方案二:

将所有数据映射到4*10=40个文件中,4为表数,10个gameId的数量。1_1,1_2.....1_10,.......4_10;

读取日志文件String line=reader.readline();

对每行数据进行处理:String[] infos=line.split(" ");info[0]-->userId,info[1]-->gameId,info[2]-->gameScore。

userId为n,gameId为m,那么映射的文件为:n/5000000_m。这样就把数据放入到40个文件中了。

开始读取文件:进行解决方案一的处理。每个文件生成一个hashmap。再将hashmap批量插入数据库中。然后读取下一个文件,依次这么处理。。。

每个hashmap也就是平均存放25万行数据。爆不了内存,同时查找速度也不慢。经测试,到了200多万时会变得特别慢。

现在功能是完成了,但是你会发现当所有数据插入到数据库需要1个多小时,我的是每个文件2分钟多。这是一个相当漫长的等待。。。呜呜呜。。。

优化:对于mysql数据库,采用批量插入的同时设置:rewriteBatchedStatements=true。现在7秒一个文件。整个处理过程在4分钟之内就完成了。

代码就不上传。。


展开阅读全文

没有更多推荐了,返回首页