Spark下生成2000w测试数据(每条记录150列)

使用spark生成大量数据过程中遇到问题,如果sc.parallelize(fukeData, 64);的记录数特别大比如500w,1000w时,会特别慢,而且会抛出内存溢出over head错误。解决方案,一次生成的数据量不高于100w,多次调用,这样下来一共生成2000w耗时十几分钟。

如果环境允许你可以在本地生成测试数据,然后上传到hdfs供spark测试。

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random; public class FileGenerate {
public static void main(String[] args) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("d://test.csv")); List<String> fukeData = new ArrayList<String>();
for (int i = 1; i <= 20000000; i++) {
fukeData.add(String.valueOf(i));
} List<String> fields = new ArrayList<String>(); fields.add("id");//
fields.add("object_id"); //
fields.add("scan_start_time"); //
fields.add("scan_stop_time");//
fields.add("insert_time");//
fields.add("enodeb_id");
for (int i = 0; i < 145; i++) {
fields.add("mr_tadv_" + (i < 10 ? "0" + i : i));
}
writer.write(String.join(",", fields) + "\r\n"); // 假设有1w个小区,数据一共200w条记录,那么每个小区有200条记录。
Random random = new Random();
for (String id : fukeData) {
List<String> rowItems = new ArrayList<String>();
// id
int intId = Integer.valueOf(id);
rowItems.add(id);
if (intId % 100000 == 0) {
System.out.println(intId);
writer.flush();
}
// object_id
String objectId = String.valueOf((intId % 10000) + 10000 * 256 + 1);
rowItems.add(objectId); int hour = random.nextInt(5) + 2;
int minute = random.nextInt(59) + 1;
int second_start = random.nextInt(30) + 1;
int second_stop = second_start + 15;
String scan_start_time = "2018-10-29 1" + hour + ":" + minute + ":" + second_start;
String scan_stop_time = "2018-10-29 1" + hour + ":" + minute + ":" + second_stop;
// scan_start_time
rowItems.add(scan_start_time);
// scan_stop_time
rowItems.add(scan_stop_time); // insert_time
rowItems.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); // enodeb_id
rowItems.add(String.valueOf((int) Integer.valueOf(objectId) / 256)); for (int i = 0; i < 145; i++) {
rowItems.add(String.valueOf(random.nextInt(100)));
} writer.write(String.join(",", rowItems) + "\r\n");
} writer.flush();
writer.close();
}
}

如下代码是spark2.2.0环境下生成2000w测试数据代码:

