Hadoop-HDFS核心知识笔记整理

       本文内容主要从《Hadoop技术内幕:深入解析Hadoop Common和HDFS架构设计与实现原理》一书中摘录总结成文,可以让我们以最快的速度回顾相关的核心知识点。文章成文以常见的领域模块组织。

集群模块

  1. master/salve架构,由一个固定的节点充当master,称为NameNode,他是集群的管理者。还有一个NameNode节点用来备用做高可用。其他的节点称为DataNode,用来存储数据块
  2. NameNode有两个,一个是主,一个是辅助。主节点维护整个文件系统的文件目录树、元信息和数据块索引等。这些信息事实在内存中更新,同时也会有一个落盘的编辑日志文件记录,用于宕机重启恢复。不过和数据节点相关的信息并不会写入日志文件,而是每次重启都重新动态构建出来,通过于集群中的数据节点交互。
  3. 辅助的NameNode,主要用于定时整理主NameNode上的元数据信息,先获取其镜像,然后合并清理日志文件,然后重新上传给主NameNode覆盖,使这些元数据信息保持精简,不至于随时间信息越来越冗余。本身不会接受任何客户端请求。所以它并不是一个简单的支持自动切换的备用NameNode。但是当主NameNode宕机或使用新服务器时,可以从它这里恢复数据。主NameNode出了问题需要人工干预。
  4. DataNode初始化或更新时负责像NameNode报告其上数据块的最新信息。其上的数据块是以普通文件方式存储的,大小固定为64M。一个数据块默认是3个副本
  5. 客户端提供了一套抽象过的文件操作API供用户像操作本地文件一样操作远程分布式文件。客户端命令接口没有实现标准的POSIX命令。zk是实现了的
  6. 数据节点启动后去名字节点进行版本检查、注册,然后将自身上的数据块信息呈送给名字节点,以帮助其建立数据块和节点的映射关系。名字节点虽然有持久化备份目录和数据块,但是却没有持久化数据块的位置,重启后需要数据节点上报重新建立联系。同时数据节点会定期上报数据块信息,使名字节点保持最新状态,防止某些错误导致的长时间不一致性问题。
  7. 数据节点会定时和名字节点保持心跳通信。内容除了自身标识外还包括节点的容量、正在写文件的连接数、读写数据的线程数等负载信息。这样名字节点可以实时掌握各个数据节点的运行和负载状态。
  8. 名字节点对数据节点的心跳通信返回时可以顺便携带某些操作指令下达给数据节点,这样也省去了额外的RPC通信。比如数据库复制、删除、恢复、升级以及关闭节点等
  9. 名字节点为平衡数据分布,会发起节点间数据拷贝转移命令。A节点接受命令后对B节点发起数据拷贝请求,完后B节点删除数据块,最后上报给名字节点,完成数据转移
  10. 租约是名字节点用于管理客户端文件写入加锁的管理机制。客户端写入文件前先要去名字节点申请文件写锁才能写入,保证文件写入的安全性,防止并发写入。租期快到一半时,客户端要主动续约,否则过期后会被判定为已结束,名字节点释放锁,开始接受其他写入请求。正常情况下客户端写完文件后,通知名字节点释放锁(名字节点和客户端都移除该租约)。其实这个很像redis分布式锁中过期时间的处理,客户端需要维持一个看门狗定时续约,不然过期了,锁就不在了。
  11. 名字节点启动后会立即进行目录文件恢复至内存,此时进入安全模式,即不允许实际读写数据,只能查看。需要等待一段时间,等数据节点上报的数据块信息达到95%以上后,才可以离开安全模式,接受客户端操作

选举

  1. 和其他大多数分布式系统不一样的是,hdfs系统不存在选举机制。虽然也是master-slave架构,但是其master是一开始就指定好的节点,第二名字节点也仅用来做名字节点宕机恢复用的,整个过程需要人工干预
  2. 从2.6版本后,hdfs也做了高可用方案,但其也算不上选举,仅是使用备用主节点方案实现。

