HDFS笔记

HDFS是大数分布式存储

HDFS原理

数据存储发展

单块硬盘

单机时代:早期互联网刚发展的时候,各种硬件资源相对缺乏,成本较高。我们将数据写入到磁盘中,一块不够再来一块,如果把数据一块磁盘一块磁盘的写,有如下问题:

  1. 单块磁盘写,磁盘读写速度上不去,读写慢;
  2. 数据写入单块磁盘,一旦磁盘故障导致数据丢失;

在这种情况下,RAID技术就应运而生了。

RAID

RAID ( Redundant Array of Independent Disks )即独立磁盘冗余阵列,简称为「磁盘阵列」,其实就是用多个独立的磁盘组成在一起形成一个大的磁盘系统,从而实现比单块磁盘更好的存储性能和更高的可靠性。

根据 RAID 算法的不同,RAID 有很多种。下面主要介绍 RAID0、RAID1、RAID10。

RAID0

RAID0 是一种非常简单的的方式,它将多块磁盘组合在一起形成一个大容量的存储。

假设阵列中有N块磁盘,当写数据时,会将数据分为N份,然后分别写入N块 磁盘中。因此,RAID0将提供非常优秀的读写性能。

优点:

  • 并行写入读取快,空间利用率高。
  • 如果你要读取/写入 2G 的数据,在普通硬盘上,要以单盘的速度读取/写入 2G 的数据。
  • 如果在 4 盘 RAID0 阵列中,每个盘只需读取/写入 500MB 的数据,四个盘可以并行读取/写入,因此理论的读写速度将是单块硬盘的4倍。

缺点:

  • 只要阵列中有一块硬盘坏掉,由于这块硬盘保存着所有数据(每个文件)的某一部分,因此所有数据都将无法读取,整个阵列中的数据将宣告报废。

RAID1

RAID1 是磁盘阵列中单位成本最高的一种方式。因为它的原理是在往磁盘写数据的时候,将同一份数据无差别的写两份到磁盘,分别写到工作磁盘和镜像磁盘,那么它的实际空间使用率只有50%了,两块磁盘当做一块用,这是一种比较昂贵的方案。

优点:

  • 数据写入两个磁盘,通过冗余存储实现容错。

缺点:

  • 空间利用率低,读写速度慢。

RAID10

RAID10其实就是RAID1与RAID0的一个合体。

先将磁盘阵列组成 RAID1, 再将多个RAID1 组成 RAID0。

读写数据时,可以将数据分N块,并行写入,而且每块数据都有备份。

这样既可以通过冗余存储容错,也可以提高读写的效率。

HDFS3.0

HDFS是Hadoop Distribute File System 的简称,也就是Hadoop的一个分布式文件系统,用来解决存储问题。

HDFS 可以使用低成本的硬件来搭建。

HDFS 可以对海量的数据进行分布式存储。

HDFS 实现软件RAID10。

namenode

名称节点,用来存储元数据。接收客户端的读写请求。

namenode元数据保存到了内存中和磁盘中,保存到内存中是为了快速查询数据信息,保存到磁盘中是为了数据安全。

元数据包括:

  • 文件名称
  • 文件大小
  • 文件权限
  • 文件所有者
  • 文件切了几块
  • 副本数量
  • 每一个block数据块存到了哪一个datanode上
  • 等等…

3.0中一般有一个active状态的namenode,有两个standby状态的namenode,其中,active状态的NameNode负责所有的客户端操作,standby状态的NameNode处于从属地位,维护着数据状态,随时准备切换。

一个数据块的元数据信息占用namenode内存存储空间为150字节。块越小读取的速度就越快,但是整体占用namenode的空间就越大。

配置方式如下:

core-site.xml

<property>
    <name>fs.defaultFS</name>
    <value>hdfs://ns1</value>
    <description>默认文件服务的协议和NS逻辑名称,和hdfs-site.xml里的对应此配置替代了1.0里的fs.default.name</description>
</property>
<property>
    <name>hadoop.tmp.dir</name>
    <value>/data/tmp</value>
    <description>数据存储目录</description>