public class ESWriterTest extends Driver implements Serializable {
private static final long serialVersionUID = 1L;
private ExpressionEncoder<Row> encoder = null;
private StructType type = null;
    private String hdfdFilePath = "/user/my/streaming/test_es/*";
public ESWriterTest() {
} @Override
public void run() {
initSchema();
generateTestData(); sparkSession.stop();
} private void initSchema() {
type = DataTypes.createStructType(Arrays.asList(//
DataTypes.createStructField("id", DataTypes.StringType, true), //
DataTypes.createStructField("object_id", DataTypes.StringType, true), //
DataTypes.createStructField("scan_start_time", DataTypes.StringType, true), //
DataTypes.createStructField("scan_stop_time", DataTypes.StringType, true), //
DataTypes.createStructField("insert_time", DataTypes.StringType, true), //
DataTypes.createStructField("enodeb_id", DataTypes.StringType, true)));
for (int i = 0; i < 145; i++) {
type = type.add("mr_tadv_" + (i < 10 ? "0" + i : i), DataTypes.StringType);
}
encoder = RowEncoder.apply(type);
} private void generateTestData() {
generateData("/user/my/streaming/test_es/1/");
generateData("/user/my/streaming/test_es/2/");
generateData("/user/my/streaming/test_es/3/");
generateData("/user/my/streaming/test_es/4/");
generateData("/user/my/streaming/test_es/5/");
generateData("/user/my/streaming/test_es/6/");
generateData("/user/my/streaming/test_es/7/");
generateData("/user/my/streaming/test_es/8/");
generateData("/user/my/streaming/test_es/9/");
generateData("/user/my/streaming/test_es/10/");
generateData("/user/my/streaming/test_es/11/");
generateData("/user/my/streaming/test_es/12/");
generateData("/user/my/streaming/test_es/13/");
generateData("/user/my/streaming/test_es/14/");
generateData("/user/my/streaming/test_es/15/");
generateData("/user/my/streaming/test_es/16/");
generateData("/user/my/streaming/test_es/17/");
generateData("/user/my/streaming/test_es/18/");
generateData("/user/my/streaming/test_es/19/");
generateData("/user/my/streaming/test_es/20/"); // 支持的文件格式有:text、csv、json、parquet。
StructType structType = DataTypes.createStructType(Arrays.asList(DataTypes.createStructField("value", DataTypes.StringType, true)));
Dataset<Row> rows = sparkSession.read().format("text").schema(structType).load(hdfdFilePath);
rows.printSchema();
rows.show(10);
} private void generateData(String hdfsDataFilePath) {
List<Row> fukeData = new ArrayList<Row>();
for (int i = 1; i <= 1000000; i++) {
fukeData.add(RowFactory.create(String.valueOf(i)));
} StructType structType = DataTypes.createStructType(Arrays.asList(DataTypes.createStructField("id", DataTypes.StringType, false)));
JavaSparkContext sc = new JavaSparkContext(sparkSession.sparkContext());
JavaRDD<Row> javaRDD = sc.parallelize(fukeData, 64);
Dataset<Row> fukeDataset = sparkSession.createDataFrame(javaRDD, structType); Random random = new Random();
// 假设有1w个小区,数据一共200w条记录,那么每个小区有200条记录。
Dataset<Row> rows = fukeDataset.mapPartitions(new MapPartitionsFunction<Row, Row>() {
private static final long serialVersionUID = 1L; @Override
public Iterator<Row> call(Iterator<Row> idItems) throws Exception {
List<Row> newRows = new ArrayList<Row>();
while (idItems.hasNext()) {
String id = idItems.next().getString(0);
List<Object> rowItems = new ArrayList<Object>();
// id
int intId = Integer.valueOf(id);
rowItems.add(id); // object_id
String objectId = String.valueOf((intId % 10000) + 10000 * 256 + 1);
rowItems.add(objectId); int hour = random.nextInt(5) + 2;
int minute = random.nextInt(59) + 1;
int second_start = random.nextInt(30) + 1;
int second_stop = second_start + 15;
String scan_start_time = "2018-10-29 1" + hour + ":" + minute + ":" + second_start;
String scan_stop_time = "2018-10-29 1" + hour + ":" + minute + ":" + second_stop;
// scan_start_time
rowItems.add(scan_start_time);
// scan_stop_time
rowItems.add(scan_stop_time); // insert_time
rowItems.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); // enodeb_id
rowItems.add(String.valueOf((int) Integer.valueOf(objectId) / 256)); for (int i = 0; i < 145; i++) {
rowItems.add(String.valueOf(random.nextInt(100)));
} newRows.add(RowFactory.create(rowItems.toArray()));
} return newRows.iterator();
}
}, encoder); rows.toJavaRDD().repartition(20).saveAsTextFile(hdfsDataFilePath);
}
}

Spark环境下使用BulkProcessor将测试数据入库到ES6.4.2

下边是Spark2.2.0环境下,使用BulkProcessor方式插入2000w条记录到ES6.4.2下的测试代码,测试代码调测过程中发现问题:不能再ForeachPartitionFunction的call函数中调用client.close(),和bulkProcessor.close();函数,否则会抛出异常:原因这个client可能是多个executor共用。

    private ExpressionEncoder<Row> encoder = null;
private StructType type = null;
private String hdfdFilePath = "/user/my/streaming/test_es/*"; public static void main(String[] args) {
initSchema(); StructType structType = DataTypes.createStructType(Arrays.asList(DataTypes.createStructField("value", DataTypes.StringType, true)));
Dataset<Row> lines = sparkSession.read().format("text").schema(structType).load(hdfdFilePath); Dataset<Row> rows = lines.map(new MapFunction<Row, Row>() {
private static final long serialVersionUID = 1L; @Override
public Row call(Row value) throws Exception {
List<Object> itemsList = new ArrayList<Object>();
String line = value.getAs("value");
String[] fields = line.split(","); for (String filed : fields) {
itemsList.add(filed);
} return RowFactory.create(itemsList.toArray());
}
}, encoder); rows.show(10); rows.toJSON().foreachPartition(new EsForeachPartitionFunction()); sparkSession.stop();
} private void initSchema() {
type = DataTypes.createStructType(Arrays.asList(//
DataTypes.createStructField("id", DataTypes.StringType, true), //
DataTypes.createStructField("object_id", DataTypes.StringType, true), //
DataTypes.createStructField("scan_start_time", DataTypes.StringType, true), //
DataTypes.createStructField("scan_stop_time", DataTypes.StringType, true), //
DataTypes.createStructField("insert_time", DataTypes.StringType, true), //
DataTypes.createStructField("enodeb_id", DataTypes.StringType, true)));
for (int i = 0; i < 145; i++) {
type = type.add("mr_tadv_" + (i < 10 ? "0" + i : i), DataTypes.StringType);
}
encoder = RowEncoder.apply(type);
}

