今天又重新搭建了一遍 Hadoop 和 Hive 运行环境,搭建过程中虽然遇到不少问题,但几乎都是之前已经遇到过的,算是都轻易化解了。但是,最后在测试 Hive 环境时,遇到了问题。

在 Hive 的终端下,执行 show tables,错误信息如下:

		hive> show tables;
		FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient

这个错误并不陌生。为了得到更精确的错误信息,执行命令:

$ hive --service metastore

错误信息如下(简化版,更完整的错误信息在此):

		Exception in thread "main" javax.jdo.JDODataStoreException: Error(s) were found while auto-creating/validating the datastore for classes. The errors are printed in the log, and are attached to this exception.
		NestedThrowablesStackTrace:
		java.sql.SQLException: The table 'DBS' is full
		...
		java.sql.SQLException: The table 'DATABASE_PARAMS' is full

需要说明一点,配置 Hive 时采用的元数据库是 MySQL。根据错误信息来看,我觉得问题应该出在 Hive 或 MySQL 这一层。在 MySQL 的终端下,show tables 可以看到一些表确实没有被创建。

随便重试几次,发现问题依旧;然后,想到可能是有残留信息(Hive 的整个安装目录是从一台已配置成功的服务器上同步过来的)的缘故,于是改用原始的 Hive 安装包,只保留几个纯文本的配置文件,问题依旧;反复换各种关键词 Google,无果。

……

 

转机发生在 df 命令的执行结果上,由于这台 master 结点硬盘空间比较小(10G 多点儿),而且分区很不合理,所以需要经常观察磁盘占用率。df -hT,执行结果如下:

hduser@master:/$ df -hT
Filesystem             Type      Size  Used Avail Use% Mounted on
/dev/mapper/wa205-root ext4      2.3G  1.9G  315M  86% /
udev                   devtmpfs  2.0G  4.0K  2.0G   1% /dev
tmpfs                  tmpfs     811M  240K  811M   1% /run
none                   tmpfs     5.0M     0  5.0M   0% /run/lock
none                   tmpfs     2.0G     0  2.0G   0% /run/shm
/dev/sda1              ext2      228M   25M  192M  12% /boot
/dev/mapper/wa205-home ext4      5.2G  2.1G  2.9G  42% /home
overflow               tmpfs     1.0M  832K  192K  82% /tmp
/dev/sdb1              ext4      2.3G  1.9G  315M  86% /

不难发现,/tmp 目录挂载结果很奇怪:文件系统类型为 overflow;大小仅 1M;用 lsblk 命令看不到对应的物理磁盘分区。

再次 Google 之,有收获:0 , 1 , 2 , 3 , 4 , 5 , 6

说下我的理解:

  • /tmp overflow 是一种保护机制,是为了应对磁盘空间不足的状况:当没有给 /tmp 单独分区且根目录 / 使用率过高时,通过限制 /tmp 目录的大小来节省磁盘空间。如果 /tmp 是单独分区的,则没有该现象。
  • 限制大小默认为 1M。
  • /tmp 对应的是 ram memory,不是真实的物理磁盘分区,用 lsblk 自然看不到。

 

按照上面链接提供的方法,禁用 /tmp overflow 这一 feature/bug:

  1. 停止 MySQL daemon(因为 MySQL daemon 使用了 /tmp 目录):
    service mysql stop
  2. 查看还有哪些程序占用了 /tmp 目录(需要自己分别处理之):
    lsof /tmp
  3. 卸载 /tmp目录:
    umount /tmp
  4. 禁用 /tmp overflow
    echo 'MINTMPKB=0' > /etc/default/mountoverflowtmp

OK! /tmp overflow 禁用掉了,Hive 也正常了。

至于原因嘛,应该是 Hive 运行时产生的日志文件(多个)在 /tmp/hadoop_user/ 目录下,由于 /tmp 大小受限制、空间已满,导致 Hive 无法正常工作,也无法向 MySQL 中写入元数据。

 

接下来开始吐槽。

先吐槽 Hive。错误信息不搭边,跟实际原因没什么关联,反而有误导。当然,其实大部分时侯,从 Hive 的错误信息还是能看出些端倪来的。

再喷 /tmp overflow

  • 不会自动取消,只能手动处理掉。也就是说,如果你的机器曾经出现了该问题,那么即使以后你的磁盘空间又变得充足了,该问题依然存在、不会自动取消,直到你自己手动解决掉这个问题。
  • 默认上限 1M,显然太小了。多运行几个程序,或者较长时间不关机,/tmp 目录很有可能会塞满、进而导致某些程序出错。
  • 它是在用一种不合理(dirty?)的方法来避免某一问题的发生,而没有意识到它本身却成了问题。如上所述,这种机制本身就有可能成为问题(从前文 Google 出来的几个链接也可以看出来),而且这个问题出现在它试图解决的那个问题(根目录 / 磁盘占用率过高)之前。难不成它是想以这种「用心良苦」的方式来提醒用户根目录磁盘占用率过高?
  • 试图避免(也可以理解为「隐藏」)问题,不符合 Fail fast 的理念。与其隐藏问题、「苟延残喘」地运行着,不如尽早暴露问题,用户也有机会更早地意识到并解决它。
  • 增加了解决问题的复杂度。如果问题仅仅是磁盘空间占满,你会怎么做呢?df 发现问题后,删掉磁盘上不再需要的文件,或者增加磁盘空间(物理机,可以挂载一块儿新硬盘;虚拟机,调大磁盘空间)即可。但是如果你是第一次遇到 /tmp overflow 的问题呢?你需要 Google 了解什么是 /tmp overflow、为什么会产生该现象、应该如何解决它……而且,最终你还是得面对并解决磁盘空间不足的问题。

总的来说,我觉得 /tmp overflow 这一机制是在制造更多的问题,却没能解决原有的问题。磁盘空间不足的问题偶有发生,在没有发现更好的方法之前,我宁愿自己手动管理解决此类问题,而不是用 /tmp overflow 这种「自以为是」的奇怪方法。

 

其它关于 /tmp overflow

/tmp overflow 机制在 Debian Squeeze 和 Ubuntu server 12.04 上有,其它 Linux 环境暂时未知。

设置 /tmp overflow 大小上限:

sudo mount -t tmpfs -o size=1048576,mode=1777 overflow /tmp

 

本文环境:Ubuntu 12.04 LTS,64 位

Leave a Reply

Your email address will not be published. Required fields are marked *