元数据模块

  1. 所有文件单元的物理位置信息都存放在NameNode机器的内存中,这个内存决定了整个集群可以保存文件的数量上限,以及处理性能
  2. 第二名字节点NameNode根据一定的策略从名字节点上获取命名空间镜像和编辑日志镜像进行合并,以减少名字节点从故障中恢复的时间。合并完后通知名字节点,再由名字节点从第二名字节点上下载新命名空间镜像。这之间的过程并没有使用底层的IPC远程过程调用接口,而是走的HTTP协议。因为这样做可以基于流式读取。
  3. 名字节点内存中保存着整个文件系统的目录树以及文件的数据块索引。为了不丢失数据这些信息更新时也会持久化到磁盘上的fsimage(命名空间镜像)文件中,相当于一个检查点机制。这里面主要存储的是序列化后的文件系统目录和文件的i-node。和Linux类似,hdfs索引接单表征一个文件或者目录的元数据信息,以及文件的副本数、修改和访问时间等信息
  4. 由于对目录树的每次修改不可能实时的去随机修改这个文件,因为这样做性能很差。所以采用日志记录方式额外写入edits日志文件中。如果名字节点发生宕机重启后可以凭借这两个文件快速恢复内存中的目录信息。
  5. 随着系统更新目录越来越多,日志文件edits也会越来越庞大,严重影响数据恢复速度。所以集群额外使用第二名字节点帮助整理名字节点上的日志文件和fsimage镜像文件。第二名字节点从名字节点上下载日志文件和fsimage文件,此时名字节点将新建一个日志edit.new文件用于记录期间产生的新操作。第二名字节点本地处理合并到新的fsimage镜像文件。然后通知名字节点获取该新镜像,名字节点通过HTTP流式下载镜像到本地后替换原有fsimage镜像文件,并删除原有日志文件,将处理期间新建的那个日志文件edit.new重命名为正式的日志文件名edit。
  6. 客户端通过IPC远程过程调用与名字节点交互。创建目录时,名字节点只在本地内存中创建,并持久化创建操作到日志文件即算完成,直接返回客户端成功。并不会联系数据节点去创建。增加副本数或删除文件操作时也是如此,只是在数据节点下一次心跳时,将这些指令顺便返回给数据节点去执行。所以客户端收到删除成功,并不意味着已经删除了,而是稍后删除,这也是一种最终一致性实现。
  7. 名字节点NameNode恢复时,先加载fsimage目录镜像文件,然后再加载editlog编辑日志文件才能完整恢复数据。

存储模块

  1. hdfs最小存储单位是块(64M),以普通文件的形式存储于操作系统的文件系统里。一个大文件会被分割成多个块分布式存储到数据节点磁盘上。这种机制类似于操作系统中的文件系统,磁盘块也是文件存储的最小单位(ext3中大小为4093字节)。一个文件会被分割成块的整数倍小块分散式存储到本地磁盘中。所以一个磁盘块只会属于一个文件。
  2. 数据节点管理的数据块文件目录下,blocksBeingWritten文件夹存放着客户端发起写入的数据块文件,tmp文件夹存放着其他数据节点发起复制写入的数据块文件。两者数据块完成后迁移至current目录下。如果数据块文件被打开追加写,则又迁移到blocksBeingWritten文件夹中
  3. 数据目录下的in_use.lock用于标记该目录已经有一个Hadoop实例使用,防止其他实例共享一个目录。实例退出时会被删除。这是一种常用于本地文件系统实现文件操作互斥锁的技巧,因其判断过程是非原子操作,所以只能用于低频并发。需要注意的是这和多线程写同一个文件加锁是不同的,这个是用new FileChannel().tryLock /lock实现的,且是原子操作。
  4. 数据节点可以管理多个目录,每个目录下都有自己的current的目录。数据目录下的current目录下即有数据块文件也有子目录,其他几个文件夹是没有子目录的。为了让current目录下不会因为太多平级文件造成遍历性能问题,整个目录树设计为一个目录下最多64个数据块和64个子目录。这样设计就可以让目录树深度不会太深,太深也会导致查找性能问题。(注意:有人在ext3文件系统上测试一个目录下1000个文件和1万个文件打开速度区别不明显)
  5. current目录下的数据块名称由前缀blk_+唯一标识构成,同时还有一个对应的.meta文件,用于校验文件。
  6. 版本升级过程中需要同时保留旧版本数据和生成新版本数据,但是不需要复制所有文件,使用两倍的空间来完成。而是采用Linux文件系统的硬链接特性,一个文件可以有多个别名,就版本用一个名,新版本用另外一个名。这样升级过程中新版本的文件做了修改,回滚的话,也不会影响就版本的文件数据,底层做了隔离的(后面282页又说如果新版本直接修改文件则会同时影响旧版本,所以需要拷贝一份后再修改)。升级成功后删除旧版本使用的文件名即可,不会真的删除数据的,因为还有新版本的文件名在使用。
  7. 因为升级时一个很耗时的过程,为了不因为系统异常中断,在此过程中会创建各种临时文件表示升级过程到了什么状态,以便下次恢复系统时可以用来判断检查点到了哪个位置。这是一种典型的状态机设计,面对复杂的场景描述各个状态之间的转换关系。
  8. 升级失败回滚时,分三步走。首先将当前升级版本current文件夹改名removed.tmp,然后将旧版本previous改名为current,最后再删除removed.tmp即可。不需要去一个个修改子文件名,因为在最父层做了别名的硬链接。
  9. 由于hdfs对数据块的管理是建立在普通文件上的,所以不会去设计系统文件底层对磁盘块的处理。而是借鉴Linux逻辑卷LVM管理思想,传统文件系统是基于分区的,一个文件系统对应一个分区。物理卷就是磁盘分区(类似Windows系统上的磁盘分区),卷组就是建立在物理卷之上,由多个物理卷组成的存储池。逻辑卷是建立在卷组上,所以实际上是可以跨存储设备的。但是可以看做是一个整体磁盘存储空间,屏蔽掉了物理分离上的细节,然后再整个逻辑卷上建立一个文件系统。这样也可以提高多个物理磁盘并发读写性能
  10. 文件系统数据集FSDataSet是HDFS操作文件底层接口,屏蔽了大量底层的实际操作过程细节。
  11. 编辑日志的写入使用双缓冲区交互写入方式。首先建立两个缓冲区,然后建立两个缓冲区指针(引用对象)bufCurrent和bufReady,前者指向写用户空间写入缓冲,后者指向即将写入内核缓冲区即将fsync到磁盘的缓冲区。后者写完后清空,和前者缓冲的引用对象对调一下指向位置即可。