</property>
<property>
        <name>hadoop.proxyuser.root.groups</name>
        <value>hadoop</value>
        <description>配置root(超级用户)允许通过代理用户所属组</description>
</property>
<property>
    <name>hadoop.proxyuser.root.hosts</name>
    <value>localhost</value>
    <description>配置root(超级用户)允许通过代理访问的主机节点</description>
</property>
<property>
    <name>ha.zookeeper.quorum</name>
    <value>nn1:2181,nn2:2181,nn3:2181</value>
    <description>HA使用的zookeeper地址</description>
</property>

hdfs-site.xml

<property>
    <name>dfs.namenode.name.dir</name>
    <value>/data/namenode</value>
    <description>namenode本地文件存放地址</description>
</property>
<property>
    <name>dfs.nameservices</name>
    <value>ns1</value>
    <description>提供服务的NS逻辑名称,与core-site.xml里的对应</description>
</property>
<!--主要的-->
<property>
    <name>dfs.ha.namenodes.ns1</name>
    <value>nn1,nn2,nn3</value>
    <description>列出该逻辑名称下的NameNode逻辑名称</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.rpc-address.ns1.nn1</name>
    <value>nn1:9000</value>
    <description>指定NameNode的RPC位置</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.http-address.ns1.nn1</name>
    <value>nn1:50070</value>
    <description>指定NameNode的Web Server位置</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.rpc-address.ns1.nn2</name>
    <value>nn2:9000</value>
    <description>指定NameNode的RPC位置</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.http-address.ns1.nn2</name>
    <value>nn2:50070</value>
    <description>指定NameNode的Web Server位置</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.rpc-address.ns1.nn3</name>
    <value>nn3:9000</value>
    <description>指定NameNode的RPC位置</description>
</property>
<!--主要的-->
<property>
    <name>dfs.namenode.http-address.ns1.nn3</name>
    <value>nn3:50070</value>
    <description>指定NameNode的Web Server位置</description>
</property>
<property>
    <name>dfs.namenode.handler.count</name>
    <value>77</value>
    <description>namenode的工作线程数</description>
</property>

hadoop-env.sh

# The maximum amount of heap to use, in MB. Default is 1000.
# java虚拟机使用的最大内存
source /etc/profile
export HADOOP_HEAPSIZE_MAX=512

datanode

数据节点

负责存储client发来的数据块block;执行数据块的读写操作。

  1. 数据是切块进行分布式存储的,而每个block块都需要存储在datanode上。
  2. namenode的其中一个作用是存元数据,另外一个作用就是用来管理datanode
  3. 每隔3sdatanode就会想namenode汇报自身情况,如果超过10min中没有收到datanode的心跳信息,namenode就会认为此datanode丢失了,将其身上的数据拷贝到其他服务器中。
  4. datanode在启动成功之后会接收namenode同步过来的clusterid,之后的通信过程中,datanode都会带着clusterid去和namenode通信,所以切记不要频繁的格式化namenode,因为每一次格式化namenode都会重新产生新的clusterid,造成namenode和datanode起不来的情况出现。

journalnode

用于数据同步

namenode元数据同步

Namenode 除了内存存储元数据外,磁盘也存储,主要维护两个文件,一个是fsimage,一个是 editlog

  • editlog(简称edits)是操作日志文件,记录了NameNode所要执行的操作
  • fsimage是元数据镜像文件。存储某NameNode元数据信息,并不是实时同步内存中的数据。

一般而言,fsimage中的元数据是落后于内存中的元数据的

当有写请求时,NameNode会首先写该操作先写到磁盘上的edits文件中,当edits文件写成功后才会修改NameNode内存的元数据,内存修改成功后向客户端返回成功信号。

请求操作记录除了会写入到activenamenode中的edits文件中,还会给journalnode中写入edits文件,然后journalnode会将本地的edits文件中的请求操作,在standbynamenode中进行同步。这样就可以进行元数据的同步了。

随着edits记录的操作越来越多,内存中的元数据越来越多,这样的话内存中的元数据存在风险,一旦宕机,内存数据丢失,所以为了安全起见,需要将内存中的元数据,周期性的写入到fsimage文件中。如果数据出错可以通过 fsimage + edits 恢复。

