JDFS:一款分布式文件管理系统,第四篇(流式云存储续篇)
一 前言
本篇博客是JDFS系列博客的第四篇,从最初简单的上传、下载,到后来加入分布式功能,背后经历了大量的调试,尤其当实验的虚拟计算结点数目增加后,一些潜在的隐藏很深的bug就陆续爆发。在此之前笔者并没有网络编程的经验,大约半年之前读到unix环境高级编程的socket章节,然后就突然对网络编程产生了兴趣,于是后来就想着写一款http远程下载小工具(是笔者另外一篇博客,链接请点击我)。再到后来,由于笔者之前读研期间接触过map-reduce,知道HDFS这个东西,于是突发奇想,不如自己动手写一款类似于HDFS的小巧的分布式文件管理系统,这便是JDFS诞生的来历。笔者开发JDFS的目的,其一是想体验、巩固一下网络编程的知识;其二是想培养实现一个功能上较为完善有一定复杂性的系统;其三也许将来笔者会着手写一个小巧的map-reduce引擎,引擎就可以使用JDFS作为中间计算结果的存储。
上一篇博客主要介绍了客户端如何把本地文件分片后流式、冗余地存储到虚拟集群里的结点里,本篇将会接着上一篇博客介绍如下几个话题:客户端向name node查询文件的元信息,并且显示在终端界面上;客户端查询完文件元信息后,向不同的data node请求下载原始文件的不同分片到本地,并且在本地合并所有分片,恢复原始文件的面貌;客户端向name node请求删除虚拟集群里面的某个文件。在前三篇博客提到的一些点,本文不会再重复赘述,因此如果读者朋友是第一次阅读本文,笔者建议最好先阅读前三篇博客,链接在下面。
- JDFS:一款分布式文件管理实用程序第一篇(线程池、epoll、上传、下载) 点击我
- JDFS:一款分布式文件管理实用程序第二篇(更新升级、解决一些bug) 点击我
- JDFS:一款分布式文件管理系统,第三篇(流式云存储) 点击我
代码已经更新到github上面,请点击我
PS: 本篇博客是博客园用户“cs小学生”的原创作品,转载请注明原作者和原文链接,谢谢。
二 实验结果展示
按照管理,先展示几张实验过程的截图

如上图所示,左边是命令行,fileinfo.sh 是向name node查询文件元信息并显示出来,从图上可以看出,CRLS-en.pdf由5个block组成,每一个block分别被冗余地存储在data node 1,3,4上面(目前代码实现的时候简单地把每一个block存储于相同的几个结点上,后续会专门实现一个为每一个block挑选结点的函数)。接着./fetchfile.sh 是把存储在虚拟集群结点上的CRLS-en.pdf的各个block下载到本地并合并还原,还原后的截图如右边那种图显示。双击打开CRLS-en.pdf的截图如下:

