一个HDFS集群,会有很多个datanode节点,每个datanode节点会挂载很多块磁盘。HDFS在存储数据时如何动态负载均衡最优化地往每个datanode,每个磁盘上存储数据呢?
其实没啥,DataNode在运行过程中,为了计算DN的capacity使用量,实现数据存储的动态均衡,DN会对已配置的数据存储路径(dfs.datanode.data.dir)进行du -sk操作,以此获得capacity使用量汇报给NN中,然后NN就知道哪些DN有空间能被写数据进去,哪些是空间不足的。

为了保证数据使用量的近实时性,目前DN是以默认10分钟的间隔时间执行一次。假设按照一个DN节点12个数据目录对应12块盘的情况,就会有12个du操作在每个10分钟内都会执行一次。在datanode存储的数据使用率比较高的时候,会十分消耗性能。直接引发阻塞io,系统load直线增高。
这种问题在大规模的集群中是很常见的,下面是针对线上(hadoop2.6版本的)简易零时的优化手段。说明:此问题仅存在于低于hadoop2.8版本,高于此版本已经修复。
https://issues.apache.org/jira/browse/HADOOP-9884
如果碰到这种情况,升级不了集群版本,那么我们还有其他奇技淫巧吗?
du原理简述:
du命令全程disk usage,它的统计原理在于将目标路径下的当前没有被删除的文件进行大小累加,然后得出总使用量。这种计算方式在文件数量少时往往不会表现出什么问题。但是当目标路径目录多,文件多的时候,du会表现出明显的时间执行耗时。
df 原理简述:
df命令统计值通过文件系统获取的。df命令的弊端是它不能按照具体目录进行使用量的统计。df是按照所在磁盘级别进行统计的。换句话说,用df命令在属于同一块物理盘的子路径下执行df命令,获取的值会是完全一致的。比较遗憾,这种情况将无法支持DataNode多block pool共用一块盘的情况。
处理方式:使用 df 命令替换 du
捕获到datanode执行过程中调用的 du -sk 命令,替换为df -k 。
实现脚本如下:
##将原始的 du指令更换名称
mv /usr/bin/du /usr/bin/du_bakvim /usr/bin/du#!/bin/sh
if [[ $2 == */current/BP-* ]] && [ $1 == -sk ]
then
used=`df -k $2 | grep -vE 'Used' | awk '{print $3}'`
echo -e "$used\t$2"
else
echo -e "$(du_bak $@)"
fichmod +x /usr/bin/du
跳板机(10.90.72.195)已经部署好ansible环境,配置主机名,执行ansible-playbook脚本即可。
执行路径:/home/tool/updata_datanodes_du
需要修改的配置文件:/home/tool/updata_datanodes_du/datanodes
执行脚本:./run.shupdata_du.yml
---
- hosts: all_datanodes
remote_user: root
gather_facts: F # 跳过gather_facts环节
serial: 70 #开启的并发数
tasks:
- name: "检查主机du是否已经被部署过"
stat:
path: "/usr/bin/du_bak"
register: file_stat
- name: "同步du脚本文件到目标主机"
copy: # 使用复制模块,进行文件分发,从本地主机分发到远程主机
src: '{{ item.src }}' # 源文件,变量定义多个源文件
dest: "/tmp/" # 文件复制到目标主机的目录
owner: root
group: root
mode: 0777
with_items: # 本地源文件列表
- { src: '/home/tool/updata_datanodes_du/scp_files/du' }
when: not file_stat.stat.exists
- name: "检查du文件是否同步成功"
stat:
path: "/tmp/du"
register: tmp_du_stat
- name: "备份du文件"
command: mv /usr/bin/du /usr/bin/du_bak
when: tmp_du_stat.stat.exists
- name: "更新为新的du脚本文件"
command: mv /tmp/du /usr/bin/du
when: tmp_du_stat.stat.exists
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/