因为ActiveNamenode相对来说比较忙,所以选择相对轻松的StandbyNamenode来做元数据同步这个事情

namenode 元数据合并

  • StandByNamenode检查是否达到checkpoint条件:
    • 离上一次checkpoint操作是否已经有一个小时
    • HDFS已经进行了100万次操作。
  • StandByNamenode检查达到checkpoint条件后,将该元数据以fsimage.ckpt_txid格式保存到StandByNamenode的磁盘上,并且随之生成一个MD5文件。然后将该fsimage.ckpt_txid文件重命名为fsimage_txid。
  • 然后StandByNamenode通过HTTP联系ActiveNameNode。
  • ActiveNameNode通过StandByNamenode从StandByNamenode获取最新的fsimage_txid文件并保存为fsimage.ckpt_txid,然后也生成一个MD5,将这个MD5与StandByNamenode的MD5文件进行比较,确认ANN已经正确获取到了StandByNamenode最新的fsimage文件。然后将fsimage.ckpt_txid文件重命名为fsimage_txit。

周期可以自行配置

<property>
    <name> dfs.namenode.checkpoint.period</name>
  <value>3600</value>
  <description>
    两次连续的 checkpoint 之间的时间间隔。默认 1 小时
  </description>
</property>
<property>
  <name>dfs.namenode.checkpoint.txns</name>
  <value>1000000</value>
  <description>最大的没有执行 checkpoint 事务的数量,满足将强制执行紧急 checkpoint,即使尚未达到检查点周期。默认设置为 100 万。
  </description>
</property>

ZKFC

三台namenode已经全部启动成功但全是standby。

#手动切换nn1的节点是主节点
hdfs haadmin -transitionToActive nn1
#查看节点状态
hdfs haadmin -getServiceState nn1

如果每次都是程序员自己切换的话,那也太不灵活了,所以需要引入一个组件,就是zkfc

zkfc本质上就是一个进程,全称是ZKFailoverController,需要在三台namenode上启动。

它的主要任务就是一边联系同服务器的namenode,一边连接zookeeper。我们三个namenode启动之后,怎么通过zkfc选出一个active的namenode呢?那就看哪台节点的zkfc先在zookeeper中创建节点。谁创建成功,哪台服务器就是active的namenode,具体过程如下:

  1. 启动NameNode,ZKFC,此时三个NameNode的状态都是竞选状态
  2. 三个ZKFC分别通过ActiveStandbyElector发起NameNode的选举 通过zookeeper的写一致性以及临时节点来实现
  3. 发起主备选举的时候,ActiveStandbyElector会尝试在zookeeper的/hadoop-ha/ns1创建一个临时节点,zookeeper的写一致性会保证只有一个节点创建成功
  4. 创建成功的ActiveStandbyElector通过回调方式通知ZKFC,将对应的NameNode切换为Active状态;创建失败的也通过同样方式将NameNode切换为Standby状态
  5. 无论是否创建成功,这些ActiveStandbyElector都会监听/hadoop-ha/ns1; 当ActiveNameNode对应的HealthMonitor监控到NameNode异常时,会告知ZKFC,ZKFC通过ActiveStandbyElector删除所创建的临时节点
  6. 此时处于Standby的NameNode会监控到这个消息它首先会通过判断节点是否存在来确认情况,如果是正常关闭的,则发起主备选举,成功创建临时节点,并且将NameNode的状态切换为Active

HDFS高级配置

core-site.xml

#开启本地库对压缩的支持
<property>
    <name>io.native.lib.available</name>
    <value>true</value>
    <description>开启本地库支持</description>
</property>
#支持的压缩格式
<property>
    <name>io.compression.codecs</name>    <value>org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec</value>
    <description>相应编码的操作类</description>
</property>
#SequenceFiles在读写中可以使用的缓存大小
<property>
    <name>io.file.buffer.size</name>
    <value>131072</value>
    <description>SequenceFiles在读写中可以使用的缓存大小</description>
</property>
# 设置mr输入到hdfs中的数据的压缩是按照块压缩
<property>
    <name>mapreduce.output.fileoutputformat.compress.type</name>
    <value>BLOCK</value>