网络模块

  1. 使用自研的IPC模块充当底层RPC框架。直接基于java NIO API上构建,而不是使用netty第三方组件。这里的RPC过程实现了动态代理模式,使用起来像本地方法调用。底层异步调用等待远程结果返回过程中也是使用了线程的wait和notify机制。
  2. Java NIO中,缓存(cache)、通道(Channel)、选择器(selecter)是基本概念。缓存给通信双方提供了以块为单元的数据交换。通道是某个具体的到达目标的信道,比如一个文件、一个网络目标机器。选择器则是注册于通道上的监听程序,使用一个线程进行轮询所有通道。监听通道上的读、写、连接等事件。
  3. 每个节点都内嵌了Jetty包,可以以web容器启动,故支持HTTP协议通信
  4. 为了提供高吞吐的数据访问,数据节点使用基于TCP流的访问接口实现读写数据操作。使用传统的阻塞式IO,一个线程对接一个客户端,这种场景下适应了大文件流式读写的高吞吐需求,而非采用NIO设计。
  5. 网络传输数据采用”零拷贝“技术,即数据由DMA(不是CPU)负责读入内核缓冲区后,使用Java NIO中的FileChannel.transferTo()方法负责直接将内核缓冲区的数据描述符(都不用拷贝一次数据)传递到网卡Socket缓冲区等待DMA发送即可,不需要传统方式经过用户缓冲区中转,大大提供了效率。同时也失去了数据节点校验数据的能力,改由接收的客户端去校验即可。
  6. 数据节点有一个节流器功能,负责控制某个时段内客户端发送/接收数据量不能超过一个上限阈值。主要用于数据块扫描器和节点间数据块的移动复制工作,不能影响系统对外提供服务。
  7. 在多层次拓扑网络集群中,会根据不同的机架位置(网段)生成一颗树形结构信息,用于判断节点之间的距离。默认数据块有3个副本,第二个副本会放到另外一个机架(网段)上的节点。这样是为了尽可能的降低数据丢失风险,因为某个区域停电。第三个副本放到和第二个副本同一个机架(网段)上,这样是为了尽可能降低延迟。
  8. 当客户端读取数据时,通过对副本做网络地址排序,尽可能优先访问离其最近的节点

