大数据第五天

  1.校验和

     HDFS数据完整性:

用户希望储存和处理数据的时候,不会有任何损失或者损坏。
 Hadoop提供两种校验
 1校验和(常用循环冗余校验CRC-32)

               ·1 写入数据节点验证

   写入数据节点验证
   Hdfs会对写入的所有数据计算校验和,并在读取数据时验证校验和。
   元数据节点负责在验证收到的数据后,储存数据及其校验和。在收到客户端数据或复制其他datanode的数据时执行。
   正在写数据的客户端将数据及其校验和发送到一系列数据节点组成的管线,管线的最后一个数据节点负责验证校验和

               ·2 读取数据节点验证

   读取数据节点验证
   客户端读取数据节点数据也会验证校验和,将它们与数据节点中储存的校验和进行比较。
   每个数据节点都持久化一个用于验证的校验和日志。
   客户端成功验证一个数据块后,会告诉这个数据节点,数据节点由此更新日志。

  ·3恢复数据          由于hdfs储存着每个数据块的备份,它可以通过复制完好的数据备份来修复损坏的数据块来恢复数据。  
   

· 4LocalfileSystem类

                Hadoop的LocalFileSystem类是用来执行客户端的校验和验证。当写入一个名为filename的文件时文件系统客户端会在包含文件块校验和的同一目录内建立一个名为Filename.crc的隐藏文件。

  ·5ChecksumfileSystem类

   LocalFileSystem类通过ChecksumFileSystem类来完成自己的任务
   FileSystem rawFs;
   FileSystem checksummedFs=new ChecksumFileSystem(rawFS);
   可以通过CheckFileSystem的getRawFileSystem()方法获取源文件系统。
   当检测到错误,CheckFileSystem类会调用reportCheckSumFailure()方法报告错误,然后LocalFileSystem将这个出错的文件和校验和移到名为bad_files的文件夹内,管理员可以定期检查这个文件夹。

        2运行后台进程来检测数据块

 数据节点后台有一个进程DataBlockScanner,定期验证储存在这个数据节点上的所有数据项,该项措施是为解决物理储存媒介上的损坏。DataBlockScanner是作为数据节点的一个后台线程工作的,跟着数据节点同时启动。它的工作流程如图

  由于对数据节点上的每一个数据块扫描一遍要消耗较多系统资源,因此扫描周期的值一般比较大,这就带来另一个问题,就是在一个扫描周期内可能出现数据节点重启的情况,所以为了提高系统性能,避免数据节点在启动后对还没有过期的数据块又扫描一遍,DataBlockScanner在其内部使用了日志记录器来持久化保存每一个数据块上一次扫描的时间,这样的话,数据节点可以在启动之后通过日志文件来恢复之前所有的数据块的有效时间。

  2.文件结构---》sequenceFiLe  mapFile   两个例子read write

   基于文件的数据结构 

 HDFS和MR主要针对大数据文件来设计,在小文件处理上效率低.解决方法是选择一个容器,将这些小文件包装起来,将整个文件作为一条记录,可以获取更高效率的储存和处理,避免多次打开关闭流耗费计算资源.hdfs提供了两种类型的容器 SequenceFile和MapFile
小文件问题解决方案:
(1)在原有HDFS基础上添加一个小文件处理模块,具体操作流程如下:
(2)当用户上传文件时,判断该文件是否属于小文件,如果是,则交给小文件处理模块处理,否则,交给通用文件处理模块处理。在小文件模块中开启一定时任务,其主要功能是当模块中文件总size大于HDFS上block大小的文件时,则通过SequenceFile组件以文件名做key,相应的文件内容为value将这些小文件一次性写入hdfs模块。
(3)同时删除已处理的文件,并将结果写入数据库。
(4)当用户进行读取操作时,可根据数据库中的结果标志来读取文件。
       Sequence file由一系列的二进制key/value组成,如果key为小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。Hadoop-0.21.0版本开始中提供了SequenceFile,包括Writer,Reader和SequenceFileSorter类进行写,读和排序操作。该方案对于小文件的存取都比较自由,不限制用户和文件的多少,支持Append追加写入,支持三级文档压缩(不压缩、文件级、块级别)。其存储结构如下图所示:
 

SequenceFile储存
文件中每条记录是可序列化,可持久化的键值对,提供相应的读写器和排序器,写操作根据压缩的类型分为3种:
--Write 无压缩写数据
--RecordCompressWriter记录级压缩文件,只压缩值
--BlockCompressWrite块级压缩文件,键值采用独立压缩方式
在储存结构上,sequenceFile主要由一个Header后跟多条Record组成,如图



SequenceFile写操作
 通过createWrite创建SequenceFile对象,返回Write实例,指定待写入的数据流如FSDataOutputStream或FileSystem对象和Path对象。还需指定Configuration对象和键值类型(都需要能序列化)。
 SequenceFile通过API来完成新记录的添加操作:fileWriter.append(key,value);

