一、概述

近年来,大数据技术如火如荼,怎样存储海量数据也成了当今的热点和难点问题,而HDFS分布式文件系统作为Hadoop项目的分布式存储基础,也为HBASE提供数据持久化功能,它在大数据项目中有很广泛的应用。

Hadoop分布式文件系统(Hadoop Distributed File System。HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。HDFS是Hadoop项目的核心子项目,是一种具有高容错性、高可靠性、高可扩展性、高吞吐量等特征的分布式文件系统,可用于云计算或其他大数据应用中海量数据的存储(主要为大文件的存储)。

本文结合作者本人及同事对HDFS的学习和实践的理解,首先介绍HDFS的特点和重要SHELL命令(hadoop和hdfs命令)的使用。接着介绍HDFS提供的C訪问接口LIB HDFS及其跟普通文件系统的C API的异同。然后介绍怎样利用LIB HDFS接口实现简单的HDFSclient并列举相关应用实例,最后针对编写HDFSclient中遇到的问题进行描写叙述和分析。

二、HDFS简单介绍

HDFS是Hadoop项目的核心子项目。是一种具有高容错性、高可靠性、高可扩展性、高吞吐量等特征的分布式文件系统。

1.HDFS特点

HDFS作为一种分布式文件系统,主要有以下特点:

1)主要用于存储和管理大数据文件(因为HDFS默认数据块为128M。所以它主要适合于存储百M级别及以上大小的文件)。

2)其数据节点可横向扩展,且可选择便宜的商业硬件。

3)设计理念为“一次写,多次读”。

4)当前不支持在文件任何位置改动文件内容。仅仅能在文件尾部运行append操作。

5)不适合低延迟(几十毫秒)数据訪问应用(低延迟应用能够考虑HBASE分布式数据库或者ES+分布式文件系统的架构)。

2.HDFS经常使用SHELL命令简单介绍

hadoop有两个很重要的SHELL命令:hadoop和hdfs。对于管理HDFS文件系统而言,hadoop和hdfs脚本功能有很大的反复性,以下以分别对这两个命令进行介绍。

1)hadoop命令使用

hadoop差点儿全部的管理命令都被整合到了一个SHELL脚本中,即bin/hadoop脚本,通过运行带參数的hadoop脚本。就能够实现hadoop模块的管理工作。

因为本文主要介绍HDFS文件系统。所以这里就主要介绍怎样使用hadoop脚本操作HDFS文件系统。相关命令及參数见图1所看到的。



图1 hadoop fs命令及參数描写叙述

以下举一个详细的样例。比如,要在HDFS文件系统中查看根文件夹包含的全部文件夹或文件,再创建test文件夹,并赋予777权限,最后删除该文件夹。实现以上操作的主要命令例如以下:

  1. hadoop fs ls /
  2. hadoop fs -mkdir /test
  3. hadoop fs chmod R 777 /test
  4. hadoop fs rmdir /test

hadoop fs命令能够实现用户组及权限的管理、文件夹和文件和管理、文件的上传和下载等功能,但对于HDFS文件系统的检查(包含坏块的清理)、节点管理、快照管理和格式化等深层次管理工作就无能为力了,这里就须要用到hdfs命令了。

2)hdfs命令使用

hdfs全部管理命令都被整合到了一个SHELL脚本中,即bin/hdfs脚本。通过运行带參数的hdfs脚本,就能够实现对HDFS文件系统的管理工作。包含主要的文件、文件夹、权限和属组操作以及数据块管理和格式化等功能。

hdfs脚本实现的功能很强大。hdfs dfs命令跟hadoop fs命令功能全然一致。所以我们能够利用hdfs dfs命令并携带图1中的參数实现hadoop fs的全部功能。以下主要介绍下HDFS文件系统格式化和数据块管理操作。

格式化一个HDFS文件系统,使用例如以下命令:

hdfs namenode -format

删除HDFS文件系统中存在的坏块及对应已损坏的文件,使用例如以下命令:

hdfs fsck -delete -files /

三、LIB HDFS接口简单介绍

Hadoop FileSystem APIs是JAVA CLIENT API。HDFS并没有提供原生的C语言訪问接口。

但HDFS提供了基于JNI的C调用接口LIB HDFS,为C语言訪问HDFS提供了很大的便利。

LIB HDFS接口的头文件和库文件已包含在Hadoop发行版本号中,能够直接使用。它的头文件hdfs.h一般位于HADOOPHOME/include目录中,而其库文件libhdfs.so通常则位于{HADOOP_HOME}/lib/native文件夹中。