</property>
# 出入到hdfs中的文件是按照块为一个整体进行压缩
<property>
    <name>io.seqfile.compressioin.type</name>
    <value>BLOCK</value>
</property>
# 客户端连接超时时间
<property>
    <name>ipc.client.connection.maxidletime</name>
    <value>60000</value>
</property>

hdfs-site.xml

# hdfs开启支持文件追加操作
#关闭文件系统权限
#开启垃圾箱,删除的文件不会消失会移除到垃圾箱中
<property>
    <name>dfs.support.append</name>
    <value>true</value>
    <description>是否支持追加</description>
</property>
<property>
    <name>dfs.permissions.enabled</name>
    <value>false</value>
    <description>是否开启目录权限</description>
</property>
<property>
    <name>fs.trash.interval</name>
    <value>2880</value>
    <description>回收周期</description>
</property>
# datanode在读写本地文件的时候设置最大机器文件打开数
<property>
        <name>dfs.datanode.max.transfer.threads</name>
        <value>8192</value>
        <description>相当于linux下的打开文件最大数量,文档中无此参数,当出现DataXceiver报错的时候,需要调大。默认256</description>
</property>
# 在hdfs多个节点中数据均衡的时候能够用到的最大系统带宽,防止占用太多带宽
<property>
        <name>dfs.datanode.balance.bandwidthPerSec</name>
        <value>104857600</value>
</property>
# 设置每个机器的磁盘要预留两个G的数据,不能全部都给hdfs使用
# 设置存储的datanode机器的选择策略,优先以机器剩余磁盘存储两个G以上
<property>
    <name>dfs.datanode.du.reserved</name>
    <value>2147483648</value>
    <description>每个存储卷保留用作其他用途的磁盘大小</description>
</property>
<property>
    <name>dfs.datanode.fsdataset.volume.choosing.policy</name>
    <value>org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy</value>
    <description>存储卷选择策略</description>
</property>

<property>
    <name>dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold</name>
    <value>2147483648</value>
    <description>允许的卷剩余空间差值,2G</description>
</property>
# 设置客户端读取数据
# 如果读取数据的客户端和datanode在同一个机器上那么可以直接从本地读取数据,不需要走远程IO
<property>
    <name>dfs.client.read.shortcircuit</name>
    <value>true</value>
</property>
<property>
    <name>dfs.domain.socket.path</name>
    <value>/data/dn_socket_PORT</value>
</property>

HDFS 常用命令

标准写法

本地文件file:

hdfs路径:hdfs://ns1

ls

hadoop fs -ls hdfs://ns1/

简写

hadoop fs -ls /

-h

文件大小显示为最大单位,更加人性化

hadoop fs -ls -h /

-R

递归显示

hadoop fs -ls -R /

put

标准写法

put 左面:是本地,右面是hdfs集群

hadoop fs -put ~/demo.txt hdfs://ns1/

简写

右面默认找hdfs

hadoop fs -put ~/demo.txt /

上传时重名

hadoop fs -put  ~/demo.txt /demo1.txt

上传多个文件

上传多个文件的时候无法改名,最后只能是一个目录

hadoop fs -put a.txt b.txt  /

上传目录

hadoop fs -put ceshi / 

-f

覆盖上传

hadoop fs -put -f demo.txt /

put 原理(hdfs 写流程)

cat

读取文件,如果文件太大,不要用cat读取文件

hadoop fs -cat /data/demo.log

cat原理(hdfs 读流程)

get

下载hdfs文件或目录到本地目录

hadoop fs -get /demo.txt ./

下载hdfs文件到本地目录并重命名

hadoop fs -get /demo.txt ./nihao.txt

cp

拷贝文件/目录

上传本地文件使用file:开头,这就相当于put

hadoop fs -cp file:/home/hadoop/word.txt /

从hdfs进行拷贝

hadoop fs -cp /demo.txt /ceshi

mv

剪切文件

hadoop fs -mv /b.txt /ceshi

rm

删除文件/目录

执行-rm 命令后,默认是把文件移动到 user/hadoop/.Trash/Current 下,会根据配置文件配置的清理周期定期清理。