三 获取并显示文件元信息
在上一篇博客里,我们说过,文件的正文存储在data node上面,而描述文件元信息的文件存储在name node上。在JDFS的设计里,name node对每个将要存储到虚拟集群里的文件会在name node端创建一个同名的文件,文件里存储对应的元信息,按照存储的顺序包括如下信息:
- 文件名。元信息文件的开头100个字节用来存储文件的名字
- 文件的状态。一个int型的数据,值如果是0表示该文件还没有存储成功,1表示文件已经存储成功,2表示文件等待被删除(每一个data node删除自己的block后,name node才能最后删除元信息文件)
- block数目。一个int型的数据,表示该文件由多少个block组成,比如在本文的实验中,CRLS-en.pdf由5个block组成
- 每一个block的信息,加入block的数目是N,name接下来会有连续的N*max_num_of_nodes*sizeof(int)的存储空,其中max_num_of_nodes表示数据结点的最大数目,假设block 2 打算存储在第m个数据结点上,那么初始情况下(2-1)*max_num_of_nodes*sizeof(int)+(m-1)处的初始值应当被name node设置为1,表示期待存储在该结点上,如果后续data node成功接收到block 2后会告诉name node,然后name node会把该位置的值从1更新为2表示已经ok了。对于其他空闲的结点就初始化为0,表示block2不会存储在该node上。
那么现在客户端想在终端上显示文件的元信息,就必须首先向name node请求上述的文件元信息,获取后解析出来,然后打印在终端上面,客户端实现了下面两个函数来支持该功能:
int JDFS_cloud_query_file(char *file_name, JDFS_file_info *jfi,int flag);//flag, 0: query for reading ,1 :query for deleting
int JDFS_cloud_display_file_info(char *file_name);
函数JDFS_cloud_query_file()便是用来具体向name node请求文件元信息用的,该函数还可以被删除功能调用,因此需要加一个参数flag来区分,不同的flag, name node做的事情不同。JDFS_cloud_display_file_info()调用前者来获取文件元信息,然后解析打印之,具体的代码逻辑也比较直接,请参考前言里给出的github代码链接。
对应的name node端响应这个请求的函数如下,对应的http request_kind是13
void *Http_server_callback_query_file_meta_info(void *arg);
四 从虚拟结点里下载文件到本地
截止到目前我们已经实现了把文件存储到虚拟集群里的结点上,也实现了查询特定文件元信息的功能,现在我们需要把文件下载到本地。
想象一下,我们要把“云端”的数据下载到本地要经历哪些过程呢?首先客户端需要向name node查询元信息,元信息里包含了文件的block数目N,对于每个block客户端从元信息里解析出它冗余地存储在哪些结点里,然后挑选一个最优的结点将之下载到本地。在实际的场景中,挑选结点是有讲究的,如果同一个机柜里的结点有这个block,就从这个机柜里下载,否则需要从其他机柜里的某个结点下载。但是在JDFS中暂时把这个挑选的功能简化为直接指定某个结点,未来会细化这一块,目的是使得现在面临的问题不至于太复杂。文件元信息里面存储了包含这个block的结点串号,光是有串号还不行,客户端需要用这个串号向name node查询对应的ip地址和端口号(目前JDFS中简单地设置端口为8888),于是对于每一个block我就得到了<block num, ip, port>这组信息,有了这些信息我们就可以向对应的结点请求传送该block了,所有block传输到客户端后,客户端需要把这N个block合并成一个整体。
在客户端我们实现了下面几个函数来支持该功能:
int JDFS_cloud_query_file(char *file_name, JDFS_file_info *jfi,int flag);//flag, 0: query for reading ,1 :query for deleting
int JDFS_cloud_query_ip_from_node_serial(int serial_num, char *ip_str);
int JDFS_cloud_fetch_file(char *file_name);
int JDFS_cloud_merge_file(char *file_name, int num_of_blocks);
如上述代码所示,JDFS_cloud_fetch_file()是该功能的入口,它先调用JDFS_cloud_query_file()来查询文件元信息,解析出存储该block的结点串号serial_num后调用JDFS_cloud_query_ip_from_node_serial()来查询它的ip地址,得到ip地址后紧接着调用JDFS_http_download()从data node上面下载该block,都下载完后调用JDFS_cloud_merge_file()合并block成为一个文件。
name node端响应客户端查询文件元信息的过程请参见上一小节,此处不再赘述。
data node端响应客户端下载请求的逻辑在之前的博客里也详细介绍过,此处也不再赘述,感兴趣的读者可以翻看笔者之前写的博客。
五 从虚拟集群里删除文件
最后我们还需要实现删除文件的功能。想象一下,一个文件被切分成了N份,N份文件正文被冗余地存储在不同的结点上面,我们需要通知所有存储有该文件block的数据结点去删除之,另外文件的元信息也需要删除。具体的流程是客户端向name node查询文件元信息,并通知它该文件要删除了,name node server不仅要把文件元信息发送给客户端,还有把文件元信息里的“文件状态”值改为2,表示等待被删除,以防止其他客户端来读它。客户端得到文件元信息后就会通知各个data node删除相应的数据。等隶属于该文件的所有冗余block都被删除后,客户端再一次请求name node server删除该文件的元信息文件,于是删除动作完成了。
在客户端我们实现了如下几个函数来支持该功能:
int JDFS_cloud_delete_file(char *file_name);
int JDFS_cloud_delete_file_internal(char *file_name, char *ip_str, int port);
int JDFS_cloud_delete_meta_file(char *file_name, char *ip_str, int port); int JDFS_cloud_query_file(char *file_name, JDFS_file_info *jfi,int flag);//flag, 0: query for reading ,1 :query for deleting
int JDFS_cloud_query_ip_from_node_serial(int serial_num, char *ip_str);
JDFS_cloud_delete_file()是该功能的入口点函数,它会首先调用第5,6行的函数来获得文件元信息、以及结点ip地址,然后对于文件的每一个block,查询所有存储有该block的data node,向该data node server发送删除请求,具体是通过调用JDFS_cloud_delete_file_internal()来做的,等所有的都删除完毕后,再调用JDFS_cloud_delete_meta_file()向name node server发送删除元信息文件的请求。
对于data node端,实现了一下几个函数来支持该功能
void *Http_server_callback_delete_file(void *arg);
对于name node server实现了如下函数来支持该功能:
void *Http_server_callback_delete_meta_file(void *arg);
六 结束语
到此为止,JDFS的全部功能已经介绍完毕,当前还剩下两件事情要做,其一是继续调试JDFS隐藏很深的潜在bug,使得系统能够稳定的运行,稳定运行之后,需要把data node server和name node server做成守护进程,这样server启动后就不会因为用户关闭终端而终止了,也不会因为用户按下Crtl+C等而终止,诸如此类,关于守护进程请参见《Unix环境高级编程》;其二,在下一篇博客笔者会配以流程图、结构图的方式从总体上勾画出JDFS的架构,工作流程等,还会详细介绍如何在虚拟集群里把JDFS跑起来,也有读者反应能否简化安装,一键部署等,等JDFS稳定运行后,我在来研究一下简化安装,一键部署的问题。
另外因为笔者研究生期间曾接触过一个单机多核平台的map-reduce系统,因此萌生了自己动手写一个模仿hdoop的小巧的map-reduce引擎的想法,如果未来真去做的话,正好可以用JDFS来作为中间结果的存储管理系统。
联系方式:https://github.com/junhuster/
JDFS:一款分布式文件管理系统,第四篇(流式云存储续篇)的更多相关文章
- JDFS:一款分布式文件管理系统,第五篇(整体架构描述)
一 前言 截止到目前为止,虽然并不完美,但是JDFS已经初步具备了完整的分布式文件管理功能了,包括:文件的冗余存储.文件元信息的查询.文件的下载.文件的删除等.本文将对JDFS做一个总体的介绍,主要是 ...
- JDFS:一款分布式文件管理系统,第三篇(流式云存储)
一 前言 看了一下,距离上一篇博客的发表已经过去了4个月,时间过得好快啊.本篇博客是JDFS系列的第三篇博客,JDFS的目的是为了实现一个分布式的文件管理系统,前两篇实现了基本的上传.下载功能,但是那 ...
- 手把手教你用 FastDFS 构建分布式文件管理系统
说起分布式文件管理系统,大家可能很容易想到 HDFS.GFS 等系统,前者是 Hadoop 的一部分,后者则是 Google 提供的分布式文件管理系统.除了这些之外,国内淘宝和腾讯也有自己的分布式文件 ...
- JDFS:一款分布式文件管理实用程序第二篇(更新升级、解决一些bug)
一 前言 本文是<JDFS:一款分布式文件管理实用程序>系列博客的第二篇,在上一篇博客中,笔者向读者展示了JDFS的核心功能部分,包括:服务端与客户端部分的上传.下载功能的实现,epoll ...
- Hadoop HDFS概念学习系列之分布式文件管理系统(二十五)
数据量越来越多,在一个操作系统管辖的范围存在不了,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,因此迫切需要一种系统来 管理多台机器上的文件,这就是分布式文件管理系统. 是一种允许文件 ...
- 分布式文件管理系统HDFS
Hadoop 分布式文件管理系统HDFS可以部署在廉价硬件之上,能够高容错. 可靠地存储海量数据(可以达到TB甚至PB级),它还可以和Yam中的MapReduce 编程模型很好地结合,为应用程序提供高 ...
- 20190827 On Java8 第十四章 流式编程
第十四章 流式编程 流的一个核心好处是,它使得程序更加短小并且更易理解.当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体.流使得 Java ...
- JDFS:一款分布式文件管理实用程序第一篇(线程池、epoll、上传、下载)
一 前言 截止目前,笔者在博客园上面已经发表了3篇关于网络下载的文章,这三篇博客实现了基于socket的http多线程远程断点下载实用程序.笔者打算在此基础上开发出一款分布式文件管理实用程序,截止目前 ...
- 分布式文件管理系统_FastDFS集群
简单介绍 1,client storage tracker的关系 先用一幅图来解释用户如何访问一个通过DFS管理的文件 一般来说,一台服务器只有一个storage server,多个storage s ...
随机推荐
- 欠了好久的CRM帖子,双11来读。
又一年双11了,觉得天猫双11越来越没特色了. 从折扣,音符旋律到红包,今年15年却找不出往年的热度,只是商家还是一样的急,备着活动目标计划,做着库存价格打标视觉设计这种苦逼的日子. 欠了好久的CRM ...
- python基础教程(七)
本章介绍如何将语句组织成函数,这样,可以告诉计算机如何做事. 下面编写一小段代码计算婓波那契数列(前两个数的和是第三个数) fibs = [0,1] # 定义一个列表,初始内容是0,1 for i ...
- 介绍下Python的两个标准库 os 和 sys
import sysprint(sys.path) #python 2 中报错 ....,打印的是绝对路径(***\\python\\lib\\site-packages# 第三方库,后退一级为标准库 ...
- SVG基本形状及样式设置
前面的话 图形分为位图和矢量图.位图是基于颜色的描述,是由像素点组成的图像:而矢量图是基于数学矢量的描述,是由几何图元组成的图像,与分辨率无关.可缩放矢量图形,即SVG,是W3C XML的分支语言之一 ...
- PHP初入--添加内容到框框里并删除
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- IS-IS完整笔记
IS-IS笔记大全 1.公开,ISO国际标准化组织(按照中文顺序翻译) 中间系统到中间系统 双栈.集成 数据传递机制 Cons面向连接网络服务(TCP) Clns缺少链接网络服务(UDP) Is-is ...
- 【集美大学1411_助教博客】团队作业4——第一次项目冲刺(Alpha版本) 成绩
写在前面的话 第一次alpha冲刺,大家完成得都很好,从博客中体现出来的是所有团队都完成了预期的目标. 一个团队从最初建立,到磨合,到做出一个能被接受的产品,真是一件不容易的事情.就好像TheNexu ...
- 团队作业4——第一次项目冲刺(Alpha版本)3rd day
一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 1.界面 界面已初步完成并能够进行简单的界面关联 界面内的功能正在完善 2.登陆方面 QQ授权已申请,等待通过 申请通过后在登 ...
- 201521123025《java程序设计》第七周学习总结
1. 本周学习总结 2. 书面作业 Q1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 public boolean contains(Object o) { r ...
- 201521123114 《Java程序设计》第2周学习总结
#1. 本周学习总结 1. 学会了使用码云管理代码,使用eclipse关联jdk源代码: 2. 学习了包管理机制,包的作用:主要是管理java文件,解决同名文件冲突; 3. ArrayList可以处理 ...