1. 程式人生 > >4.大資料學習之旅——Avro

4.大資料學習之旅——Avro

一、概述


Avro是一種遠端過程呼叫和資料序列化框架,是在Apache的Hadoop專案之內開發的。它使用JSON來定義資料類
型和通訊協議,使用壓縮二進位制格式來序列化資料。它主要用於Hadoop,它可以為持久化資料提供一種序列化格
式,併為Hadoop節點間及從客戶端程式到Hadoop服務的通訊提供一種電報格式。

二、序列化和反序列化


概述

資料序列化就是將物件或者資料結構轉化成特定的格式,使其可在網路中傳輸,或者可儲存在記憶體或者檔案中。反
序列化則是相反的操作,將物件從序列化資料中還原出來。
資料序列化的重點在於資料的交換和傳輸

衡量標準

  1. 序列化之後的資料大小
    因為序列化的資料要通過網路進行傳輸或者是儲存在記憶體或者檔案中,所以資料量越小,則儲存或者傳輸所
    用的時間就越少
  2. 序列化以及反序列化的耗時及佔用的CPU
  3. 是否能夠跨語言或者平臺
    因為現在的企業開發中,一個專案往往會使用到不同的語言來進行架構和實現。那麼在異構的網路系統中,
    網路雙方可能使用的是不同的語言或者是不同的作業系統,例如一端使用的是Java而另一端使用的C++;或者
    一端使用的是Windows系統而另一端使用的是Linux系統,那麼這個時候就要求序列化的資料能夠在不同的語
    言以及不同的平臺之間進行解析傳輸

Java原生序列化/反序列化機制的問題

  1. Java的原生序列化不能做到物件結構的服用,就導致序列化多個物件的時候資料量較大
  2. Java的原生序列化在使用的時候,是按照Java指定的格式將物件進行解析,解析為位元組碼格式,那麼此時其他
    的語言在接收到這個物件的時候,是無法解析或者解析較為困難。即Java的原生序列化機制是沒有做到跨語言
    或者跨平臺傳遞使用

三、常見序列化框架


Protobuf

Protobuf是Google公司提供的序列化/反序列化框架,特點如下:

  1. 平臺無關、語言無關。
  2. 二進位制、資料自描述。
  3. 提供了完整詳細的操作API。
  4. 高效能,比xml要快20-100倍
  5. 尺寸小,比xml要小3-10倍,高可擴充套件性
  6. 資料自描述、前後相容

Thrift

Thrift是Facebook公司提供的序列化/反序列化的框架,2007年貢獻給了Apache。特點如下:

  1. 支援非常多的語言繫結
  2. thrift檔案生成目的碼,簡單易用、
  3. 訊息定義檔案支援註釋
  4. 資料結構與傳輸表現的分離,支援多種訊息格式
  5. 包含完整的客戶端/服務端堆疊,可快速實現RPC
  6. 支援同步和非同步通訊

三、Avro的特點


  1. 豐富的資料結構型別,8種基本資料型別以及6種複雜型別
  2. 快速可壓縮的二進位制形式
  3. 提供容器檔案用於持久化資料
  4. 遠端過程呼叫RPC框架
  5. 簡單的動態語言結合功能,Avro 和動態語言結合後,讀寫資料檔案和使用 RPC協議都不需要生成程式碼,而代
    碼生成作為一種可選的優化只值得在靜態型別語言中實現。而程式碼生成作為一種可選的優化只值得在靜態類
    型語言中實現。
    通過avro,每次進行序列化,根據模式(schema)檔案來序列化,可以提高效能。
    Avro是依賴於模式(schema),模式檔案是用json格式來表示的。如果是想利用avro實現序列化或rpc通訊,需要
    遵守schema的格式要求。基於模式的好處是使得序列化快速而又輕巧

四、Avro的格式說明


簡單型別

Avro定義了8種簡單資料型別,下表是其簡單說明:

Avro型別 說明
null 沒有值
boolean 一個二級制布林值
int 32位有符號整數
long 64位有符號整數
float 32位單精度浮點數
double 64位雙精度浮點數
bytes 8位無符號位元組序列
string 字元序列