写数据模块

  1. 客户端create一个新文件写入数据时,需要先向名字节点申请创建一个新文件,它会做一些必要权限、合规性检查。名字节点本地内存中创建成功后,同时记录一条操作日志(添加文件)持久化到磁盘上。然后添加租约并返回给客户端,表示创建了一个新的空文件。客户端收到响应后也在本地租约管理器中添加租约
  2. 客户端创建完一个新的空文件后,需要再次像名字节点申请一个新的数据块写入。然后再联系目标数据节点写入数据。
  3. 更新一个文件append操作,也是需要先向名字节点申请一个新的数据块,然后再联系目标数据节点写入数据。
  4. 如果名字节点返回写入数据块的位置给客户端后,客户端联系不上目标数据节点。则需要告知名字节点放弃之前申请的数据块,然后重新申请,并排除掉上一次联系不上的数据节点,以免又分配了这个失联的节点。
  5. 客户端使用fsync方法将要写入的数据持久化到集群。这个方法类似系统调用中的刷盘操作,但是有很大区别。这里的fsync是通知名字节点已经完成数据写入,主节点依靠内在一致性机制保证数据写入成功,并持久化了自身元数据(编辑日志)的更新。但是不能保证数据真正被持久化到了物理磁盘上,这和操作系统调用的该方法有较大区别。
  6. 服务端写数据时将多个副本按顺序组成一个数据流管道顺序写入。并不是客户端同时发起对多个副本节点同时写入,也不是先写入其中一个节点,然后分发或订阅发送到其他副本节点。
  7. 客户端向服务端写数据首先要想目标副本发起一个请求写的命令,以便服务端的所有副本节点之间建立好数据流管道。假设有3个副本,第一个副本节点收到客户端写请求后又转发给第二个副本节点,第二个副本节点接受请求后再转发给第三个副本节点终止。客户端请求的的响应也是由数据流管道3个副本节点逆流发送响应信息,即第三个副本节点响应给第二个副本节点后再响应给第一个副本节点,再响应给客户端。后续客户端写入数据包都按此顺序请求响应。这是一个多副本同步写入的过程,保证数据的强一致性。
  8. 客户端写入输出流中的数据被分成一个个文件包,放入输出流的内部队列dataQueue中。该队列中的文件包最后打包成数据包Packet,发往数据流管道。然后从该队列移动到应答队列ackQueue。数据包得到写入成功确认后再删除ackQueue中的该包。如果确认失败,则重新将数据包移动回dataQueue。等待数据流管道恢复后继续发送
  9. 如果待发送的数据包是最后一个数据包,还需要写出一个特殊标记,通知数据节点,数据块发送完毕。然后客户端通知名字节点调用fsync方法,完成名字节点的元数据输出
  10. 数据发送和接收应答分别是两个独立的线程负责。
  11. 客户端在写完一个数据块后,数据流管道上的节点会通知名字节点提交数据块信息。如果客户端输出流的队列中还有等待输出的数据。则客户端还需要再次联系名字节点申请一个新块。
  12. 服务端写入数据期间,数据流管道上的副本节点其中一个出现异常时,数据流管道会被关闭。已经发送到服务端管道上的数据包还没有收到确认的文件包,会被重新添加到客户端输出流的队列里等待重新发送。这样保证了不会丢失数据。重新发送的数据包到达服务端数据流管道写入后会产生一个新版本号,并通知名字节点。这样失败的数据节点从故障恢复后,即便已经写入了部分数据的数据块但因版本号低比名字节点上的低而被删除。
  13. 数据流管道上宕机的节点会被删除,然后重新建立新的管道,并继续写数据到正常的节点。客户端写完成关闭文件后,名字节点会发现该数据块的副本数没有达到要求。会选择一个新的数据节点并复制数据块,创建新的副本。数据节点故障只会影响一个数据块的写操作,后续数据块写入不会受到影响。
  14. 服务端数据节点接受客户端写入数据包,校验数据并保存到本地的数据块文件和校验信息文件中。
  15. 服务端写数据的节点有两个socket连接,一个负责接收客户端或管道上游节点发送过来的数据,另一个负责接收管道下游节点数据写入的确认包。两个线程分别执行,互不影响,有利于提高吞吐量。因为写入数据是一个持续的输入流,时间可能很长,每个数据包都需要单独做出确认反馈。
  16. 数据节点接受下游确认包,也是一个异步过程,每次向下游发送一个数据包后,都创建一个应答对象放入本地集合变量中。当收到下游的确认后,标记这个对象为已接受应答,同时通过java 的wait/notify机制触发下一步向上游反馈动作。这大大提高了灵活性和吞吐量
  17. 当数据块写入到达最后一个数据包时,数据节点需要上报给名字节点。为了提高效率,使用一个队列接受待上报的请求,然后独立线程批量合并发送给名字节点
  18. 服务端数据节点接收数据时需要先放入ByteBuffer,至少能装下一个客户端发送过的数据包。然后再从这个缓冲里读入数据包的包头信息,以便知道这个数据包要写入哪个数据块文件和其对应的校验文件中。
  19. 数据节点写数据时同时写数据块文件和其检验文件的。数据块文件总是从后面追加,而检验文件则可能需要更新,因为之前的检验值并没有对应一个数据块中的完整小块。
  20. 客户端如果长时间没有发送数据给数据节点,为了维持TCP连接会发送一个长度为0 的心跳包。
  21. 数据流管道中,只有最后一个数据节点才需要进行数据校验。如果发现错误会上报名字节点删除数据块,并向上游节点抛出异常。这种情况属于少见的,所以上报也不需要考虑批量设计
  22. 写数据过程中如果某个节点发生异常后,会被上游节点捕获,然后向上游传播反馈错误信息给到客户端,再由客户端负责发起数据块的恢复工作。客户端在写数据节点中选出一个节点负责监督相关数据块副本节点整个恢复过程。首先会获取每个副本上该异常数据块的大小,选择最小那个数据块的长度作为本地恢复数据块截断对齐的长度值。然后主负责数据节点通知其他副本节点按此长度对齐数据块,达到恢复数据到错误前状态。同时当前恢复后的数据块拥有新的版本号。最后客户端又可以重新发起新的写入请求,并重新建立数据流管道,从上次故障点开始继续写即可。

