概述
- 简介:
- 特点:
- 扩展性
- 容错性
- 海量数据存储
- 优缺点:
- 优点:
- 数据冗余, 硬件容错
- 处理流式(一次写入多次读取)的数据访问
- 适合存储大文件
- 构建在廉价机器上
- 缺点:
- 不满足低延迟的数据访问
- 不适合小文件的存储
- 存储:
- 将文件切分成指定大小的数据块并以多副本的存储在多个机器上
- 数据的切分,多副本,容错等操作对用户透明
NameNode (Filename, numReplicas, block-ids)
架构
- 简介:
- 一个Master(NameNode/NN)带N个Slaves(DataNode/DN)
- 一个文件会被拆分成多个Block, 默认blocksize:128M
NameNode
- 负责客户端请求的响应
- 负责元数据(文件的名称、副本系数、Block存放的DN)的管理
DataNode
- 存储用户的文件对应的数据块(Block)
- 要定期向NN发送心跳信息, 汇报本身及所有的block信息, 健康状况
副本机制
副本存放策略
HDFS文件读写流程
环境搭建
伪分布式
- jdk和ssh安装
- 免密登录配置:
ssh-keygen -t rsa
cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
ssh localhost
- 下载解压
tar -zxvf hadoop-x.x.x-cdhx.x.x -C ~/app
- 配置文件修改: hadoop_home/etc/hadoop
- hadoop-env.sh配置:
JAVA_HOME=/usr/lib/jvm/java-x.x
- core-site.xml配置: 默认目录位于/tmp, 重启后会丢失
<configuration>
<property>
<name>fs.defaultFS</name>
<!-- 外网访问改成ip -->
<value>hdfs://localhost:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/app/tmp</value>
</property>
</configuration>
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
- 启动
# 格式化文件系统, 仅第一次执行, 使用hdfs代替hadoop(depressed))
./bin/hdfs namenode -format
# 启动NameNode, DataNode
./sbin/start-dfs.sh
# 进程验证 DataNode SecondaryNameNode NameNode
jps
# 网页方式验证
curl http://localhost:50070/
# 防火墙添加规则
# vim /etc/sysconfig/iptables
-A INPUT -p tcp -m tcp --dport 50070 -j ACCEPT
- 停止:
./sbin/stop-dfs.sh
HDFS Shell操作
# vi ~/.bashrc
export HADOOP_HOME=/opt/apache/hadoop/hadoop-2.6.0-cdh5.7.0
export PATH=$HADOOP_HOME/bin:$PATH
# 使生效
source ~/.bashrc
- 查看命令参数:
hadoop fs(hdfs dfs)
常用操作
- ls:
# 查看根目录
hadoop fs -ls /
# 递归查看
hadoop fs -ls -R /
- mkdir
# 根目录创建test目录
hadoop fs -mkdir /test
# 递归创建目录
hadoop fs -mkdir -p /test/a
- put: 将本地文件传到hdfs
# 将hello.txt传到hdfs根目录
hadoop fs -put hello.txt /
- get
# 将hdfs中的/test/a/h.txt拷贝到本地
hadoop fs -get /test/a/h.txt
- rm: 删除文件
# 删除文件
hadoop fs -rm /hello.txt
# 递归删除
hadoop fs -rm -R /test
- cat: 查看文件内容
hadoop fs -cat /hello.txt
# 也可以使用-text
hadoop fs -text /hello.txt
- copyFromLocal: 从本地拷贝到hdfs
# 将本地hello.txt文件拷贝到hdfs的/test/a目录下, 文件名为h.txt
fs -copyFromLocal hello.txt /test/a/h.txt
- test
hdfs dfs -test -[ezd] URI
Java API操作HDFS
步骤
- 添加依赖
<properties>
<cdh.version>2.6.0-cdh5.7.0</cdh.version>
</properties>
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${cdh.version}</version>
</dependency>
- 创建连接
// 该路径为core-site.xml中配置
public static final String HADOOP_PATH = "hdfs://192.168.33.12:8020";
FileSystem fileSystem = null;
Configuration configuration = null;
configuration = new Configuration();
// 指定用户为hadoop
fileSystem = FileSystem.get(new URI(HADOOP_PATH), configuration, "hadoop");
// 创建文件夹
fileSystem.mkdirs(new Path("/hdfsapi/test"));
//创建文件并写入内容
FSDataOutputStream outputStream = fileSystem.create(new Path("/hdfsapi/test/a.txt"));
outputStream.write("hello hdfs".getBytes());
outputStream.flush();
outputStream.close();
//将内容输出到控制台
FSDataInputStream inputStream = fileSystem.open(new Path("/hdfsapi/test/a.txt"));
IOUtils.copyBytes(inputStream, System.out, 1024); // IOUtils为hadoop.io包
inputStream.close();
// 重命名
Path srcPath = new Path("/hdfsapi/test/a.txt");
Path dstPath = new Path("/hdfsapi/test/b.txt");
boolean rename = fileSystem.rename(srcPath, dstPath);
System.out.println(rename);
// 本地文件上传到hdfs
Path localPath = new Path("E:\\WorkSpace\\data\\test.txt");
Path hdfsPath = new Path("/hdfsapi/test");
fileSystem.copyFromLocalFile(localPath, hdfsPath);
//带进度的大文件上传
InputStream inputStream = new BufferedInputStream(
new FileInputStream(new File("E:\\WorkSpace\\Web\\bigFile"))
);
FSDataOutputStream fsDataOutputStream = fileSystem.create(new Path("/hdfsapi/test"), new Progressable() {
@Override
public void progress() {
System.out.println(".");
}
});
IOUtils.copyBytes(inputStream, fsDataOutputStream, 4096);
// 下载文件
Path localPath = new Path("E:\\WorkSpace\\b.txt");
Path hdfsPath = new Path("/hdfsapi/test/b.txt");
fileSystem.copyToLocalFile(hdfsPath, localPath);
// 列出文件信息
FileStatus[] listStatus = fileSystem.listStatus(new Path("/hdfsapi/test"));
for (FileStatus status : listStatus) {
String file = status.isDirectory() ? "文件夹" : "文件";
short replication = status.getReplication(); //副本
long len = status.getLen(); // 文件大小
String path = status.getPath().toString();
System.out.println(file + "\t" + replication + "\t" + len + "\t" + path);
}
//删除文件
fileSystem.delete(new Path("/hdfsapi/test/a.txt"), true);
HDFS文件读写流程
存储数据
- client(divide into blocks)->NameNode->DataNode
读取数据
- client从NameNode获取元数据信息
- client从DataNode请求数据
参考