複雜格式

Avro定義了六種複雜資料型別,每一種複雜資料型別都具有獨特的屬性,下表就每一種複雜資料型別進行說明。
在這裡插入圖片描述
在這裡插入圖片描述

每一種複雜資料型別都含有各自的一些屬性,其中部分屬性是必需的,部分是可選的。
這裡需要說明Record型別中field屬性的預設值,當Record Schema例項資料中某個field屬性沒有提供例項資料
時,則由預設值提供,具體值見下表。Union的field預設值由Union定義中的第一個Schema決定。

在這裡插入圖片描述

五、Avro的序列化與反序列化


  1. 建立Maven工程,匯入Avro的依賴
<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro</artifactId>
			<version>1.7.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro-ipc</artifactId>
			<version>1.7.5</version>
		</dependency>

完整的pom.xml檔案

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.test.avro</groupId>
	<artifactId>Avro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>Avro</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<compiler-plugin.version>2.3.2</compiler-plugin.version>
		<avro.version>1.7.5</avro.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.6.4</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro</artifactId>
			<version>1.7.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro-ipc</artifactId>
			<version>1.7.5</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${compiler-plugin.version}</version>
			</plugin>
			<plugin>
				<groupId>org.apache.avro</groupId>
				<artifactId>avro-maven-plugin</artifactId>
				<version>1.7.5</version>
				<executions>
					<execution>
						<id>schemas</id>
						<phase>generate-sources</phase>
						<goals>
							<goal>schema</goal>
							<goal>protocol</goal>
							<goal>idl-protocol</goal>
						</goals>
						<configuration>
							<!-- 表示Avro的模式檔案的儲存位置 -->
							<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
							<!-- 表示利用模式檔案生成的類存放的位置 -->
							<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
						</configuration>
					</execution>

				</executions>
			</plugin>
		</plugins>
	</build>
</project>

  1. 在指定的目錄下編輯一個avsc檔案。例如:
{
	"namespace":"avro.pojo",
	"type":"record",
	"name":"Person",
	"fields":
	[
		{"name":"username", "type":"string"},
		{"name":"age", "type":"int"},
		{"name":"no", "type":"string"}
	]
}
  1. 選中pom.xml檔案,右鍵,選擇Run as,點選Maven generate-sources
  2. 序列化操作
@Test
public void write() throws Exception{
	User u1=new User("Ken Tompson",194375);
	User u2=new User("丹尼斯·裡奇",194170);
	DatumWriter<User> dw=new SpecificDatumWriter<>(User.class);
	DataFileWriter<User> dfw=new DataFileWriter<>(dw);
	// 建立底層的檔案輸出通道
	// schema - 序列化類的模式
	// path - 檔案路徑
	dfw.create(u1.getSchema(),new File("1.txt"));
	// 把物件資料寫到檔案中
	dfw.append(u1);
	dfw.append(u2);
	dfw.close();
}
  1. 反序列化操作
@Test
public void read() throws Exception{
DatumReader<User> dr=
new SpecificDatumReader<>(User.class);
DataFileReader<User> dfr=
new DataFileReader<>(new File("1.txt"),dr);
//--通過迭代器,迭代出物件資料
while(dfr.hasNext()){
System.out.println(dfr.next());
}
}

六、RPC


概述

RPC 的全稱是 Remote Procedure Call(遠端過程呼叫) 是一種程序間通訊方式。它允許程式呼叫另一個地址空
間(通常是共享網路的另一臺機器上)的過程或函式,而不用程式設計師顯式編碼這個遠端呼叫的細節。 即程式設計師無論
是呼叫本地的還是遠端的,本質上編寫的呼叫程式碼基本相同。

起源

布魯斯·納爾遜1974年畢業於哈維·穆德學院,1976年在斯坦福大學獲得電腦科學碩士學位,1982年在卡內基梅
隆大學獲得電腦科學博士學位。在追求博士學位時,他開發了遠端過程呼叫(RPC)的概念。他和他的合作者安
德魯·伯雷爾因在RPC方面的工作而獲得了1994年ACM軟體系統獎。1996他加入思科系統擔任首席科學官。

