草庐IT

datanode单块盘故障导致节点失效之脚本解决

上官战 2023-03-28 原文
问题:

在hadoop的1.2.0中由于单个磁盘故障导致datanode节点失效,生产环境中datanode节点大多都有多块磁盘,我们现在需要一种方法,让datanode不会被单块磁盘的故障导致整个节点失效。


解决方法及适用场景:

1、修改hadoop源代码(介个在作者能力之外)

2、修改hdfs-site.xml中的dfs.data.dir的值,将故障盘的挂载点删除并重启(推荐在手动部署的hadoop环境中,将此方法做成脚本使用)

3、卸载故障盘,临时将数据写入根目录的挂载点,不修改配置文件(笔者的环境,使用hortonworks部署的hadoop,配置文件由ambari管理,手动修改后一旦使用ambari便会被同步回原来的配置...)


第三种解决方法的部分需求和代码实现

需求:

1、检测到故障盘的挂载点连续三次故障后再进行卸载并停止datanode以免错误判断

2、卸载故障盘后,检测到挂载点正常便启动datanode

3、在datanode启动后,依然能对故障盘进行nagios报警,以提醒管理员

4、管理员修复磁盘后,仅需手动停止datanode,并挂载修复后的磁盘即可,脚本会自动检测磁盘的挂载点并启动datanode

5、假设系统盘有一定可用容量,且一直是好的,因为当系统盘故障后...没有然后了...


代码实现:

#!/bin/bash # datanode的挂载点列表 MPT[0]=/storage/disk1/ MPT[1]=/storage/disk2/ # check_readonly 此脚本是用来检测datanode的挂载点是否可以,错误则必须输出有:ERROR DIRECTORY 关键字 CRD=/opt/nagios-bin/check_readonly # chk_rw.sh是nagios被动监控脚本,用来向nagios发送本地磁盘信息 RWS=/opt/nagios-bin/chk_rw.sh DPID=`cat /var/run/hadoop/hdfs/hadoop-hdfs-datanode.pid` KD=`ps aux|grep -v grep|grep $DPID` HOSTNAME=`uname -n` LIP=`grep $HOSTNAME /etc/hosts|awk '{print $1}'` CTF=/tmp/count.log [ ! -f "$CTF" ] && echo 0 > "$CTF" for i in ${MPT[@]};do CTE=`$CRD $i|grep "ERROR DIRECTORY"` NMP=`df $i|/usr/bin/tail -1|awk '{print $NF}'` # 判断datanode是否需要启动,并启动 if [[ -z "$CTE" && -z "$KD" ]];then chmod 777 $i &>/dev/null rm -rf "$i"/* &>/dev/null su - hdfs -c "/usr/lib/hadoop/bin/hadoop-daemon.sh --config /etc/hadoop/conf start datanode" &>/dev/null fi # 如果挂载点正常,判断是否需要将发送给nagios服务端的脚本信息修改为正常 if [[ -z "$CTE" && "$NMP" != "/" ]];then if grep "chkrw_state=2" $RWS &>/dev/null ;then sed -i '/chkrw_state=2/d' $RWS fi continue fi # 当挂载点故障或挂载到根目录时,进入如下判断 if [[ -n "$CTE" || "$NMP" == "/" ]];then DNP=`ps aux|grep -v grep|grep datanode|/usr/bin/wc -l` # 当挂载点正常,datanode进程正常,且挂载点为根时,跳出循环 [[ -z "$CTE" && "$NMP" == "/" && -n $DNP ]] && continue # 计数器,走到此步骤则+1,满足三次之后便进入如下判断 /usr/bin/expr `cat $CTF` + 1 > $CTF if [ `cat $CTF` -ge 3 ];then echo 0 > "$CTF" # 清零计数器,并修改想nagios发送信息的脚本 if ! grep "chkrw_state=2" $RWS &>/dev/null ;then sed -i '/chkrw_state=$?/achkrw_state=2' $RWS fi # 停止可能占用故障挂载点的进程并停止datanode以及卸载 PIDL=(`/usr/sbin/lsof $i|awk '{print $2}'|grep -v PID`) for p in ${PIDL[@]};do [ -z "$p" ] && continue kill -9 $p done /bin/umount $i &> /dev/null chmod -R 777 $i if [[ "$NMP" == "/" ]];then su - hdfs -c "/usr/lib/hadoop/bin/hadoop-daemon.sh --config /etc/hadoop/conf stop datanode" &>/dev/null [ -n "$KD" ] && kill -9 $DPID &> /dev/null else echo "`/bin/date +%k:%M:%S/%Y-%m-%d` $i umount fail." >> /tmp/check_mp.log fi fi fi done # 向nagios服务器发送本地磁盘信息 $RWS $LIP ${MPT[@]}


注:

   其中nagios方面的内容非本文重点,因此不再提供文中出现的对应脚本,如果需要,请联系笔者。

   另需考虑使用根目录的情况一段时间后,故障盘修复或更换后,重新挂载后数据迁移量问题,笔者考虑此问题时曾尝试将此时的系统盘挂载点的数据同步到新磁盘上(点击此处查看此版本),如果此操作在很短的时间内完成时可行的,但是当数据量很多时(譬如需同步500G甚至1T时),短时间必然无法完成,而同步后启动datanode,通过日志发现datanode报错数据节点的注册位置不一致(详细见下图),但是datanode进程并不会因此挂掉(事实上,不做任何操作,仅停止datanode一会,再启动就会显示此错误),考虑对此方法产生的问题暂时无法确定其后果,因此笔者本文中和生产环境中在使用挂载点时先清空里面的内容,因此启动后通过日志可看到hdfs在进行大量的数据同步操作。

   将此脚本按需要的频率,写入计划任务即可。


   写文不易,不正之处,欢迎指正,若觉得还能凑合,给个赞啊亲..


有关datanode单块盘故障导致节点失效之脚本解决的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  3. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  4. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  5. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  6. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  7. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

  8. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  9. ruby - ruby 脚本可以预编译成二进制文件吗? - 2

    我正在开发一个Ruby脚本,需要在没有Ruby解释器的情况下部署到系统上。它将需要在使用ELF格式的FreeBSD系统上运行。我知道有一个ruby​​2exe项目可以编译在Windows上运行的ruby​​脚本,但是在其他操作系统上这样做容易吗?甚至可能吗? 最佳答案 您是否检查过Rubinius或JRuby是否允许您预编译您的代码? 关于ruby-ruby脚本可以预编译成二进制文件吗?,我们在StackOverflow上找到一个类似的问题: https://

  10. ruby - 从另一个私有(private)方法中使用 self.xxx() 调用私有(private)方法 xxx,导致错误 "private method ` xxx' called” - 2

    我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是

随机推荐