EsForeachPartitionFunction.java

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit; import org.apache.spark.api.java.function.ForeachPartitionFunction;
import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.transport.client.PreBuiltTransportClient; public class EsForeachPartitionFunction implements ForeachPartitionFunction<String> {
private static final long serialVersionUID = 1L; @Override
public void call(Iterator<String> rows) throws Exception {
TransportClient client = null;
BulkProcessor bulkProcessor = null;
try {
client = getClient();
bulkProcessor = getBulkProcessor(client);
} catch (Exception ex) {
System.out.println(ex.getMessage() + "\r\n" + ex.getStackTrace());
}
Map<String, Object> mapType = new HashMap<String, Object>(); while (rows.hasNext()) {
@SuppressWarnings("unchecked")
Map<String, Object> map = new com.google.gson.Gson().fromJson(rows.next(), mapType.getClass());
bulkProcessor.add(new IndexRequest("twitter", "tweet").source(map));
} try {
// Flush any remaining requests
bulkProcessor.flush();
System.out.println("--------------------------------bulkProcessor.flush(); over...------------------------"); } catch (Exception ex) {
System.out.println("" + ex.getMessage() + "\r\n" + ex.getStackTrace());
} try {
// Or close the bulkProcessor if you don't need it anymore
bulkProcessor.awaitClose(10, TimeUnit.MINUTES);
System.out.println("--------------------------------bulkProcessor.awaitClose(10, TimeUnit.MINUTES); over...------------------------");
} catch (Exception ex) {
System.out.println("" + ex.getMessage() + "\r\n" + ex.getStackTrace());
}
} private BulkProcessor getBulkProcessor(TransportClient client) {
BulkProcessor bulkProcessor = BulkProcessor//
.builder(client, new BulkProcessor.Listener() {
@Override
public void afterBulk(long arg0, BulkRequest arg1, BulkResponse arg2) {
// TODO Auto-generated method stub
System.out.println("结束afterBulk(long arg0, BulkRequest arg1, BulkResponse arg2)。。。。");
} @Override
public void afterBulk(long arg0, BulkRequest arg1, Throwable arg2) {
// TODO Auto-generated method stub
System.out.println("结束afterBulk(long arg0, BulkRequest arg1, Throwable arg2)。。。。");
System.out.println(arg1.numberOfActions() + " data bulk failed,reason :" + arg2);
} @Override
public void beforeBulk(long arg0, BulkRequest arg1) {
// TODO Auto-generated method stub
System.out.println("开始。。。。");
}
}) //
.setBulkActions(10000)//
.setBulkSize(new ByteSizeValue(64, ByteSizeUnit.MB))//
.setFlushInterval(TimeValue.timeValueSeconds(5))//
.setConcurrentRequests(1)//
.setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))//
.build();
return bulkProcessor;
} private TransportClient getClient() {
Settings settings = Settings.builder()//
.put("cluster.name", "es") //
.put("client.transport.sniff", true)//
.build(); PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings); TransportClient client = preBuiltTransportClient;
// 10.205.201.97,10.205.201.98,10.205.201.96,10.205.201.95
try {
client.addTransportAddress(new TransportAddress(InetAddress.getByName("10.205.201.97"), 9300));
client.addTransportAddress(new TransportAddress(InetAddress.getByName("10.205.201.98"), 9300));
client.addTransportAddress(new TransportAddress(InetAddress.getByName("10.205.201.96"), 9300));
client.addTransportAddress(new TransportAddress(InetAddress.getByName("10.205.201.95"), 9300));
} catch (UnknownHostException e) {
e.printStackTrace();
throw new RuntimeException(e);
} return client;
}
}

依赖pom.xml

        <!--Spark -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-spark-20_2.11</artifactId>
<version>6.4.2</version>
</dependency> <dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.4.2</version>
</dependency>

测试速度有点低3500条记录/s

关于ES+SPARK如何优化的文章请参考:

Elasticsearch进阶(一)写入性能基准测试写入性能优化(56小时到5小时),chunk_size探讨

ElasticSearch写入性能优化

Elasticsearch写入性能优化

elasticsearch写入优化记录,从3000到8000/s

Spark2.x写入Elasticsearch的性能测试

