神木叫做序列化?
将结构化对象转化为字节流方便在网络传输或者持久化到磁盘中的过程。反序列化就是将字节流转化回结构化对象。
hadoop中如何使用序列化?
系统中各个节点通过RPC实现通信,RPC协议将消息序列化为二进制流,然后传递到远程节点,远程节点通过反序列化将二进制流转化为原始信息。
hadoop使用自己的序列化格式Writable,这个接口定义了两个方法:
public interface Writable{
void write(DataOutput out);
void readFields(DataInput input);
}
wrtite方法将原始信息写到DataOutput二进制流,readFields方法读取DataInput的二进制流。
对于MapReduce,类型比较很重要,因为中间有一个基于键的排序过程。对于每个MapReduce每个类型都要实现WritableComparable这个方法。他实现Writable和Comparator接口,支持排序。Hadoop提供了一个优化比较的接口RawComparator
public interface RawComparable<T> implements Comparator<T>{
compare(byte[] b1,int s1,int l1,byte[] b2,int s2,int l2);
}
直接比较数据流中的数据,无需进行反序列化,省去了新建对象的额外开销。
他的通用实现类WritableComparator类,对WritableComparable的类型可以进行比较。
compare(WritableComparable,WritableComparable)
.
使用:
RowComparator<IntWritable> comparator = WritableComparator.get(IntWritable.class);
为IntWritable创建一个比较对象。
comparator.comparator(new IntWritable(123),new IntWritable);
或者RowComparator原始比较方法
comparator.comparator(b1,0,b1.length,b2,0,b2.length);
Writable类
Hadoop自带的Writable实现类在org.apache.hadoop.io包中;
java基本类型的Writable封装:
八种基本类型除了char另外其中都有相应的封装:
Java基本类型 | Writable实现类 | 序列化大小(字节) |
boolean | BooleanWritable | 1 |
byte | ByteWritable | 1 |
shot | ShortWritable | 2 |
int | IntWritable VIntWritable | 4 1~5 |
long | LongWritable VLongWritable | 8 1~9 |
float | FloatWritable | 4 |
double | DoubloeWritable | 8 |
定长格式非常适合对整个数值域分布非常均匀的情况下,如哈希函数。大多数时候数值分布并不是均匀的,所以使用定长格式更节省空间,而且VIntWritable和VLongWritable相互转换,因为他们的编码实际是一样的。所以在定义数据类型的时候不必一开始就定义8个字节的long类型。这些类型都定义了set()和get()方法方便进行读取和存储
java.lang.String对应的Writable是Text,二者存在着一些本质的区别,如索引字符位置,并且Text支持字符可变。
二进制数据的封装:BytesWritable
空值:NullWritable,他的含义是既不读取数据也不写去数据,充当占位符。
通用封装:ObjectWritable,当一个字段包含多种类型的时候使用ObjectWritable非常有用,而GenericWritable是比ObjectWritable更高效的一个方式,但是不能存在比较多的类型。
Writable集合类型有6中:
ArrayWritable、ArrayPrimitiveWritable、TwoDWritable、MapWritable、SotedMapWritable、EnumMapWritable类型