读数据模块

  1. 读数据块是基于TCP协议流控制的,不是走的IPC远程调用。
  2. 客户端向名字节点发起读取文件的请求,名字节点返回该文件的第一个数据块的物理节点位置,因为有多个副本,简单使用网络拓扑信息排序,相当于把最近的一个副本节点排在前面。
  3. 客户端收到数据块后连接目标副本节点开始使用TCP流控制读取数据包(相当于循环调用文件的read方法)。读到数据块文件末端后结束并关闭连接,再像名字节点发起下一个数据块读取请求。如此循环操作,就可完成整个文件的读取。
  4. 像名字节点请求读取数据块,如果本地有缓存了则不再发起,提高效率
  5. 客户端读取数据块的过程中如果发现节点无法联系,则尝试下一个副本节点读取。数据包中不但包含了数据还有一些错误校验位,客户端接受后会进行检查,如果出现异常,则会报告给名字节点进行处理。然后客户端会尝试下一个副本节点读取数据
  6. 客户端读取文件数据块的过程是透明的,由底层封装处理完成,开发人员就像使用本地文件处理对象读取本地文件一样是一个连续的流处理过程
  7. 客户端读数据使用了两个缓冲区,buf缓冲区保存了输入数据,checksum缓冲区则包含对应的校验数据

容错模块

  1. hdfs的高可用方案是,默认只有活动的名字节点(Active)对外提供服务,然后使用另外一台备用名字节点(Standby)用来做备用,此时就不再需要第二名字节点了。当活动名字节点节点宕机后,备用节点就会接替它充当新的活动节点,等旧的活动节点恢复后自动转为备用节点。
  2. 备用名字节点平常不接受请求服务,也不会给数据节点发送命令啥的。只在名字节点宕机后才会启用。但是这样新启用后的节点元数据和前节点会不一致,于是引入了JournalNode集群,一般部署3个节点类似zk的方案,主要作用就是维护和名字节点上edit.log数据一致性的。
  3. JournalNodes集群负责同步名字节点上的元数据信息,名字节点会将元数据变更写入日志记录edit.log,并发送给JournalNodes集群完成备份,JournalNodes是一个paxos系统,都是以多数节点作为数据写入成功的标志机制,这点和zk很像。也就是说只有JournalNodes集群返回OK,名字节点才认为本次写自身edit.log才算OK的,这样就保证了元数据变更的数据一致性。JournalNodes集群节点也会将名字节点的editlog数据持久化到本地磁盘上,不过感觉没有什么必要性,和zk类似,完全内存中即可。不过JournalNodes写磁盘为了高性能,也采用了双缓冲写机制。
  4. 备用名字节点则会一直监控JournalNodes集群上的editlog数据变化,并将其同步给自己,然后和自身上的命名空间合并。名字节点发生错误需要切换成备用名字节点时,备用节点需要确保已经将所有JournalNodes集群上的editlog信息都同步过来了才可以切换。
  5. 以上切换方式可能效率上不够高,因为名字节点并不会持久化保存诸如数据节点的数据块及位置等信息,每次恢复名字节点后都需要数据节点重新上报给名字节点。为了解决这个问题,让数据节点每次上报都同时上报给这两个主备名字节点,这样切换效率就高了很多。
  6. 活动名字节点和备用名字节点状态受zk监控,在名字节点宕机后,standby名字节点会自动变更状态,切换为主名字节点完成替换。但是同时也要防止脑裂情况出现,即旧的名字节点突然复活了(假死现象),就会继续认为自己还是名字节点,于是可能继续给其他数据节点发号施令,这样就会出现问题。解决这个问题的办法是类似采用zk中的epoch(纪元)机制,即每次主备交换后epoch都加1,数据节点则规定不会接受比当前epoch小的名字节点给自己发送的命令请求即可。备用节点称为活动名字节点后,将epoch发送给所有数据节点,并让他们接受这个最新的值。
  7. 备用节点同步JournalNodes集群上的editlog信息流程是,首先发送请求到集群上所有的JournalNode节点,并与之建立连接,JN节点会将本地所有editlog段落元数据信息返回给备用节点,这样备用节点就可以从任意一个JN节点上读取editlog信息了,如果某个节点读取失败就会换另外一个。

