转自:http://kaimingwan.com/post/alluxio/spark-on-alluxiohe-mr-on-alluxioce-shi-gai-jin-ban
1. 介绍
之前我们进行过一次测试,见文章alluxio和spark以及mapreduce性能对比。但是由于硬件限制,alluxio的效果并没有体现出来。
本次我们将重新进行一番测试。我们采用的硬件配置如下所示:
注意注意!!!:最新的MR on alluxio测试请参考文章MapReduce on alluxio性能测试
ip | cpu | 核数 | 内存 | 承担角色 |
---|---|---|---|---|
10.8.12.16 | Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz | 40核 | 128GB | namenode,alluxio-master,datanode,alluxio-worker,yarn manager |
10.8.12.17 | Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz | 40核 | 128GB | standby namenode,standby alluxio-master,datanode,alluxio-worker |
10.8.12.18 | Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz | 40核 | 128GB | alluxio-master,datanode,alluxio-worker |
2. 准备数据
准备10G的数据,用于MR和Spark来进行计算统计行数。
# 在alluxio上新建存放测试数据的目录
alluxio fs mkdir /linecount
# 按照块大小为64MB,生成10G的文本文件
dd if=/dev/urandom bs=64M count=160 of=10G.txt
#将测试文件放到alluxio内存空间
alluxio fs copyFromLocal 10G.txt /linecount
#再持久化到hdfs,持久化都会存放到HDFS的/alluxio目录下
alluxio fs persist /linecount/10G.txt
2.1 清空系统缓存
位了保证实验的准确性,我们在把数据load到HDFS和alluxio后,需要清下系统缓存确保实验准确性。在各个节点上执行以下操作。
sudo sh -c ‘free && sync && echo 3 > /proc/sys/vm/drop_caches && free‘
3. MR测试
3.1 MR without alluxio
因为之前我们已经编过程序了,我们改下访问路径直接拿来用即可。如果还不会的可以参考我的文章:alluxio和spark以及mapreduce性能对比
测试结果:
耗时59秒,对10G文件进行行数统计(=。=# 机器配置牛逼就是diao)
3.2 MR with alluxio
跑一下测试:
耗时59秒(多次实验的平均值基本在1分左右)
3.3 问题补充
进行实验的时候可能会有如下报错:
Diagnostics: org.apache.commons.codec.binary.Base64.encodeBase64String([B)Ljava/lang/String;
出现这个问题主要是由于alluxio源码编译的问题。关于这个请参考我的文章:alluxio1.2.0 for hadoop 2.7.2安装
PS: 这个问题反馈给作者后,在1.3的版本中已经修复,可以下载最新版本。
4. spark测试
4.1 spark without alluxio
这里需要注意的是,在运行spark job的时候,我们发现spark job实际比MR运行的要慢。当没有对spark进行任何调优,按照默认的设置在spark-shell运行同样的line-count的任务。我整整花了6分钟。
关于该问题的描述可以参看SF上我的提问。Why line count job runs slower in spark shell than a mapreduce job
简单调优后,对10G文件进行分析统计行数,耗时1分27秒(只是进行简单调优,虽然仍然没有MR快,但是已经比原来的6分钟好的多了)
4.2 spark with alluxio
耗时1分21秒
5. 第一阶段实验总结
alluxio并没有达到预期的效果,这是什么原因呢?让我们来分析下。
首先我们可以先看看官方进行的spark on alluxio和spark without alluxio的实验——Using Alluxio to Improve the Performance and Consistency of HDFS Clusters
可以发现,官方进行实验的时候的负载模拟,还是与真实环境相近的。即同时存在每周的分析JOB和每月的分析JOB。任务也可以分为I/O密集和CPU密集的任务。我们采用linecount来进行实验,没有达到预期效果,可能是以下原因:
首先可以肯定的是我们确实清除了缓存的数据,但是经过多次实验发现。使用alluxio和不使用alluxio所花时间基本是一致的。这也就是说,在使用alluxio的时候,程序可能还是去读取HDFS了,从而导致时间上没有本质的差别。具体是什么问题我们还需继续探究。
6. IO实验
alluxio最大的作用就是IO加速。按理说,之前的实验如果正常进行的话,读取数据和写出结果的IO时间,在使用alluxio之后必然都会大大减少,因为可以从内存中直接取数据。
为此,为了更加集中的研究问题症结所在,现在我们仅仅调用HDFS和ALLUXIO的IO接口来进行文件读取,验证是否在IO性能上alluxio能帮我改进性能。
6.1 任务负载
我们需要读取的数据仍然为随机生成的10G大文件。无论是从HDFS上读取还是从alluxio中读取,我们都采用单个线程来进行文件读取。实验分为两个大组做为对比实验。即从HDFS上读文件和从alluxio中读文件。每个大组内的实验分为2个任务类型:
6.2 从HDFS中读取10G文件
注意确保清空系统缓存,并且用free确认。
采用的代码如下,我们按照64MB一个批次来读取。
public class RWHDFSTest {
public static void main(String[] args) throws IOException {
//统计时间
System.out.println("程序开始时间戳信息:"+new Date());
final long startTime=System.currentTimeMillis();
Configuration conf = initialConfig("KaimingWan", "hdfs://ns", "10.8.12.16");
//设置需要访问的文件在HDFS上的URL
String uri = "/alluxio/linecount/10G.txt";
Path path = new Path(uri);
normalFileReader(conf, path,uri);
final long endTime=System.currentTimeMillis();
float excTime=(float)(endTime-startTime)/1000;
System.out.println("执行时间:"+excTime+"s");
System.out.println("当前时间为:"+ new Date());
}
//读取任意格式数据
public static void normalFileReader(Configuration conf,Path path,String uri)throws IOException {
FileSystem fileSystem = FileSystem.get(URI.create(uri), conf);
FSDataInputStream fsDataInputStream = fileSystem.open(path);
//读取64MB字节读取
byte[] buffer = new byte[67108864];
//记录读取长度
int len = fsDataInputStream.read(buffer);
while (len != -1) {
//System.out.write(buffer, 0, len);
len = fsDataInputStream.read(buffer);
}
}
}
6.3 从HDFS中读取10G文件
把上面的地址改成:alluxio://10.8.12.16:19998 再次运行
发现耗时更久啦
7. 进一步尝试
再次猜测可能以下原因导致,再进一步进行测试。
- 远程提交代码运行MR JOB或者远程来操作HDFS都会有大量的IO时间浪费
- 同一个10G的文件的数据块全部分散在一个worker上,这导致跨worker的网络IO开销
7.1 存储均衡处理
为了保证实验结果有效性,先确保10G的数据块全部均匀分布在各个worker上。
# 如果从本地文件系统拷贝过去,可以使用命令:
alluxio fs -Dalluxio.user.file.write.location.policy.class=alluxio.client.file.policy.RoundRobinPolicy copyFromLocal 10G.txt /linecount/10G.txt
# 如果从UFS上拷贝过去,可以使用命令
alluxio fs -Dalluxio.user.file.write.location.policy.class=alluxio.client.file.policy.RoundRobinPolicy load /linecount/10G.txt
7.2 使用MR JOB统计行数
仍然确保每个节点上都清空系统缓存。将程序打包成JAR在master节点上提交, 耗时1分03秒
7.3 使用MR on alluxio统计行数
结果耗时34秒
7.4 总结
在经过诸多“磨难”之后,总算是做出了符合预期的实验,即MR on alluxio能带来性能的提升。在此过程中,我还使用了iostat和nload工具来监控了磁盘IO和网络IO。最终发现MR on alluxio确实是从内存取数据。虽然通过负载均衡的放置数据,减少了网络IO开销,但是通过监控网络IO发现仍然存在大量的网络IO开销。因此alluxio所带来的性能提升比较小,按理说应该会有数倍以上的提升才是。
可见,要通过合理的设计和配置才能发挥alluxio的性能,否则甚至可能会做出使用alluxio性能反而更差的结果。后期针对网络IO流量过大的问题,还需再探究。想了解更多可以关注我后续的文章。