java海量数据的简单清洗

这周接到了一个对爬取数据进行清理的任务,具体需求为,有一张接近百万的key值表,每一个key对应一个对象,但是在es中存在大量的相似对象,需要按照相似度清除key值表中重复的对象。

下面简单的介绍一下本人的思路。

文件准备

因为百万级数据的清理在单机模式下其实是很耗时的操作,所以我们需要考虑到一些异常的发生,并且要暂存一下重复的key值,所以需要构建三个临时文件

touch out.json set.json error.json

分别代表输出文件,key值暂存文件,以及错误文件

重试机制的简单实现

有时调用es进行查询会出现超时的情况,为了防止服务的直接停止,我们需要捕获异常进行处理。

对于重试,思路如下:

catch (Exception e) {
    // 重试超过三次后退出并写入错误文件中
    if (map.getOrDefault(key, 0) >= 3) {
    FileWriter fw2 = new FileWriter(errorFile, true);
    fw2.write("\"" + key + "\"" + ",");
    fw2.close();
    continue;
    }
    log.warn("error!", e);
    // 当失败时放入队列头部
    list.addFirst(key);
    map.put(key,map.getOrDefault(key, 0) + 1);
    }

我们使用一个map来统计当前key的失败次数,进入异常后判断一下当前失败次数,当超过3次后,写入错误文件,并跳到下一个key,未达到三次时,放入队列头部,下次继续重试

开始清洗

首先将数据读取到队列中

String content = FileUtils.readFileToString(file, "UTF-8");
// 提取json的values
JSONObject jsonObject = JSONObject.fromObject(content);
LinkedList list = new LinkedList<>(jsonObject.values());

然后通过当前key去es中查找唯一的对象,再通过对象值去查找与之相似的key,存入set中。

删除队列中存在的相似key

list.removeAll(set);

最好统计一下当前运行的进度,比如每一千个输出一次

if (count % 1000 == 0) {
    // 已清洗数据量
    log.info("count: " + count);
    // 已删除数据量
    log.info("cleanCount: " + cleanCount);
    FileWriter fw1 = new FileWriter(setFile, true);
    fw1.write("\"" + count + "\":" + "\"" + cleanCount + "\"" + ",");
    fw1.close();
}

今天的介绍就到这里了,如有问题,请联系博主

付出不到,就不要想着收获

你可能感兴趣的:(java海量数据的简单清洗)