hadoop fs -rm /demo.txt

匹配模式删除所有文件

hadoop fs -rm /ceshi/*.log

删除目录(空目录)

hadoop fs -rmdir /ceshi

强制删除,并且递归删除文件夹中的内容

hadoop fs -rmr /ceshi

删除之后不放到回收站

hadoop fs -rm -skipTrash /a.txt

touchz

创建空文件

hadoop fs - touchz /aa.txt

mkdir

创建目录,可以同时创建多个目录

hadoop fs -mkdir /tmp1 /tmp2

同时创建父级目录

hadoop fs -mkdir -p /dir1/dir2/dir3

tail

读取文件尾部

查看尾部1K字节

hadoop fs -tail /demo1.txt

appendToFile

追加写入文件

将new.txt的内容追加到node.txt中

hadoop fs -appendToFile new.txt /note.txt

du

获取逻辑空间文件/目录大小

显示HDFS根目录中各文件和文件夹大小

hadoop fs -du /

以最大单位显示HDFS根目录中各文件和文件夹大小

hadoop fs -du -h /

仅显示HDFS根目录大小。即各文件和文件夹大小之和

hadoop fs -du -s -h /

setrep

改变文件副本数

-R

递归改变目录下所有文件的副本数。

-w

等待副本数调整完毕后返回。可理解为加了这个参数就是阻塞式的了。

hadoop fs -setrep -R -w 2 /demo.txt

count

获取HDFS目录的物理空间信息

  • 值1 代表目录个数
  • 值2 代表文件个数
  • 值3 是总大小
hadoop fs -count /

HDFS 高级命令

dfsadmin

-report

查看文件系统的基本信息和统计信息

hadoop dfsadmin -report

-safemode

安全模式命令。

安全模式是NameNode的一种状态,在这种状态下,NameNode不接受对元数据的更改(只读);不复制或删除块。NameNode在启动时自动进入安全模式,当配置块的最小百分数满足最小副本数的条件时,会自动离开安全模式。enter是进入,leave是离开 。

在安全模式情况下不允许任何hdfs的修改操作的,读是可以的

进入安全模式

hadoop dfsadmin  -safemode enter

离开安全模式

hadoop dfsadmin -safemode leave

获取安全模式信息

hadoop dfsadmin -safemode get

-rollEdits

手动滚动edits文件

hadoop dfsadmin -rollEdits

fsimage和edits文件详解

两个文件存放的目录/data/namenode/current

VERSION

VERSION是java属性文件,内容大致如下:

  1. namespaceID是文件系统唯一标识符
  2. clusterID是系统生成或手动指定的集群ID
  3. cTime表示Namenode存储的创建时间
  4. storageType表示这个文件存储的是什么进程的数据结构信息
  5. blockpoolID表示每一个namenode对应的块池id,这个id包括了其对应的Namenode节点的ip地址。
  6. layoutVersion表示HDFS永久性数据结构的版本信息,只要数据结构变更,版本号也要递减

edits_*文件

edits文件中存放的是客户端执行的所有更新命名空间的操作。

hdfs oev 解析操作日志文件并且输入到相应的目录中 -i 输入 -o 输出 -p 默认就是xml

hdfs oev -i edits_0000000000000000138-0000000000000000145 -o ~/edits.txt

查看edits文件

vim ~/edits.txt

seen_txid文件

这个文件中保存了一个事务id,这个事务id并不是Namenode内存中最新的事务id。这个文件的作用在于Namenode启动时,利用这个文件判断是否有edits文件丢失,Namenode启动时会检查seen_txid并确保内存中加载的事务id至少超过seen_txid,否则Namenode将终止启动操作。

fsimage_*文件

将fsimage数据导出到文本中

hdfs oiv -i fsimage_0000000000000000024 -o ~/fs.xml -p xml

fs.xml里面有

  • version:version描述的一些版本信息
  • NameSection:描述的是命名空间的一些信息
  • ErasureCodingSection:纠删码
  • INodeSection:INodeSection 由一段一段inode组成,是image中内容最大部分,除了上述的几个片段,image中剩下的内容全部都是inode。

手动合并元数据

先进入安全模式

hadoop dfsadmin  -safemode enter

手动触发合并元数据

hadoop dfsadmin -saveNamespace

fsimage_*.md5文件

md5校验文件,用于确保fsimage文件的正确性,可以作用于磁盘异常导致文件损坏的情况。

扩容datanode节点

当磁盘容量不够的时候需要对集群进行动态扩容,动态增加一个或者多个服务器。

  1. 连接新的服务器
  2. 创建hadoop用户并设置密码
    • useradd hadoop
    • passwd hadoop
  3. 安装jdk
    • rpm -ivh /public/software/java/jdk-8u144-linux-x64.rpm
  4. 配置s4的主机名
    • vim /etc/hostname
  5. 将s3上的hadoop安装目录传输到s4上,修改所有者和属组,并配置软连接
    • scp -r hadoop@s3:/usr/local/hadoop-3.1.4 /usr/local/
    • chown hadoop:hadoop -R /usr/local/hadoop-3.1.4
    • ln -s /usr/local/hadoop-3.1.4/ /usr/local/hadoop
  6. 将环境变量文件也拷贝一份
    • scp -r root@s3:/etc/profile /etc/
    • source /etc/profile
  7. 修改/data目录所有者和属组
    • chown hadoop:hadoop /data
  8. 修改 hosts文件
  9. 修改其他服务器,添加s4节点的映射
  10. 配置s4和其他服务器免密码登录
    • scp -r hadoop@s3:/home/hadoop/.ssh /home/hadoop/
    • 测试免密码登录是否正常
  11. 给workers文件添加s4
    • echo s4 >> /usr/local/hadoop/etc/hadoop/workers
  12. 在新增的s4节点启动datanode

datanode下线

需要修改hdfs-site.xml,将要删除的节点配置在文件中,然后配置文件的路径

<property>
    <name>dfs.hosts.exclude</name>
    <value>/usr/local/hadoop/etc/hadoop/excludes</value>
</property>

将配置文件分发到各个机器节点中

在nn1节点输入

hadoop dfsadmin -refreshNodes

s4上面的数据迁移到了其他节点上,此时s4下线成功

后续我们删除 workers中的s4节点,那么下次就不会启动它了

scp_all.sh /usr/local/hadoop/etc/hadoop/workers /usr/local/hadoop/etc/hadoop/

hdfs数据负载均衡

Hadoop的HDFS集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,例如:当集群内新增、删除节点,或者某个节点机器内硬盘存储达到饱和值。当数据不平衡时,Map任务可能会分配到没有存储数据的机器,这将导致网络带宽的消耗,也无法很好的进行本地计算。

当HDFS负载不均衡时,需要对HDFS进行数据的负载均衡调整,即对各节点机器上数据的存储分布进行调整。从而,让数据均匀的分布在各个DataNode上,均衡IO性能,防止热点的发生。进行数据的负载均衡调整,必须要满足如下原则:

  • 数据平衡不能导致数据块减少,数据块备份丢失
  • 管理员可以中止数据平衡进程
  • 每次移动的数据量以及占用的网络资源,必须是可控的
  • 数据均衡过程,不能影响namenode的正常工作

在Hadoop中,包含一个start-balancer.sh脚本,通过运行这个工具,启动HDFS数据均衡服务。该工具可以做到热插拔,即无须重启计算机和 Hadoop 服务。

启动命令为:‘start-balancer.sh –threshold`

影响Balancer的参数:

  • -threshold
  • 默认设置:10,参数取值范围:1-100
  • 参数含义:datanode间磁盘使用率相差阈值。理论上,该参数设置的越小,整个集群就越平衡。

启动数据均衡,默认阈值为 10%

start-balancer.sh

启动数据均衡,阈值 5%

start-balancer.sh -threshold 5

停止数据均衡

stop-balancer.sh

修改每个节点空间大小在hdfs-site.xml

<property>
    <name>dfs.datanode.du.reserved</name>
    <value>80484251153203</value>
    <description>每个存储卷保留用作其他用途的磁盘大小,不给hdfs用的大小</description>
</property>

机架感知策略

比如说有三个副本,如果都发放在同一个机架,那么这个机架宕机,导致数据丢失。

所以加入机架感知策略。

在hadoop2.7之后,如果开启机架感知策略,那么:

  • 第一个副本:如果是集群内部上传,哪个服务器上传的,就将第一个副本放到哪里;
  • 第二个副本:放到和第一个副本相同的机架,不同的节点上;
  • 第三个副本:放到和第二个副本不同的机架,找一台容量比较充足的进行存放。

我们这里说的机架式逻辑机架而不是物理机架,但是在真正配置的时候,一般逻辑机架,要和物理机架相对应。

默认情况下,Hadoop机架感知是没有启用的,需要在NameNode机器的hdfs-site.xml里配置一个选项

<property>  
    <name>topology.script.file.name</name>
    <value>/usr/local/hadoop/etc/hadoop/tp.py</value>
</property>

这个配置选项的 value 指定为一个可执行程序,通常为一个脚本,可以是shell脚本或者python脚本。

接受的参数通常为 datanode 机器的 ip 地址,而输出的值通常为该ip地址对应的 datanode 所在的rackID,例如”/rack1”。

Namenode 启动时,会判断该配置选项是否为空,如果非空,则表示已经启用机架感知的配置,此时namenode 会根据配置寻找该脚本,并在接收到每一个 datanode 的 heartbeat 时,将该 datanode 的ip地址作为参数传给该脚本运行,并将得到的输出作为该datanode 所属的机架,保存到内存的一个map中。

至于脚本的编写,就需要将真实的网络拓朴和机架信息了解清楚后,通过该脚本能够将机器的ip地址正确的映射到相应的机架上去。

当没有配置机架信息时,所有的datanode,hadoop都默认在同一个名为 “/default-rack”机架下。

编辑to.py文件,因为官网没有指出到底是根据ip还是hostname进行判断机架。所以我们都配置 如下在tp.py中

#!/usr/bin/python

#-*-coding:UTF-8 -*-


import sys

rack = {
        "sl1":"lmk_rack1",
        "sl2":"lmk_rack1",
        "sl3":"lmk_rack2",
        "192.168.149.53":"lmk_rack1",
        "192.168.149.54":"lmk_rack1",
        "192.168.149.55":"lmk_rack2"
        }

if __name__=="__main__":

    print "/" + rack.get(sys.argv[1],"rack0")

以上的内容根据/etc/hosts中的内容配置,这个时候在集群需要得到机器的远近的时候就可以通过传入ip或者hostname进行判断。

增加执行权限

ssh_all.sh chmod +x /usr/local/hadoop/etc/hadoop/tp.py

输入命令打印机架感知

hadoop dfsadmin -printTopology

重启hdfs之后查看

HDFS 1.0

Namenode是主 Datanode是从

NameNode是一个进程,在某一个机器(主节点)上,维护内存

内存里有2份重要的数据(元数据-通过Datanode心跳保证):

(1)文件名->block数据块的映射关系(mapping关系)

(2)block数据块->datanode节点地址映射关系

配合着:去访问响应的Datanode

(1)block数据块->真实数据存放的本地地址

NameNode 不存储数据,只存储数据的位置

数据块的副本:默认3个副本

Hadoop集群不适合存储大量的小文件

(1)资源浪费 (每个block64M,如果都存不满,就非常浪费)

(2)Namenode资源有限(文件越多,需要存储的映射就越多)

(3)集群里存在大量的压缩的小文件,启动mapreduce时候,会产生大量的map进程

(4)集群里存在大文件,启动mapreduce时候,并发能力不够,导致MR任务执行慢

1.0里只有一个 NN(Namenode),当时zookeeper没有

SecondaryNameNode:其实并不是Namenode的备份

SNN存在意义:备份、数据恢复

数据完整性校验:检测数据是否损坏

用什么方法:crc32算法产生校验和(hash值)

存在几种校验逻辑?

(1)Client写校验和,Datanode来校验

(2)Datanode存在后台进程(DataBlockScanner):定期

参考视频:https://www.bilibili.com/video/BV1ed4y177zf/?spm_id_from=333.337.search-card.all.click
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