StephenChan's Tech Space 潜心修炼

24Jun/100

How MapReduce Works

一、从Map到Reduce

MapReduce其实是分治算法的一种实现,其处理过程亦和用管道命令来处理十分相似,一些简单的文本字符的处理甚至也可以使用Unix的管道命令来替代,从处理流程的角度来看大概如下:

cat input | grep |      sort      |  uniq -c | cat > output
# Input -> Map -> Shuffle & Sort -> Reduce -> Output

简单的流程图如下:

procedure对于Shuffle,简单地说就是将Map的输出通过一定的算法划分到合适的Reducer中进行处理。Sort当然就是对中间的结果进行按key排序,因为Reducer的输入是严格要求按key排序的。

Filed under: Hadoop Continue reading
16Jun/100

HDFS简介

一、HDFS

HDFS全称是Hadoop Distributed System。HDFS是为以流的方式存取大文件而设计的。适用于几百MB,GB以及TB,并写一次读多次的场合。而对于低延时数据访问、大量小文件、同时写和任意的文件修改,则并不是十分适合。

目前HDFS支持的使用接口除了Java的还有,Thrift、C、FUSE、WebDAV、HTTP等。HDFS是以block-sized chunk组织其文件内容的,默认的block大小为64MB,对于不足64MB的文件,其会占用一个block,但实际上不用占用实际硬盘上的64MB,这可以说是HDFS是在文件系统之上架设的一个中间层。之所以将默认的block大小设置为64MB这么大,是因为block-sized对于文件定位很有帮助,同时大文件更使传输的时间远大于文件寻找的时间,这样可以最大化地减少文件定位的时间在整个文件获取总时间中的比例 。

构成HDFS主要是Namenode(master)和一系列的Datanode(workers)。Namenode是管理HDFS的目录树和相关的文件元数据,这些信息是以"namespace image"和"edit log"两个文件形式存放在本地磁盘,但是这些文件是在HDFS每次重启的时候重新构造出来的。Datanode则是存取文件实际内容的节点,Datanodes会定时地将block的列表汇报给Namenode。

由于Namenode是元数据存放的节点,如果Namenode挂了那么HDFS就没法正常运行,因此一般使用将元数据持久存储在本地或远程的机器上,或者使用secondary namenode来定期同步Namenode的元数据信息,secondary namenode有点类似于MySQL的Master/Salves中的Slave,"edit log"就类似"bin log"。如果Namenode出现了故障,一般会将原Namenode中持久化的元数据拷贝到secondary namenode中,使secondary namenode作为新的Namenode运行起来。

Filed under: Hadoop Continue reading
16Jun/100

简单的Streaming和Pipes示例

一、Hadoop Streaming

Streaming是Hadoop提供的一个可以使用其他编程语言来进行MapReduce来的API,因为Hadoop是基于Java(由于作者比较擅长Java,Lucene和Nutch都是出于Hadoop的作者)。Hadoop Streaming并不复杂,其只是使用了Unix的标准输入输出作为Hadoop和其他编程语言的开发接口,因此在其他的编程语言所写的程序中,只需要将标准输入作为程序的输入,将标准输出作为程序的输出就可以了。

在标准的输入输出中,key和value是以tab作为分隔符,并且在reduce的标准输入中,hadoop框架保证了输入的数据是经过了按key排序的。

下面的示例是用Python重写了上一个示例:

# max_temperature_map.py
#!/usr/bin/env python
import sys
for line in sys.stdin:
 val = line.strip().split()
 # 分隔年份和温度值,输出到标准输出
 print "%s\t%s"%(val[0], val[1])

# max_temperature_reduce.py
#!/usr/bin/env python
import sys
(last_key, max_val) = (None, 0)
for line in sys.stdin:
 (key, temp) = line.strip().split('\t')
 if last_key and last_key != key:
 print "%s\t%s" % (last_key, max_val)
 (last_key, max_val) = (key, int(temp))
 else:
 (last_key, max_val) = (key, max(max_val, int(temp)))

if last_key:
 print "%s\t%s" % (last_key, max_val)
Filed under: Hadoop Continue reading
16Jun/100

简单的MapReduce示例(Java)

Hadoop的三种模式以及相应的安装细节Google上一大把,其实都基本上是一些参数的设置。

下面自己在.bashrc文件中的设置:

# setting in .bashrc
export HADOOP_INSTALL=/home/stephenchan/hadoop-0.20.2
export CLASSPATH=.:$HADOOP_INSTALL/hadoop-0.20.2-core.jar:$HADOOP_INSTALL/lib:$CLASSPATH
export PATH=$PATH:$HADOOP_INSTALL/bin

样例的代码是来自<Hadoop : The Definitive Guide>一书,由于没有拿到天气的数据,所以自己用代码生成了一个类似的样例数据,只有年份和温度,用MapReduce来取每年的最高温度,但我省去了日期中的天,保留了年。代码在standalone模式下运行即可,官方的参考文档 : http://hadoop.apache.org/common/docs/r0.20.2/cn/。目前Hadoop只在Linux下完全支持商用运行,在Unix和Windows只支持用来开发。

生成示例数据的Python代码(生成后再手动给三个年份设置最大的temp值(如999)来观察结果的正常与否):

#!/usr/bin/env python

import string
import random
import hashlib
random_chars = string.digits
year_list = [1990, 2000, 2010]
for idx in range(1, 1000):
 year = year_list[idx%3]
 temp  = random.sample(random_chars, 3)
 s = "%s %s" % (year, "".join(temp))
 print s
Filed under: Hadoop Continue reading
7Jun/100

动态链接

动态链接的基本思想是把程序按照模块拆分成各个相对独立的部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接那样把所有的程序模块都链接成一个单独的可执行文件。动态链接涉及运行时的链接及多个文件的装载,必需要有操作系统的支持,因为动态链接的情况下,进程的虚拟地址空间的分布会比静态链接情况下更为复杂,还有一些存储管理、内存共享、进程线程等机制在动态链接下也会有一些微妙的变化。在Linux系统中,ELF动态链接文件被称为“动态共享对象(DSO,Dynamic Shared Objects),简称共享对象,它们一般都是以“.so”为扩展名的一些文件,而在Windows系统中,动态链接文件被称为动态链接库(Dynamical Linking Library),即平时见到的以“.dll”为扩展名的文件。

动态链接库的特点与优势

把函数库推迟到程序运行时加载的好处有几个:

  • 可以实现进程之间的资源共享。就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝。如果有,则让其共享那一拷贝(共享代码段,数据码各自独立一份);只有没有才链接载入。这种模式虽然会带来一些”动态链接“额外的开销,但却大大地节省了系统的内存资源,通过一定的优化,与静态链接相比,性能损失大约在5%以下。
  • 程序升级变得简单。用户只需要升级动态链接库,而无需像静态链接那样重新编译其他原有的代码就可以完成整个程序的升级。
  • 可以使链接载入由程序员在程序代码中控制,如dlopen、dlsym、dlclose等等。
Page 2 of 1312345678910...Last »