用Hadoop1.0.3实现KMeans算法(2)

二、用分布式缓存文件存储K个质心

既然不能通过共享外部类变量的方式,那我们通过文件在map和reduce之间传递数据总可以吧,Mapper从文件中读取质心,Reducer把更新后的质心再写入这个文件。这里的问题是:如果确定要把质心放在文件中,那Mapper就需要从2个文件中读取数据--质心文件和样本数据文件。虽然有MutipleInputs可以指定map()的输入文件有多个,并可以为每个输入文件分别指定解析方式,但是MutipleInputs不能保证每条记录从不同文件中传给map()的顺序。在我们的KMeans中,我们希望质心文件全部被读入后再逐条读入样本数据。

于是乎就想到了DistributedCache,它主要用于Mapper和Reducer之间共享数据。DistributedCacheFile是缓存在本地文件,在Mapper和Reducer中都可使用本地Java I/O的方式读取它。于是我又有了一个错误的思路:

class MyMaper{

    Vector<Sample> centers=new Vector<Sample>(K);

    void setup(){

        //读取cacheFile,给centers赋值

    }

    void map(){

        //计算样本离哪个质心最近

    }

}

class MyReducer{

    Vector<Sample> centers=new Vector<Sample>(K);

    void reduce(){

        //更新centers

    }

    void cleanup(){

        //把centers写回cacheFile

    }

}

错因:DistributedCacheFile是只读的,在任务运行前,TaskTracker从JobTracker文件系统复制文件到本地磁盘作为缓存,这是单向的复制,是不能写回的。试想在分布式环境下,如果不同的mapper和reducer可以把缓存文件写回的话,那岂不又需要一套复杂的文件共享机制,严重地影响Hadoop执行效率。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/103e90ef9f10a21de2f918e05bffabb8.html