在MR作业中,经常有使所有节点的作业共享引用数据的需求,Hadoop为我们提供了一种可供选择的机制:分布式缓存。它可以把map或reduce任务要用的通用只读文件在所有节点之间共享。这些文件可以是文本数据,也可以是jar包或者二进制文件,任何文件都可以。

        要被共享的文件放置在HDFS,作业驱动将其加入到DistributedCache。在作业执行前,Hadoop的每个节点都会将文件复制到本地文件系统,这意味着每个任务对文件都有本地访问权限。

        1)将要用的文件上传到HDFS。

        2)具体使用方法如下,在创建将conf传递到job之前,将数据分发到每个节点上:

DistributedCache.addCacheFile(new URI("/user/hadoop/conf/a.txt"), conf);

3)在Job初始化的时候回调函数configure中加载此文件:

Path[] cacheFile = DistributedCache.getLocalCacheFiles(job);

4)在mapper和reduce函数中使用此数据 。

注意:我们一定要把获取数据的过程放在mapper或reducer类的configure()函数中,这样对应一个datanode就只有一份数据,N个map可以共享着一份数据。如果放在map和reduce中去获取,那么每个都会去加载一次,很容易会导致堆栈溢出。

DistributedCache有以下几种典型的应用场景:

1)分发字典文件,一些情况下Mapper或者Reducer需要用到一些外部字典,比如黑白名单、词表等;

2)map-side join:当多表连接时,一种场景是一个表很大,一个表很小,小到足以加载到内存中,这时可以使用DistributedCache将小表分发到各个节点上,以供Mapper加载使用;

3)自动化软件部署:有些情况下,MapReduce需依赖于特定版本的库,比如依赖于某个版本的PHP解释器,一种做法是让集群管理员把这个版本的PHP装到各个机器上,这通常比较麻烦,另一种方法是使用DistributedCache分发到各个节点上,程序运行完后,Hadoop自动将其删除。