特點

  1. 簡單:RPC 概念的語義十分清晰和簡單,這樣建立分散式計算就更容易。
  2. 高效:過程呼叫看起來十分簡單而且高效。
  3. 通用:在單機計算中過程往往是不同演算法部分間最重要的通訊機制。 通俗一點說,就是一般程式設計師對於本地
    的過程呼叫很熟悉,那麼我們在通過網路做遠端通訊時,通過RPC 把遠端呼叫做得和本地呼叫完全類似,那
    麼就更容易被接受,使用起來也就毫無障礙。

RPC架構

模組

  1. 使用者(User)
  2. 使用者存根(User-Stub)
  3. RPC通訊包(稱為RPCRuntime)
  4. 伺服器存根(Server-Stub)
  5. 伺服器(Server)

關係圖

在這裡插入圖片描述

過程

  1. 服務消費方(User)呼叫以本地呼叫方式呼叫服務
  2. User-stub(存根)接收到呼叫後負責將方法、引數等組裝成能夠進行網路傳輸的訊息體,並交給
    RPCRuntime模組
  3. RPCRuntime找到服務地址,並將訊息傳送到服務端
  4. 服務端的RPCRuntime收到訊息後,傳給Server-stub
  5. Server-stub根據解碼結果呼叫本地的服務
  6. 本地服務執行並將結果返回給Server-stub
  7. server stub將返回結果打包成訊息併發送至消費方
  8. client stub接收到訊息,並進行解碼
  9. 服務消費方得到最終結果

RPC呼叫細節

  1. 介面方式的呼叫
    RPC設計的目的在於可以讓呼叫者可以像以本地呼叫方式一樣呼叫遠端服務。具體實現的方式是呼叫介面的方
    式來呼叫。在java中,底層通過Java動態代理方式生成介面的代理類,代理類中封裝了與遠端服務通訊的細
    節。這些細節包括:

客戶端的請求訊息:

  1. 介面名稱
  2. 方法名
  3. 引數型別以及相應的引數值
  4. requestID,標識唯一請求id

伺服器端的返回訊息:

  1. 返回值
  2. requestID
  3. 序列化
  4. 通訊
    一般RPC通訊都是基於NIO進行通訊

RPC框架的特點

  1. 基於RPC的程序通訊方式
  2. 有自定義的一套序列化和反序列的機制
  3. 客戶端通過代理機制呼叫遠端方法
  4. 服務端通過回撥機制執行方法及返回結果
    Avro的RPC
  5. 建立客戶端的Maven工程,匯入Avro的依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.test.avro</groupId>
  <artifactId>Avroclient</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Avroclient</name>
  <url>http://maven.apache.org</url>

  <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<compiler-plugin.version>2.3.2</compiler-plugin.version>
		<avro.version>1.7.5</avro.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.6.4</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro</artifactId>
			<version>1.7.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro-ipc</artifactId>
			<version>1.7.5</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${compiler-plugin.version}</version>
			</plugin>
			<plugin>
				<groupId>org.apache.avro</groupId>
				<artifactId>avro-maven-plugin</artifactId>
				<version>1.7.5</version>  
				<executions>
					<execution>
						<id>schemas</id>
						<phase>generate-sources</phase>
						<goals>
							<goal>schema</goal>
							<goal>protocol</goal>
							<goal>idl-protocol</goal>
						</goals>
						<configuration>
							<!-- 表示Avro的模式檔案的儲存位置 -->
							<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
							<!-- 表示利用模式檔案生成的類存放的位置 -->
							<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
						</configuration>
					</execution>

				</executions>
			</plugin>
		</plugins>
	</build>
</project>
  1. 在指定的目錄下編輯一個avdl檔案。例如:
@namespace("rpc.service")
protocol AddService{
int add(int i,int y);
}

如果想要傳遞的是一個物件,則約束如下:

@namespace("rpc.service")
protocol TransferService{
 import schema "User.avsc";
 void parseUser(avro.domain.User user);
}

如果想要傳遞一個map,並且map裡包含一個物件的程式碼:

