【hadoop】18.MapReduce-序列化

簡介

序列化就是把內存中的對象,轉換成字節序列(或其餘數據傳輸協議)以便於存儲(持久化)和網絡傳輸。 java

反序列化就是將收到字節序列(或其餘數據傳輸協議)或者是硬盤的持久化數據,轉換成內存中的對象。apache

Hadoop擁有一套本身的序列化機制。網絡

一、爲何不用Java Serialization

Java的序列化是一個重量級序列化框架(Serializable),一個對象被序列化後,會附帶不少額外的信息(各類校驗信息,header,繼承體系等),不便於在網絡中高效傳輸。因此,hadoop本身開發了一套序列化機制(Writable),他具備精簡、高效的特色。框架

Hadoop之父Doug Cutting(道格卡丁)解釋道:「由於Java的序列化機制太過複雜了,而我認爲須要有一個精簡的機制,能夠用於精確控制對象的讀和寫,這個機制將是Hadoop的核心。使用Java序列化雖然能夠得到一些控制權,但用起來很是糾結。不用RMI(遠程方法調用)也是出於相似的考慮。」ide

二、Hadoop經常使用序列化類型

咱們經過經常使用的Java數據類型對應的hadoop數據序列化類型 |Java類型|Hadoop Writable類型| |-|-| |boolean |BooleanWritable| |byte |ByteWritable| |int |IntWritable| |float |FloatWritable| |long |LongWritable| |double |DoubleWritable| |string |Text| |map |MapWritable| |array| ArrayWritable|函數

在具體案例中,咱們能夠根據實際需求,若是類型能夠用簡單類型勝任的話,在此表中尋找到對應的參考。oop

三、自定義bean對象實現序列化接口

不少狀況下,基礎類型是沒法知足咱們的業務需求的,一般咱們的輸入輸出極可能都是一些實體化的類型映射。基於這種狀況,咱們就須要自定義writable類型。this

自定義bean對象要想序列化傳輸,必須實現序列化接口,須要參考以下規則:code

  1. 必須實現Writable接口
    • 重寫序列化方法
    • 重寫反序列化方法,反序列化時,須要反射調用空參構造函數,因此必須有空參構造,注意反序列化的順序和序列化的順序徹底一致
  2. 要想把結果顯示在文件中,須要重寫toString(),且用」\t」分開,方便後續用;
  3. 若是須要將自定義的bean放在key中傳輸,則還須要實現comparable接口,由於mapreduce框中的shuffle過程必定會對key進行排序。

setter方法中,推薦再增長一個set方法,用於一次性設置全部的合併字段。對象

以下是一個簡單的自定義Writable類型

package com.zhaoyi.phoneflow;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class FlowBean implements Writable {

    private long upFlow;// 上行流量
    private long downFlow;// 下行流量
    private long totalFlow;// 總流量

    // 無參構造
    public FlowBean() {
    }

    public FlowBean(long upFlow, long downFlow) {
        this.upFlow = upFlow;
        this.downFlow = downFlow;
        this.totalFlow = upFlow + downFlow;
    }

    // 序列化
    public void write(DataOutput out) throws IOException {
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(totalFlow);
    }

    // set方法,一次性設置屬性
    public void set(long upFlow, long downFlow){
        this.upFlow = upFlow;
        this.downFlow = downFlow;
        this.totalFlow = upFlow + downFlow;
    }

    // 反序列化 - 順序和序列化保持一致
    public void readFields(DataInput in) throws IOException {
        this.upFlow = in.readLong();
        this.downFlow = in.readLong();
        this.totalFlow = in.readLong();
    }

    public long getUpFlow() {
        return upFlow;
    }

    public long getDownFlow() {
        return downFlow;
    }

    public long getTotalFlow() {
        return totalFlow;
    }

    public void setUpFlow(long upFlow) {
        this.upFlow = upFlow;
    }

    public void setDownFlow(long downFlow) {
        this.downFlow = downFlow;
    }

    public void setTotalFlow(long totalFlow) {
        this.totalFlow = totalFlow;
    }

    // 使用製表符分隔
    @Override
    public String toString() {
        return "upFlow=" + upFlow +
                "\t" + downFlow +
                "\t" + totalFlow;
    }
}
相關文章
相關標籤/搜索