Spark2.2+ES6.4.2(三十一):Spark下生成测试数据,并在Spark环境下使用BulkProcessor将测试数据入库到ES的更多相关文章

  1. OpenCV探索之路(二十一)如何生成能在无opencv环境下运行的exe

    我们经常遇到这样的需求:我们在VS写好的程序,需要在一个没有装opencv甚至没有装vs的电脑下运行,跑出效果.比如,你在你的电脑用opencv+vs2015写出一个程序,然后老师叫你把程序发给他,他 ...

  2. 大数据笔记(三十一)——SparkStreaming详细介绍,开发spark程序

    Spark Streaming: Spark用于处理流式数据的模块,类似Storm 核心:DStream(离散流),就是一个RDD=================================== ...

  3. Spark Streaming性能优化: 如何在生产环境下应对流数据峰值巨变

    1.为什么引入Backpressure 默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > ...

  4. Bootstrap <基础三十一>插件概览

    在前面布局组件中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使不是一名高级的 JavaScript 开发人员,也可以着手 ...

  5. COJ969 WZJ的数据结构(负三十一)

    WZJ的数据结构(负三十一) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 A国有两个主基站,供给全国的资源.定义一个主基站 ...

  6. NeHe OpenGL教程 第三十一课:加载模型

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. 三十一、Java图形化界面设计——布局管理器之GridLayout(网格布局)

    摘自http://blog.csdn.net/liujun13579/article/details/7772491 三十一.Java图形化界面设计--布局管理器之GridLayout(网格布局) 网 ...

  8. JAVA之旅(三十一)——JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件

    JAVA之旅(三十一)--JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件 有段时间没有更新JAVA了,我们今天来说一下JAVA中的图形化界面,也就是GUI ...

  9. Java进阶(三十一) Web服务调用

    Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...

随机推荐

  1. java :: Java中的双冒号操作符

    java中的双冒号操作符 定义 双冒号运算操作符是类方法的句柄,lambda表达式的一种简写,这种简写的学名叫eta-conversion或者叫η-conversion. 通常的情况下: 把 x -& ...

  2. 双线程 线性dp 传纸条

    /* 两种做法:一是暴力dp[i][j][k][l] 二是以走的步数k作为阶段, dp[k][i][j]表示走到第k步,第一个人横坐标走到i,第二个人横坐标走到j 可以以此推出第第一个人的坐标为[i, ...

  3. 性能测试十五:liunx下搭建(tomcat+项目+jmete命令行)

    单机 准备工作: 1.压力机安装并配置好JDK,输入java和javac验证环境变量 2.上传jmeter到liunx下: 准备好jmeter的压缩包 在第三方工具中对linux文件上传下载(需先装好 ...

  4. python 全栈开发,Day30(第一次面向对象考试)

    月考题: python 全栈11期月考题 一 基础知识:(70分) 1.文件操作有哪些模式?请简述各模式的作用(2分) 2.详细说明tuple.list.dict的用法,以及它们的特点(3分) 3.解 ...

  5. Linux学习笔记:ftp中binary二进制与ascii传输模式的区别

    在使用ftp传输文件时,常添加上一句: binary  -- 使用二进制模式传输文件 遂查资料,如下所获. FTP可用多种格式传输文件,通常由系统决定,大多数Linux/UNIX系统只有两种模式:文本 ...

  6. rsync增量备份脚本

    shell脚本: #!/bin/bash export PATH=/usr/local/bin:/usr/bin:/bin dir=/mnt/ DAY=`date "+%Y-%m-%d&qu ...

  7. NDK 开发实例一(Android.mk环境配置下)

         在我写这篇文章的时候,Android Studio已经是2.3版本了,已经集成CMake 编译工具, 用户只需在 新建项目的时候,添加选项(Include C++ support),Andr ...

  8. Docker 镜像的导入和导出

    镜像的导入和导出 export 和improt [root@#localhost docker]# docker run -ti ubuntu:update /bin/bash root@cbe3cb ...

  9. laravel5 项目上线后务必将开发环境更改为生产环境

    如果以开发环境上线,出错信息将全通过json暴露出来了,屏蔽方式如下: .env 文件设置如下APP_ENV=productionAPP_DEBUG=false 改完设置后把缓存清理一遍 如果更改后清 ...

  10. POJ 1228 (稳定凸包问题)

    <题目链接> <转载于  >>> > 首先来了解什么是稳定的凸包.比如有4个点: 这四个点是某个凸包上的部分点,他们连起来后确实还是一个凸包.但是原始的凸包可 ...