@namespace("rpc.service")
protocol MapService{
import schema "User.avsc";
void parseUserMap(map<avro.domain.User> userMap);
}
  1. 實現客戶端
public class Start {
public static void main(String[] args) throws Exception {
NettyTransceiver client=new NettyTransceiver(
new InetSocketAddress("127.0.0.1",8888));
//--因為介面不能直接使用,avro底層是通過jdk動態代理生成介面的代理物件
AddService proxy=
SpecificRequestor.getClient(AddService.class, client);
int result=proxy.add(2, 3);
System.out.println("客戶端收到結果:"+result);
}
}
  1. 伺服器端實現介面
public class AddServiceImpl implements AddService{
@Override
public int add(int a, int b) throws AvroRemoteException {
return a+b;
}
}
  1. 實現伺服器端
public class Start {
public static void main(String[] args) {
System.out.println(
            
           

相關推薦

4.資料學習——Avro

一、概述 Avro是一種遠端過程呼叫和資料序列化框架,是在Apache的Hadoop專案之內開發的。它使用JSON來定義資料類 型和通訊協議,使用壓縮二進位制格式來序列化資料。它主要用於Hadoop,它可以為持久化資料提供一種序列化格 式,併為Hadoop節點間及從客戶端程式到

記錄我的資料學習 ---01.使用VMware安裝CentOs7

前言 從2017年初開始接觸大資料,從一無所知,到慢慢探索,到最後能夠獨立開發大資料專案。為此,趁著專案空閒的時間,分享與記錄一下我的大資料學習之旅。 一.準備資料,下載CentOs 二.新建虛擬機器

13.資料學習——HBase第三天

LSM-TREE 概述 眾所周知傳統磁碟I/O是比較耗效能的,優化系統性能往往需要和磁碟I/O打交道,而磁碟I/O產 生的時延主要由下面3個因素決定: 1)尋道時間(將磁碟臂移動到適當的柱面上所需要的時間,尋道時移動到相鄰柱面移動所需 時間1ms,而隨機移動所需時間位5~1

12.資料學習——HBase第二天

HBASE完全分散式安裝 實現步驟 準備三臺虛擬機器,01作為主節點,02、03作為從節點。(把每臺虛擬機器防火牆都關掉,配 置免密碼登入,配置每臺的主機名和hosts檔案。) 01節點上安裝和配置:Hadoop+Hbase+JDK+Zookeeper

11.資料學習——HBase

一、HBASE概述 官方網址:http://hbase.apache.org/ HBase是一個分散式的、面向列的開源資料庫,該技術來源於Fay Chang 所撰寫的Google論文《Bigtable》一個結構 化資料的分散式儲存系統"。就像Bigtable利用了Google

10.資料學習——hive2

Hive解決資料傾斜問題 概述 什麼是資料傾斜以及資料傾斜是怎麼產生的? 簡單來說資料傾斜就是資料的key 的分化嚴重不均,造成一部分資料很多,一部分資料很少的局面。 舉個 word count 的入門例子,它的map 階段就是形成 (“aaa”,1)的形式,然後在redu

9.資料學習——hive

Hive介紹 Hadoop開發存在的問題 只能用java語言開發,如果是c語言或其他語言的程式設計師用Hadoop,存 在語言門檻。 需要對Hadoop底層原理,api比較瞭解才能做開發。 Hive概述 Hive是基於Hadoop的一個數據倉庫工具。可以將結構

8.資料學習——hadoop-Hadoop完全分散式配置

Hadoop完全分散式配置 關閉防火牆 修改主機名 配置hosts檔案。將需要搭建叢集的主機全部配置到hosts檔案中 192.168.32.138 hadoop01 192.168.32.139 hadoop02 192.168.32.14

7.資料學習——hadoop-MapReduce

序列化/反序列化機制 當自定義一個類之後,如果想要產生的物件在hadoop中進行傳輸,那麼需要 這個類實現Writable的介面進行序列化/反序列化 案例:統計每一個人產生的總流量 import java.io.DataInput; import java.io.DataOutp

5.資料學習——hadoop-HDFS

NameNode 檢視edits檔案: hdfs oev -i edits_0000000000000000022-0000000000000000023 -o edits.xml 檢視fsimage檔案: hdfs oiv -i fsimage_000000000000000002

5.資料學習——hadoop-簡介及偽分散式安裝

Hadoop簡介 是Apache的頂級專案,是一個可靠的、可擴充套件的、支援分散式計算的開源 專案。 起源 創始人:Doug Cutting 和Mike 2004 Doug和Mike建立了Nutch - 利用通用爬蟲爬取了網際網路上的所有數 據,獲取了10億個網頁資料 - 1

3.資料學習——Zookeeper

Zookeeper Zookeeper是開源的分散式的協調服務框架,是Apache Hadoop的子件,適用 於絕大部分分散式叢集的管理 分散式引發問題: 死鎖:至少有一個執行緒佔用了資源,但是不佔用CPU 活鎖:所有執行緒都沒有把持資源,但是執行緒卻是在不斷地

2.資料學習——紅黑樹

紅黑樹 自平衡二叉查詢樹 — 時間複雜度O(logn) 特徵: 每一個節點非紅即黑 根節點一定是黑色 所有的葉子節點一定是黑色的nil節點 紅節點的子節點一定是黑節點 任意一條路徑中的黑色節點個數一致 插入的節點一定是紅色 修復

1.資料學習——NIO

Concurrent包 jdk1.5所提供的一個針對高併發進行程式設計的包。 阻塞式佇列 - BlockingQueue 遵循先進先出(FIFO)的原則。阻塞式佇列本身使用的時候是需要指定界限。 ArrayBlockingQueue - 阻塞式順序佇列 - 底層是基於陣列來進

14.資料學習——HBASE表設計&HBase優化

HBASE表設計 Rowkey設計 Rowkey是不可分割的位元組數,按字典排序由低到高儲存在表中。 在設計HBase表時,Rowkey設計是最重要的事情,應該基於預期的訪問模式來為Rowkey建 模。Rowkey決定了訪問HBase表時可以得到的效能,原因有兩個: 1)R

16.資料學習——Storm叢集配置&Strom叢集中各角色說明&Storm併發機制*

實現步驟: 安裝和配置jdk 安裝和配置zookeeper 上傳和解壓storm 配置storm安裝目錄conf目錄下的storm.yaml檔案 storm.yaml配置示例: 注意配置項開頭需要有空格,:後面需要跟空格,否則啟動會報錯 5.

19.資料學習——flume介紹

flume介紹 概述 Flume最早是Cloudera提供的日誌收集系統,後貢獻給Apache。所以目前是Apache下的專案,Flume支援在日誌 系統中定製各類資料傳送方,用於收集資料。 Flume是一個高可用的,高可靠的魯棒性(robust 健壯性),分散式的海量日誌採集、聚合

資料學習2——從零開始搭hadoop完全分散式叢集

前言        本文從零開始搭hadoop完全分散式叢集,大概花費了一天的時間邊搭邊寫部落格,一步一步完成完成叢集配置,相信大家按照本文一步一步來完全可以搭建成功。需要注意的是本文限於篇幅和時間的限制,也是為了突出重點,一些很基礎的操作就不再詳細

資料學習SPARK計算天下

學習大資料技術,SPARK無疑是繞不過去的技術之一,它的重要性不言而喻,本文將通過提問的形式圍繞著SPARK進行介紹,希望對大家有幫助,與此同時,感謝為本文提供素材的科多大資料的武老師。 為了輔助大家更好去了解大資料技術,本文集中討論Spark的一系列技術問題,大家在學習過程中如果遇到困難,可以

資料學習小白如何學資料?(詳細篇)

大資料這個話題熱度一直高居不下,不僅是國家政策的扶持,也是科技順應時代的發展。想要學習大資料,我們該怎麼做呢?大資料學習路線是什麼?先帶大家瞭解一下大資料的特徵以及發展方向。 大資料的三個發展方向,平臺搭建/優化/運維/監控、大資料開發/設計/架構、資料分析/挖掘。 先說一下大資料的4V特徵: 資料