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. 进一步尝试

再次猜测可能以下原因导致,再进一步进行测试。

  1. 远程提交代码运行MR JOB或者远程来操作HDFS都会有大量的IO时间浪费
  2. 同一个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流量过大的问题,还需再探究。想了解更多可以关注我后续的文章。