MapFile

 一个MapFile可以通过SequenceFile的地址,进行分类查找的格式。使用这个格式的优点在于,首先会将SequenceFile中的地址都加载入内存,并且进行了key值排序,从而提供更快的数据查找。与SequenceFile只生成一个文件不同,MapFile生成一个文件夹。索引模型按128个键建立的,可以通过io.map.index.interval来修改
缺点:
1.文件不支持复写操作,不能向已存在的SequenceFile(MapFile)追加存储记录

2.当write流不关闭的时候,没有办法构造read流。也就是在执行文件写操作的时候,该文件是不可读取的



排序后的SequeneceFile,并且它会额外生成一个索引文件提供按键的查找.

读写mapFile与读写SequenceFile非常类似,只需要换成MapFile.Reader和MapFile.Writer就可以了。在命令行显示mapFile的文件内容同样要用  -text

总结

 SequenceFile文件是用来存储key-value数据的,但它并不保证这些存储的key-value是有序的,而MapFile文件则可以看做是存储有序key-value的SequenceFile文件。
       MapFile文件保证key-value的有序(基于key)是通过每一次写入key-value时的检查机制,这种检查机制其实很简单,就是保证当前正要写入的key-value与上一个刚写入的key-value符合设定的顺序,但是,这种有序是由用户来保证的,一旦写入的key-value不符合key的非递减顺序,则会直接报错而不是自动的去对输入的key-value排序

SequenceFile转换为MapFile
 mapFile既然是排序和索引后的SequenceFile那么自然可以把SequenceFile转换为MapFile使用mapFile.fix()方法把一个SequenceFile文件转换成MapFile

3.数据类型-hadoop

为什么Hadoop基本类型还要定义序列化?
 Hadoop在集群之间通信或者RPC调用时需要序列化,而且要求序列化要快,且体积要小,占用带宽小。
 java的序列化机制占用大量计算开销,且序列化结果体积过大;它的引用机制也导致大文件不能被切分,浪费空间;此外,很难对其他语言进行扩展使用;
 java的反序列化过程每次都会构造新的对象,不能复用对象。
Hadoop定义了两个序列化相关接口:Writable和Comparable
  WritableComparable接口相当于继承了上述两个接口的新接口
 Public interface WritableComparable<T>extends Writable,Comparable<T>
Writable接口
 基于DataInput与DatOutput的简单高效可序列化接口,就是org.apache.hadoop.io.Writable接口
 几乎所有的hadoop可序列化对象都必须实现这个接口有2个方法:Write,readFiles

WritableComparable接口
 类似java的Comparable接口,用于类型的比较。MR其中一个阶段叫排序,默认使用Key来排序。Hadoop提供了一个优化接口RawComparator
  Public interface RawComparator<T> extends Comparator<T>{
     Public int compare(byte[]  b1,int s1,int l1,byte[] b2,int s2,int l2);
 }
可以比较b1和b2,允许执行者直接比较数据流记录,而无须先把数据流反序列化成对象,这样可以避免新建对象的开销 。

Writable类
ArrayWritable
TwoDArrayWritable
MapWritable
SortedMapWritable
BooleanWritable
ByteWritable
IntWritable
VIntWritable
FloatWritable
LongWritable
VLongWritable
DoubleWritable
NullWritable
Text
BytesWritable
MD5Hash
ObjectWrtiable
GenericWritable


Text  

 存储的数据按照UTF-8,类似String,它提供了序列化,反序列化和字节级别比较的方法。Text类替换了UTF8类。
 1.unicode编码是一个很大的集合,可以容纳100多万个符号。具体的符号对应表可以查询unicode.org 它只规定了符号的二进制代码,没有规定如何存储,而utf-8就是unicode的实现还有utf16等。对于单个字符字节第一位为0,后面7位为这个符号的unicode码。因此对于英语字母,utf-8编码和ASCII码是相同的。所有\u0001~\u007f会以单字节储存。\u0080~\u07ff的unicode会以双字节储存,\u0800~\uFFFF的会以3字节存储。

 2.例子 Text的几个方法 一旦使用多字节编码Text和String区别就明显了

Public void testText() throws UnsupportedEncodingException{
T=new Text(“你好刘老”);
S=”你好刘老”;
assertEquals(t.getLength(),12);
assertEquals(s.getBytes(“utf-8”).length,12);
assertEquals(s.length(),4);
assertEquals(t.find(“刘”),6);
assertEquals(s.indexOf(“刘”),3);
}
Text.find()方法返回的是字节偏移量,String.indexOf返回单个编码字符的索引位置,
String.codeprintAt()和Text.charAt类似,前者通过字节偏移量来索引
Text对字符串没有String方法丰富 大多数情况下通过toString转换成String来操作
BytesWritable
 相当于二进制数据数组的包装。以字节数组{1,2,3,4}它的序列化格式是4字节表示字节数 ,每2个字节表示一个数据即 “0000 0004 0102 0304” 和Text一样BytesWritable也是可变的 ,可以通过set来修改