因为Hadoop版本号一直在更新中,所以不同版本号的LIB HDFS接口功能通常不太一样,主要表现为功能递增的现象。

通过LIB HDFS訪问HDFS文件系统与使用C语言API訪问普通操作系统的文件系统相似,但还存在一些不足的地方,详细例如以下所看到的:

a)LIB HDFS接口实现的功能仅仅是JAVA CLIENT API功能的一个子集。且跟JAVA CLIENT API相比可能还存在不少BUG未被发现或修复,如多线程、多进程訪问文件系统时句柄资源释放的问题。

b)另外因为是使用JNI方式调用JAVA CLASS,所以应用程序占用内存较多,并且该接口运行可能会产生大量异常日志。怎么管理这些日志是个问题。另外,当操作HDFS文件系统出错时,errno不一定会有正确的提示,也会添加排查问题的难度。

c)眼下LIB HDFS可參考用例较少。而利用多线程等方式通过LIB HDFS大数据量读写HDFS文件系统的用例更是少之又少。

d)眼下LIB HDFS不支持在任何位置改动文件内容,仅仅能在文件末尾运行append操作。或对整个文件运行truncate操作。这个主要跟HDFS文件系统设计有关,大数据存储一般都缺乏更新功能的支持。这点我们仅仅能通过业务层面来规避了。

e)由低到高Hadoop发行版本号携带的LIB HDFS功能可能呈现递增的情况,所以每当Hadoop版本号更新了,都须要又一次编译我们的应用程序,添加升级难度。

眼下尽管LIB HDFS接口还存在一些不足的地方。但相信未来随着该接口版本号的不断更新,其功能和稳定性都会大大提高。

四、C语言訪问HDFS应用实践

1.编译和运行环境搭建

为了成功编译C语言client程序,我们须要预先安装7.0及以上版本号的JAVA JDK和Hadoop发行版,前者提供libjvm.so等库,后者则提供LIB HDFS连接所须要的库。

为了成功运行C语言client程序,除了预先安装上面提到的程序外,我们还须要正确地设置几个关键环境变量。包含LD_LIBRARY_PATH和CLASSPATH的设置。

关于LD_LIBRARY_PATH环境变量。主要是须要加入libjvm.so和libhdfs.so库所在路径;而针对CLASSPATH则须要囊括Hadoop提供的全部jar包的全路径信息(详细可通过find+awk组合命令来实现)。否则C语言client程序总会报缺少某个类而无法运行的错误。

2.LIB HDFS接口简单应用实践

这里主要介绍部分API的使用演示样例。

1)获取HDFS文件系统的容量和已使用空间大小信息如GetHdfsInfo函数所看到的:

  1. void GetHdfsInfo(void)
  2. {
  3. hdfsFS pfs = NULL;
  4. int iRet = 0;
  5. tOffset iTmp = 0;
  6. pfs = hdfsConnect("hdfs://127.0.0.1:9000/", 0); // 与HDFS文件系统建立连接
  7. if (NULL == pfs)
  8. {
  9. WRITELOGEX(LOG_ERROR, ("GetHdfsInfo(): hdfsConnect failed! errno=%d.", errno));
  10. return;
  11. }
  12. WRITELOG(LOG_INFO, "GetHdfsInfo(): hdfsConnect success!");
  13. iTmp = hdfsGetCapacity(pfs); // 获取HDFS文件系统容量
  14. if (-1 == iTmp)
  15. {
  16. WRITELOGEX(LOG_ERROR, ("GetHdfsInfo(): hdfsGetCapacity failed! errno=%d.", errno));
  17. hdfsDisconnect(pfs);
  18. pfs = NULL;
  19. return;
  20. }
  21. WRITELOGEX(LOG_INFO, ("GetHdfsInfo(): hdfsGetCapacity success! offset=%ld.", iTmp));
  22. iTmp = hdfsGetUsed(pfs); // 获取HDFS文件系统中全部文件占用空间大小,即已使用量
  23. if (-1 == iTmp)
  24. {
  25. WRITELOGEX(LOG_ERROR, ("GetHdfsInfo(): hdfsGetUsed failed! errno=%d.", errno));
  26. hdfsDisconnect(pfs);
  27. pfs = NULL;
  28. return;
  29. }
  30. WRITELOGEX(LOG_INFO, ("GetHdfsInfo(): hdfsGetUsed success! offset=%ld.", iTmp));
  31. iRet = hdfsDisconnect(pfs); // 关闭与HDFS文件系统的连接
  32. if (-1 == iRet)
  33. {
  34. WRITELOGEX(LOG_ERROR, ("GetHdfsInfo(): hdfsDisconnect failed! errno=%d.", errno));
  35. return;
  36. }
  37. WRITELOGEX(LOG_INFO, ("GetHdfsInfo(): hdfsDisconnect success! ret=%d.", iRet));
  38. pfs = NULL;
  39. return;
  40. }