数据丢失

  1. 数据写入过程中,可能出现多个节点出现故障。这时只要管道中正常工作的副本节点满足配置项设置的值,默认为1,就可以继续正常写入,并认为是成功的。后续这个数据块会被复制,直到满足规定的副本数要求。这里显然有一个风险,那就是只有一个副本节点正常工作时,数据写入成功后也宕机了,则此时名字节点也来不及去复制数据块了,导致数据被丢失

数据一致性

  1. 活动名字节点和备用名字节点切换时,如果活动节点宕机且此时正有一个editlog在写入JN集群,那么就有可能出现数据不一致,比如JN集群认为成功了,但是活动节点发生错误,客户端自然认为失败了。此时就需要先恢复一致后才能切换。
  2. 写入数据时基于多节点副本管道流模式同步写,已有机制保证数据的强一致性。这种一致性比其他一些分布式系统要强得多,因为是基于同步模式,而不是像其他一些分布式系统那样使用异步同步到副本实现最终一致性。当然这种模式下效率也就会大打折扣。
  3. 写入过程虽然存在数据丢失风险,但是对于hdfs系统来说最终也是满足数据一致性的。因为写入脏数据的节点宕机后恢复时这部分数据会被删除掉。

异常场景

  1. 由于DataNode失联后,NameNode无法及时感知到。故客户端写数据时,可能分配了一个失联的节点导致无法写入。此时客户端可以通过放弃接口告知主节点重新分配一个新节点。

其他模块

  1. 采用自定义对象序列化工具实现以适应大规模数据的高效存储和传输场景,而不是使用java原生的对象序列化api,因为占用空间较大,效率很低。
  2. 对于整数类型int、long等序列化成字节流时,会根据实际的值范围以变长的方式进行序列化。相对于传统序列化成固定长度字节而言,这样可以有效的降低存储空间。比如-112
  3. 支持可扩展的压缩算法框架。压缩主要应用于数据存储以及map到reduce过程中的转换。为了提高压缩性能,支持使用java本地库方式调用,也就是方法使用native关键字修饰,需要安装好本地压缩函数库。这样java就可以直接调用系统本地方法进行高效压缩了,不用走JVM虚拟机运行
  4. 不支持多用户同时更新文件,且只能在文件末尾追加内容,不能随机位置修改文件内容。
  5. 支持超大文件上传并不像传统单机文件系统那样是一个文件,而是将它分割成非常多的小文件分别存储到各个网络节点上。
  6. Hadoop由于专注于数据的高吞吐设计,所以在低延迟数据访问上不是很好。可以考虑使用HBASE或Cassandra
  7. 数据节点会定期(3周一次)使用数据块扫描器扫描数据块是否有错误,通过校验信息文件。这样可以尽快发现有问题的数据块,然后重新复制。每次客户端读取某数据块成功后会发送一个响应码给数据节点,这样扫描器扫描时这个周期内可以忽略掉这块数据,因为客户端已经校验过一遍了,提高效率。
  8. 支持数据节点正常下线操作。名字节点通过下达撤销节点指令,将数据节点上的数据块转移到其他节点后就可以关机下线了。整个过程会被名字节点监控。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值