NullWritable
 是writable类型的特殊类型,序列化长度为0,它充当占位符但不真在数据流中读写。NullWritable是单实例类型,通过NullWriable.get()方法获取
ObjectWritable和GenericWritable
 ObjectWritable是对java基本类型的和这些类型的数组类型的通用封装 ,使用RPC来封送
自定义Writable类型
 Hadoop基本满足大部分需求,但有些情况下可以根据业务需要构造新的实现,为了提高MR作业的性能,因为Writable是MR的核心。

    writable-serilziable   comparable-sort

    IntWritable   Text
    A implements Writable,comparable
    {
          write(DataInputStream)      
          readFiles         
          comparaTO(B b)          
    }
    A--》hadoop filesystem operator sort

    4.hadoop压缩(分片,压缩率,本地方法)

         1.CodeC
  实现了一种压缩解压算法。Hadoop中压缩解压类实现CompressionCodec接口
  createOutputStream来创建一个CompressionOutputStream,将其压缩格式写入底层的流
  演示HDFS上一个1.bzip2算法压缩的文件解压,然后把解压的文件压缩成2.gz
2.本地库
  Hadoop使用java开发,但是有些需求和操作并不适合java,所以引入了本地库 native。可以高效执行某些操作。如使  用gzip压缩解压时,使用本地库比使用java时间要缩短大约10%,解压达到50%。在hadoop_home/lib/native下
  在hadoop配置文件core-site.xml可以设置是否使用native
  <property>
  <name>Hadoop.native.lib
  <value>true
  </property>
默认是启用本地库,如果频繁使用原生库做压解压任务,可以使用codecpool,通过CodecPool的getCompressor方法获得Compressor对象,需要传入Codec 。这样可以节省创建Codec对象开销 ,允许反复使用。
3.如何选择压缩格式
     1.Gzip 优点是压缩率高,速度快。Hadoop支持与直接处理文本一样。缺点不支持split,当文件压缩在128m内,都可以用gzip
    2.Izo   优点压缩速度快 合理的压缩率;支持split,是最流行的压缩格式。支持native库;缺点 比gzip压缩率低,hadoop本身不支持,需要安装;在应用中对lzo格式文件需要处理如 指定inputformat为lzo格式
    3.Snappy压缩 高速压缩率合理支持本地库。不支持split,hadoop不支持 要安装linux没有对应命令;当MR输出数据较大,作为到reduce数据压缩格式
    4.Bzip2 支持split,很高的压缩率,比gzip高,hadoop支持但不支持native,linux自带命令使用方便。缺点压缩解压速度慢
使用哪种压缩和具体应用有关,对于巨大,没有储存边界的文件如日志 可以考虑
1储存不压缩的文件
2使用支持切分的储存格式 bzip2
3在应用中切分,然后压缩,需要选择合理数据块的大小,以确定压缩后的块大小
4使用顺序文件SF,支持压缩和切分
5使用Avro数据文件,支持压缩切分并增加了编程语言可读写的优势对于大文件,不应该使用不支持切分的压缩格式,否则失去本地性,造成MR应用效率低下。

 5.mapFile---》操作 read write 优缺点

  mapfile写操作

  

public class MapFileWriteFile
{
private static final String[] myValue={"hello world","bye world","hello hadoop","bye hadoop"};
public static void main(String[] args)
{
String uri=“hdfs://master:8020/number.map";
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(URI.create(uri),conf);
IntWritable key=new IntWritable();
Text value=new Text();
MapFile.Writer writer=null;
try
{
writer=new MapFile.Writer(conf,fs,uri,key.getClass(),value.getClass());
for(int i=0;i<500;i )
{
key.set(i);
value.set(myValue[i%myValue.length]);
writer.append(key,value);
}
finally {IOUtils.closeStream(writer);}
}
}
}
MapFile会生成2个文件 1个名data,1个名index
查看前10条data+index $ hdfs –fs –text /number.map/data | head
    读取mapfile

   

public class MapFileReadFile
{
public static void main(String[] args)
{
String uri=“hdfs://master:8020/number.map";
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(URI.create(uri),conf);
MapFile.Reader reader=null;
try
{
reader=new MapFile.Reader(fs,uri,conf);
WritableComparable key=(WritableComparable)ReflectionUtils.newInstance(reader.getValueClass(),conf);
while(reader.next(key,value))
{
System.out.printf("%s\t%s\n",key,value);
}
reader.get(new IntWritable(7),value);
System.out.printf("%s\n",value);
}
finally
{ IOUtils.closeStream(reader); }
}
}





1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值