2)在HDFS文件系统中新增文件并写入数据如HdfsWriteTest函数所看到的:

  1. void HdfsWriteTest(hdfsFS pfs)
  2. {
  3. int iRet = 0;
  4. hdfsFile pfile = NULL;
  5. char szTestFile[200] = "/test/ write.test";
  6. if (NULL == pfs)
  7. {
  8. WRITELOG(LOG_ERROR, "HdfsWriteTest():pfs is null.");
  9. return;
  10. }
  11. pfile = hdfsOpenFile(pfs, szTestFile, O_WRONLY || O_CREAT, 0, 0, 0); // 打开文件句柄
  12. if (NULL == pfile)
  13. {
  14. WRITELOGEX(LOG_ERROR, ("HdfsWriteTest(): hdfsOpenFile failed! szFilePath=%s,errno=%d.", szTestFile, errno));
  15. return;
  16. }
  17. WRITELOGEX(LOG_INFO, ("HdfsWriteTest(): hdfsOpenFile success! szFilePath=%s.", szTestFile));
  18. iRet = hdfsWrite(pfs, pfile, "hello world!", strlen("hello world!")); // 写入数据
  19. if (-1 == iRet)
  20. {
  21. WRITELOGEX(LOG_ERROR, ("HdfsWriteTest(): hdfsWrite failed! ret=%d,errno=%d.", iRet, errno));
  22. hdfsCloseFile(pfs, pfile);
  23. pfile = NULL;
  24. return;
  25. }
  26. WRITELOGEX(LOG_INFO, ("HdfsWriteTest(): hdfsWrite success! ret=%d.", iRet));
  27. iRet = hdfsHFlush(pfs, pfile); // 将缓冲区中数据写入磁盘
  28. if (-1 == iRet)
  29. {
  30. WRITELOGEX(LOG_ERROR, ("HdfsWriteTest(): hdfsFlush failed! ret=%d,errno=%d.", iRet, errno));
  31. hdfsCloseFile(pfs, pfile);
  32. pfile = NULL;
  33. return;
  34. }
  35. WRITELOGEX(LOG_INFO, ("HdfsWriteTest(): hdfsFlush success! ret=%d.", iRet));
  36. iRet = hdfsCloseFile(pfs, pfile); // 关闭文件句柄,释放资源
  37. if (-1 == iRet)
  38. {
  39. WRITELOGEX(LOG_ERROR, ("HdfsWriteTest(): hdfsCloseFile failed! ret=%d,errno=%d.", iRet, errno));
  40. return;
  41. }
  42. WRITELOGEX(LOG_INFO, ("HdfsWriteTest(): hdfsCloseFile success! ret=%d.", iRet));
  43. pfile = NULL;
  44. return;
  45. }

3.遇到的主要问题描写叙述与分析

对于LIB HDFS接口的不足之处,在本文第三部分(LIB HDFS接口简单介绍)已有大致描写叙述。

在实际性能測试过程中。因LIB HDFS接口引起的问题主要包含:lease租约回收异常和程序句柄资源释放异常等两大类。

我们换了多种測试模型,基本确认LIB HDFS接口在某些异常情况下(如频繁对同一个文件运行append操作)会产生上述问题。

所以假设在项目中须要实际应用LIB HDFS接口,就须要我们改进client程序处理流程,尽量规避和降低上述问题的产生。能够採用例如以下方法:

1)在client程序和HDFS文件系统间添加缓存的方式降低HDFS的读写密度;

2)降低对HDFS文件系统的更新操作,比如文件写入完毕后就不再运行append操作,仅仅运行read操作。

五、总结

本文对HDFS和用C语言訪问HDFS的操作进行了详细的介绍,可供相关项目的开发者參考。

HDFS作为一种分布式文件系统,并非万能的,比如并不适合于存储量太小或要求低訪问延迟的应用场景,又或者须要频繁更新数据的系统。即使应用了HDFS文件系统,为了发挥HDFS文件系统的最大效率,仍可能须要通过我们改动业务分层或逻辑实现等手段来规避HDFS的一些缺点。


本人微信公众号:zhouzxi,请扫描以下二维码:

HDFS简单介绍及用C语言訪问HDFS接口操作实践的更多相关文章

  1. Hadoop HDFS (3) JAVA訪问HDFS

    如今我们来深入了解一下Hadoop的FileSystem类. 这个类是用来跟Hadoop的文件系统进行交互的.尽管我们这里主要是针对HDFS.可是我们还是应该让我们的代码仅仅使用抽象类FileSyst ...

  2. Hadoop-2.6.0上的C的API訪问HDFS

    在通过Hadoop-2.6.0的C的API訪问HDFS的时候,编译和执行出现了不少问题,花费了几天的时间,上网查了好多的资料,最终还是把问题给攻克了 參考文献:http://m.blog.csdn.n ...

  3. Hadoop HDFS (3) JAVA訪问HDFS之二 文件分布式读写策略

    先把上节未完毕的部分补全,再剖析一下HDFS读写文件的内部原理 列举文件 FileSystem(org.apache.hadoop.fs.FileSystem)的listStatus()方法能够列出一 ...

  4. Hadoop自学笔记(二)HDFS简单介绍

    1. HDFS Architecture 一种Master-Slave结构.包括Name Node, Secondary Name Node,Data Node Job Tracker, Task T ...

  5. c语言訪问excel

    直接通过格式化读取文件就可实现,见附件

  6. C语言訪问MySQL数据库的方法

    1.加入头文件路径(MySQL安装路径中的include路径) 2.加入库文件(直接从MySQL安装路径中copy libmysql.lib就可以) 3.编程操作数据库 代码 // AccessToM ...

  7. FMDB(一)— 简单介绍

    在iOS开发过程中常常会用到数据库方面的操作,但是iOS原生的SQLite API使用起来并不十分友好,对于C语言基础较薄弱的朋友来说.使用起来可能会认为比較不便.于是,一些第三方的对SQLite A ...

  8. LuaInterface简单介绍

    LuaInterface简单介绍 Lua是一种非常好的扩展性语言.Lua解释器被设计成一个非常easy嵌入到宿主程序的库.LuaInterface则用于实现Lua和CLR的混合编程. (一)Lua f ...

  9. hibernate简单介绍

    1.   Hibernate是什么? hibernate是 轻量级的 ORM 框架. ORM全称object/relationmapping [对象/关系映射]. Hibernate主要用来实现Jav ...

随机推荐

  1. 记intel杯比赛中各种bug与debug【其一】:安装intel caffe

    因为intel杯创新软件比赛过程中,并没有任何记录.现在用一点时间把全过程重演一次用作记录. 学习 pytorch 一段时间后,intel比赛突然不让用 pytoch 了,于是打算转战intel ca ...

  2. vsftp迁移记录笔记

     由于之前的服务器用的window下的ftp安全性和稳定性都不好,所以我们才把ftp迁移到linux环境下 vsftp概述: vsftpd 它可以运行在多平台系统上面,是一个完全免费的.开放源代码的f ...

  3. FastDFS学习总结(1)--FastDFS安装和部署

    FastDFS是一个开源的,高性能的的分布式文件系统,他主要的功能包括:文件存储,同步和访问,设计基于高可用和负载均衡,FastDFS非常适用于基于文件服务的站点,例如图片分享和视频分享网站 Fast ...

  4. 绿色版SecureCRT启动崩溃,遇到一个致命的错误且必须关闭

    百度搜了半天,大家都是说删除注册表的VanDyke就能解决问题,但是我用的是绿色版的,删除VanDyke后还不行. 然后试了一下重新解压出一个绿色版的SecureCRT,发现能用. 但之前我配置了很多 ...

  5. python的开发工具UliPad安装篇

    之前文章里写过一个搭建windows下搭建Selenium+Eclipse+Python环境,如今认为这个Eclipse太大了,太笨重了,重新启动又慢,像Python脚本轻级语言,不是必需用那么大的工 ...

  6. [Recompose] Handle React Events as Streams with RxJS and Recompose

    Events are the beginning of most every stream. Recompose provides a createEventHandler function to h ...

  7. windows “文件大小”与“占用空间”、文件系统与文件拷贝

    0. 文件大小与占用空间 "文件大小"和"占用空间"的差别 首先需要明确的是,"文件大小"代表着文件的真实大小(文件内容实际包含的全部字节数 ...

  8. Gym - 100625J Jailbreak 最短路+搜索

    http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...

  9. dos 实用命令搜集

    dos 命令: 1.netstat -an 2.XP下打开凭证管理:  control keymgr.dll 3.刷新DHCP协议,重新自动获取IP *   ipconfig/release 命令来丢 ...

  10. layui图片懒加载-loading占位图

    前言 使用layui的图片懒加载,发现未加载的图片没有loading占位图,显示的是裂图,看着不是很好.找了一些解决方法我统一记录一下. layui图片懒加载使用方法 layui.use(’flow’ ...