HDFS 优化方案
1. 短路本地读取:Short Circuit Local Reads
1.背景
在HDFS中,不管是Local Reads(DFSClient和Datanode在同一个节点)还是Remote Reads(DFSClient和Datanode不在同一个节点),底层处理方式都是一样的,都是先由Datanode读取数据,然后再通过RPC(基于TCP)把数据传给DFSClient。这样处理是比较简单的,但是性能会受到一些影响,因为需要Datanode在中间做一次中转。尤其Local Reads的时候,既然DFSClient和数据是在一个机器上面,那么很自然的想法,就是让DFSClient绕开Datanode自己去读取数据
所谓的“短路”读取绕过了DataNode,从而允许客户端直接读取文件。显然,这仅在客户端与数据位于同一机器的情况下才可行。短路读取为许多应用提供了显着的性能提升。
2. 短路本地读取
在HDFS-2246这个JIRA中,工程师们的想法是既然读取数据DFSClient和数据在同一台机器上,那么Datanode就把数据在文件系统中的路径,从什么地方开始读(offset)和需要读取多少(length)等信息告诉DFSClient,然后DFSClient去打开文件自己读取。想法很好,问题在于配置复杂以及安全问题。
首先是配置问题,因为是让DFSClient自己打开文件读取数据,那么就需要配置一个白名单,定义哪些用户拥有访问Datanode的数据目录权限。如果有新用户加入,那么就得修改白名单。需要注意的是,这里是允许客户端访问Datanode的数据目录,也就意味着,任何用户拥有了这个权限,就可以访问目录下其他数据,从而导致了安全漏洞。因此,这个实现已经不建议使用了。
3. 短路本地读取安全性改进
在HDFS-347中,提出了一种新的解决方案,让短路本地读取数据更加安全。
Unix Domain Socket是一种进程间的通讯方式,它使得同一个机器上的两个进程能以Socket的方式通讯。它带来的另一大好处是,利用它两个进程除了可以传递普通数据外,还可以在进程间传递文件描述符。
假设机器上的两个用户A和B,A拥有访问某个文件的权限而B没有,而B又需要访问这个文件。借助Unix Domain Socket,可以让A打开文件得到一个文件描述符,然后把文件描述符传递给B,B就能读取文件里面的内容了即使它没有相应的权限。在HDFS的场景里面,A就是Datanode,B就是DFSClient,需要读取的文件就是Datanode数据目录中的某个文件。
这个方案在安全上就比上一个方案上好一些,至少它只允许DFSClient读取它需要的文件
4. 短路本地读取配置
libhadoop.so
因为Java不能直接操作Unix Domain Socket,所以需要安装Hadoop的native包libhadoop.so。在编译Hadoop源码的时候可以通过编译native模块获取。可以用如下命令来检查native包是否安装好。hadoop checknative
- hdfs-site.xml
dfs.client.read.shortcircuit
true
dfs.domain.socket.path
/var/lib/hadoop-hdfs/dn_socket
dfs.client.read.shortcircuit是打开短路本地读取功能的开关,dfs.domain.socket.path是Datanode和DFSClient之间沟通的Socket的本地路径。
2. HDFS Block负载平衡器:Balancer
1. 背景
HDFS数据可能并不总是在DataNode之间均匀分布。一个常见的原因是向现有群集中添加了新的DataNode。HDFS提供了一个Balancer程序,分析block放置信息并且在整个DataNode节点之间平衡数据,直到被视为平衡为止。
平衡器无法在单个DataNode上的各个卷之间进行平衡。
2. 命令行配置和运行
命令:
hdfs balancer --help
设置平衡数据传输带宽
命令:hdfs dfsadmin -setBalancerBandwidth newbandwidth
默认运行 balancer
命令:hdfs balancer
此时将会以默认参数进行数据块的平衡操作。
修改阈值运行balancer
命令:hdfs balancer -threshold 5
Balancer将以阈值5%运行(默认值10%),这意味着程序将确保每个DataNode上的磁盘使用量与群集中的总体使用量相差不超过5%。例如,如果集群中所有DataNode的总体使用率是集群磁盘总存储容量的40%,则程序将确保每个DataNode的磁盘使用率在该DataNode磁盘存储容量的35%至45%之间。
3.磁盘均衡器:HDFS Disk Balancer
1. 背景
相对于个人PC,服务器一般可以通过挂载对块磁盘来扩大单机的存储能力
在Hadoop HDFS中,DataNode负责最终数据block的存储,在所在机器上的磁盘之间分配数据块。当写入新block时,DataNodes将根据选择策略(循环策略或可用空间策略)来选择block的磁盘(卷)。
循环策略: 它将新block均匀分布在可用磁盘上。默认此策略。
可用空间策略: 此策略将数据写入具有更多可用空间(按百分比)的磁盘
但是,在长期运行的群集中采用循环策略时,DataNode有时会不均匀地填充其存储目录(磁盘/卷),从而导致某些磁盘已满而其他磁盘却很少使用的情况。发生这种情况的原因可能是由于大量的写入和删除操作,也可能是由于更换了磁盘。
另外,如果我们使用基于可用空间的选择策略,则每个新写入将进入新添加的空磁盘,从而使该期间的其他磁盘处于空闲状态。这将在新磁盘上创建瓶颈。
因此,需要一种Intra DataNode Balancing(DataNode内数据块的均匀分布)来解决Intra-DataNode偏斜(磁盘上块的不均匀分布),这种偏斜是由于磁盘更换或随机写入和删除而发生的。
因此,Hadoop 3.0中引入了一个名为Disk Balancer的工具,该工具专注于在DataNode内分发数据。
2. HDFS Disk Balancer简介
HDFS disk balancer是Hadoop 3中引入的命令行工具,用于平衡DataNode中的数据在磁盘之间分布不均匀问题。 这里要特别注意,HDFS disk balancer与HDFS Balancer是不同的:
HDFS disk balancer针对给定的DataNode进行操作,并将块从一个磁盘移动到另一个磁盘,是DataNode内部数据在不同磁盘间平衡;
HDFS Balancer平衡了DataNode节点之间的分布。
3. HDFS Disk Balancer功能
HDFS Disk balancer支持两个主要功能,即报告和平衡。
- 数据传播报告
了定义一种方法来衡量集群中哪些计算机遭受数据分布不均的影响,HDFS磁盘平衡器定义了HDFS Volume Data Density metric(卷/磁盘数据密度度量标准)和Node Data Density metric(节点数据密度度量标准)。
HDFS卷数据密度度量标准能够比较数据在给定节点的不同卷上的分布情况。
节点数据密度度量允许在节点之间进行比较。
- Volume data density metric计算过程
假设有一台具有四个卷/磁盘的计算机-Disk1,Disk2,Disk3,Disk4,各个磁盘使用情况:
Disk1 | Disk2 | Disk3 | Disk4 | |
---|---|---|---|---|
capacity | 200 GB | 300 GB | 350 GB | 500 GB |
dfsUsed | 100 GB | 76 GB | 300 GB | 475 GB |
dfsUsedRatio | 0.5 | 0.25 | 0.85 | 0.95 |
volumeDataDensity | 0.20 | 0.45 | -0.15 | -0.24 |
Total capacity= 200 + 300 + 350 + 500 = 1350 GB
Total Used= 100 + 76 + 300 + 475 = 951 GB
因此,每个卷/磁盘上的理想存储为:
Ideal storage = total Used ÷ total capacity= 951÷1350 = 0.70
也就是每个磁盘应该保持在 70%理想存储容量。
VolumeDataDensity = idealStorage – dfs Used Ratio
比如Disk1的卷数据密度= 0.70-0.50 = 0.20。其他Disk以此类推。
volumeDataDensity的正值表示磁盘未充分利用,而负值表示磁盘相对于当前理想存储目标的利用率过高。
Node Data Density计算过程
Node Data Density(节点数据密度)= 该节点上所有卷/磁盘volume data density绝对值的总和。
上述例子中的节点数据密度=|0.20|+|0.45|+|-0.15|+|-0.24| =1.04
较低的node Data Density值表示该机器节点具有较好的扩展性,而较高的值表示节点具有更倾斜的数据分布。
一旦有了volumeDataDensity和nodeDataDensity,就可以找到集群中数据分布倾斜的节点,或者可以获取给定节点的volumeDataDensity。- 磁盘平衡
当指定某个DataNode节点进行disk数据平衡,就可以先计算或读取当前的volumeDataDensity(磁盘数据密度)。有了这些信息,我们可以轻松地确定哪些卷已超量配置,哪些卷已不足。为了将数据从一个卷移动到DataNode中的另一个卷,Hadoop开发实现了基于RPC协议的Disk Balancer。
4. HDFS Disk Balancer开启
HDFS Disk Balancer通过创建计划进行操作,该计划是一组语句,描述应在两个磁盘之间移动多少数据,然后在DataNode上执行该组语句。计划包含多个移动步骤。计划中的每个移动步骤都具有目标磁盘,源磁盘的地址。移动步骤还具有要移动的字节数。该计划是针对可操作的DataNode执行的。
默认情况下,Hadoop群集上已经启用了Disk Balancer功能。通过在hdfs-site.xml中调整dfs.disk.balancer.enabled参数值,选择在Hadoop中是否启用磁盘平衡器。
5. HDFS Disk Balancer相关命令
Plan 计划
命令:hdfs diskbalancer -plan
-out //控制计划文件的输出位置 -bandwidth //设置用于运行Disk Balancer的最大带宽。默认带宽10 MB/s。 –thresholdPercentage //定义磁盘开始参与数据重新分配或平衡操作的值。默认的thresholdPercentage值为10%,这意味着仅当磁盘包含的数据比理想存储值多10%或更少时,磁盘才用于平衡操作。 -maxerror //它允许用户在中止移动步骤之前为两个磁盘之间的移动操作指定要忽略的错误数。 -v //详细模式,指定此选项将强制plan命令在stdout上显示计划的摘要。 -fs //此选项指定要使用的NameNode。如果未指定,则Disk Balancer将使用配置中的默认NameNode。 Execute 执行
命令:hdfs diskbalancer -execute
execute命令针对为其生成计划的DataNode执行计划。
Query 查询
命令:hdfs diskbalancer -query
query命令从运行计划的DataNode获取HDFS磁盘平衡器的当前状态。
Cancel 取消
命令:hdfs diskbalancer -cancel
hdfs diskbalancer -cancel planID node cancel命令取消运行计划。
- Report 汇报
命令:hdfs diskbalancer -fs https://namenode.uri -report
4. 纠删码技术: Erasure Coding
1. 背景: 3副本策略弊端
为了提供容错能力,HDFS会根据replication factor(复制因子)在不同的DataNode上复制文件块。默认复制因子为3(注意这里的3指的是1+2=3,不是额外3个),则原始块除外,还将有额外两个副本。每个副本使用100%的存储开销,因此导致200%的存储开销。这些副本也消耗其他资源,例如网络带宽。
在复制因子为N时,存在N-1个容错能力,但存储效率仅为1/N。
这种复制增加了存储开销,并且似乎很昂贵。因此,HDFS使用Erasure Coding(纠删码)代替复制,以提供相同级别的容错能力,并且存储开销不超过50%。
Erasure Coding文件的复制因子始终为1,用户无法对其进行更改。
2. Erasure Coding(EC)简介
纠删码技术(Erasure coding)简称EC,是一种编码容错技术。最早用于通信行业,数据传输中的数据恢复。它通过对数据进行分块,然后计算出校验数据,使得各个部分的数据产生关联性。 当一部分数据块丢失时,可以通过剩余的数据块和校验块计算出丢失的数据块。
Hadoop 3.0 之后引入了纠删码技术(Erasure Coding),它可以提高50%以上的存储利用率,并且保证数据的可靠性。
存储系统RAID使用纠删码。RAID通过striping(条带化)实现纠删码,也就是说,将逻辑上连续的数据(例如文件)划分为较小的单位(bit, byte, or block),并将连续的单位存储在不同的磁盘上。
对于原始数据集的每个条带,都会根据纠删码算法来计算并存储一定数量的奇偶校验单元,该过程称为编码。
任何条带化单元中的错误都可以根据剩余数据和奇偶校验单元从计算中恢复,此过程称为解码。
3. Reed-Solomon(RS)码
- RS 码介绍
Reed-Solomon(RS)码是存储系统较为常用的一种纠删码,它有两个参数k和m,记为RS(k,m)。如下图所示,k个数据块组成一个向量被乘上一个生成矩阵(Generator Matrix)GT从而得到一个码字(codeword)向量,该向量由k个数据块和m个校验块构成。如果一个数据块丢失,可以用(GT)-1乘以码字向量来恢复出丢失的数据块。RS(k,m)最多可容忍m个块(包括数据块和校验块)丢失。 - RS 码通俗解释
比如有 7、8、9 三个原始数据,通过矩阵乘法,计算出来两个校验数据 50、122。这时原始数据加上校验数据,一共五个数据:7、8、9、50、122,可以任意丢两个,然后通过算法进行恢复。
4. Hadoop EC 架构
为了支持纠删码,HDFS体系结构进行了一些更改调整。
- NameNode 扩展
条带化的HDFS文件在逻辑上由block group(块组)组成,每个块组包含一定数量的内部块。这允许在块组级别而不是块级别进行文件管理。 - 客户端扩展
客户端的读写路径得到了增强,可以并行处理块组中的多个内部块。 - DataNode扩展
DataNode运行一个附加的ErasureCodingWorker(ECWorker)任务,以对失败的纠删编码块进行后台恢复。 NameNode检测到失败的EC块,然后NameNode选择一个DataNode进行恢复工作。 - 纠删码策略
为了适应异构的工作负载,允许HDFS群集中的文件和目录具有不同的复制和纠删码策略。纠删码策略封装了如何对文件进行编码/解码。默认情况下启用RS-6-3-1024k策略, RS表示编码器算法Reed-Solomon,6 、3中表示数据块和奇偶校验块的数量,1024k表示条带化单元的大小。
目录上还支持默认的REPLICATION方案。它只能在目录上设置,以强制目录采用3倍复制方案,而不继承其祖先的纠删码策略。此策略可以使3x复制方案目录与纠删码目录交错。REPLICATION始终处于启用状态。
此外也支持用户通过XML文件定义自己的EC策略,Hadoop conf目录中有一个名为user_ec_policies.xml.template的示例EC策略XML文件,用户可以参考该文件。 - Intel ISA-L
英特尔ISA-L代表英特尔智能存储加速库。 ISA-L是针对存储应用程序而优化的低级功能的开源集合。它包括针对Intel AVX和AVX2指令集优化的快速块Reed-Solomon类型擦除代码。 HDFS纠删码可以利用ISA-L加速编码和解码计算。
5. Erasure Coding部署方式
- 集群和硬件配置
编码和解码工作会消耗HDFS客户端和DataNode上的额外CPU。
纠删码文件也分布在整个机架上,以实现机架容错。这意味着在读写条带化文件时,大多数操作都是在机架上进行的。因此,网络带宽也非常重要。
对于机架容错,拥有足够数量的机架也很重要,每个机架所容纳的块数不超过EC奇偶校验块的数。
机架数量=(数据块+奇偶校验块)/奇偶校验块后取整。比如对于EC策略RS(6,3),这意味着最少3个机架(由(6 + 3)/ 3 = 3计算),理想情况下为9个或更多,以处理计划内和计划外的停机。对于机架数少于奇偶校验单元数的群集,HDFS无法维持机架容错能力,但仍将尝试在多个节点之间分布条带化文件以保留节点级容错能力。因此,建议设置具有类似数量的DataNode的机架。 - 纠删码策略配置
纠删码策略由参数dfs.namenode.ec.system.default.policy指定,默认是RS-6-3-1024k,其他策略默认是禁用的。可以通过hdfs ec [-enablePolicy -policy]命令启用策略集。 启用英特尔ISA-L
默认RS编解码器的HDFS本机实现利用Intel ISA-L库来改善编码和解码计算。要启用和使用Intel ISA-L,需要执行三个步骤。- 建立ISA-L库;
- 使用ISA-L支持构建Hadoop;
- 使用-Dbundle.isal将isal.lib目录的内容复制到最终的tar文件中。使用tar文件部署Hadoop。确保ISA-L在HDFS客户端和DataNode上可用。
6. EC命令
- [-setPolicy -path
[-policy ] [-replicate]]
在指定路径的目录上设置擦除编码策略。
path:HDFS中的目录。这是必填参数。设置策略仅影响新创建的文件,而不影响现有文件。
policy:用于此目录下文件的擦除编码策略。默认RS-6-3-1024k策略。
-replicate在目录上应用默认的REPLICATION方案,强制目录采用3x复制方案。
-replicate和-policy
- [-getPolicy -path < path >]
获取指定路径下文件或目录的擦除编码策略的详细信息。 - [-unsetPolicy -path < path >]
取消设置先前对目录上的setPolicy的调用所设置的擦除编码策略。如果该目录从祖先目录继承了擦除编码策略,则unsetPolicy是no-op。在没有显式策略集的目录上取消策略将不会返回错误。 - [-listPolicies]
列出在HDFS中注册的所有(启用,禁用和删除)擦除编码策略。只有启用的策略才适合与setPolicy命令一起使用。 - [-addPolicies -policyFile <文件>]
添加用户定义的擦除编码策略列表。 - [-listCodecs]
获取系统中支持的擦除编码编解码器和编码器的列表。 - [-removePolicy -policy
]
删除用户定义的擦除编码策略。 - [-enablePolicy -policy
]
启用擦除编码策略。 - [-disablePolicy -policy
]
禁用擦除编码策略。
二.HDFS 优化方案
1.背景
已有HDFS集群容量已经不能满足存储数据的需求,需要在原有集群基础上动态添加新的DataNode节点。就是俗称的动态扩容。
旧的服务器需要进行退役更换,暂停服务,需要在当下的集群中停止某些机器上HDFS的服务,俗称动态缩容。
2. 动态扩容、节点上线
新机器基础环境准备
- 主机名 IP
确保新机器IP和已有HDFS集群所属同一网段
- SSH 免密登录
为了后续脚本一键启动关闭集群方便,设置NameNode到新机器的免密登录
- 运行命令:ssh-keygen -t rsa
默认在 ~/.ssh目录生成两个文件:
id_rsa :私钥
id_rsa.pub :公钥 导入公钥到认证文件,更改权限
- 导入本机
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
- 导入要免密码登录的服务器
scp ~/.ssh/id_rsa.pub xxx@host:/home/id_rsa.pub
- 然后,将公钥导入到认证文件(这一步的操作在服务器上进行)
cat /home/id_rsa.pub >> ~/.ssh/authorized_keys
在服务器上更改权限 (很重要,如果不这么设置,就是不让你免密登录)
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
最后在本地登录服务器
ssh -v hostname@hostip
- JDK 环境
2. Hadoop 配置
1. NameNode 节点配置
修改namenode节点workers配置文件,增加新节点主机名,便于后续一键启停。
2. 新机器配置
从namenode节点复制hadoop安装包到新节点,注意不包括hadoop.tmp.dir指定的数据存储目录。
新机器上配置hadoop环境变量vim /etc/profile export HADOOP_HOME=/export/server/hadoop-3.1.4 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin source /etc/profile
3. 手动启动DataNode 进程
Hadoop fs --daemon start datanode
4. Hadoop web 页面查看
5. DataNode 负载均衡服务
新加入的节点,没有数据块的存储,使得集群整体来看负载不均衡。因此最后还需要对hdfs负载设置均衡。首先设置数据传输带宽。
hdfs dfsadmin -setBalancerBandwidth 104857600
然后启动Balancer,等待集群自均衡完成即可。
hdfs balancer -threshold 5
3.动态缩容、节点下线
1. 添加退役节点
在namenode机器的hdfs-site.xml配置文件中需要提前配置dfs.hosts.exclude属性,该属性指向的文件就是所谓的黑名单列表,会被namenode排除在集群之外。如果文件内容为空,则意味着不禁止任何机器。
提前配置好的目的是让namenode启动的时候就能加载到该属性,只不过还没有指定任何机器。否则就需要重启namenode才能加载,因此这样的操作我们称之为具有前瞻性的操作。
编辑dfs.hosts.exclude属性指向的excludes文件,添加需要退役的主机名称。
注意:如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役。2. 刷新集群
在namenode所在的机器刷新节点:hdfs dfsadmin -refreshNodes
等待退役节点状态为decommissioned(所有块已经复制完成)3. 手动关闭DataNode 进程
hdfs --daemon stop datanode
4. DataNode负载均衡服务
如果需要可以对已有的HDFS集群进行负载均衡服务。
hdfs balancer -threshold 5
4. 黑白名单机智
1. 白名单
所谓的白名单指的是允许哪些机器加入到当前的HDFS集群中,是一种准入机制。
白名单由dfs.hosts参数指定,该参数位于hdfs-site.xml。默认值为空。
dfs.hosts指向文件,该文件包含允许连接到namenode的主机列表。必须指定文件的完整路径名。如果该值为空,则允许所有主机准入。2. 黑名单
所谓的黑名单指的是禁止哪些机器加入到当前的HDFS集群中,是一种禁入机制。
黑名单由dfs.hosts.exclude参数指定,该参数位于hdfs-site.xml。默认值为空。
dfs.hosts.exclude指向文件,该文件包含不允许连接到名称节点的主机列表。必须指定文件的完整路径名。如果该值为空,则不禁止任何主机加入。- 主机名 IP