2012-03-27 50 views
4

我正在使用AVO在hadoop上。但我關心的是大數據結構的序列化以及如何向(數據)類添加方法。Apache AVRO如何序列化(大)數據結構

該示例(取自http://blog.voidsearch.com/bigdata/apache-avro-in-practice/)顯示了facebook用戶的模型。

{ 
    "namespace": "test.avro", 
    "name": "FacebookUser", 
    "type": "record", 
    "fields": [ 
     {"name": "name", "type": "string"}, 
     ..., 
     {"name": "friends", "type": "array", "items": "FacebookUser"} 
    ] 
} 

是否Avro的連載在這個模型中facebookuser的完整社交圖譜?

[也就是說,如果我想序列化一個用戶,請問系列化包括所有它的朋友和朋友的朋友等?]

如果答案是肯定的,我寧願存儲ID的朋友的而不是引用,在需要時查找我的應用程序。在這種情況下,我希望能夠添加一個返回實際朋友而不是ID的方法。

如何包裝/擴展生成的AVRO java類來添加方法?

(還補充說,返回例如朋友計數方法)

回答

3

關於第二個問題:如何包裝/擴展生成的AVRO java類以添加方法?

您可以使用AspectJ將新方法注入到現有/生成的類中。 AspectJ僅在編譯時需要。方法如下所示。

定義一個人記錄作爲阿夫羅IDL(person.avdl):

@namespace("net.tzolov.avro.extend") 
protocol PersonProtocol { 
    record Person { 
     string firstName; 
     string lastName; 
    }  
} 

使用行家和avro-maven-plugin從AVDL生成Java源代碼:

<dependency> 
    <groupId>org.apache.avro</groupId> 
    <artifactId>avro</artifactId> 
    <version>1.6.3</version> 
</dependency> 
    ...... 
    <plugin> 
     <groupId>org.apache.avro</groupId> 
     <artifactId>avro-maven-plugin</artifactId> 
     <version>1.6.3</version> 
     <executions> 
      <execution> 
       <id>generate-avro-sources</id> 
       <phase>generate-sources</phase> 
       <goals> 
        <goal>idl-protocol</goal> 
       </goals> 
       <configuration> 
        <sourceDirectory>src/main/resources/avro</sourceDirectory> 
        <outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory> 
       </configuration> 
      </execution> 
     </executions> 
    </plugin> 

上述結構假定person.avid文件位於src/main/resources/avro。信息源在target/generated-sources/java中生成。

生成的Person.java有兩個方法:getFirstName()和getLastName()。如果想將其與另一種方法延伸:getCompleteName() =名字+ lastName的話可以用下面的方面注入此方法:

package net.tzolov.avro.extend; 

import net.tzolov.avro.extend.Person; 

public aspect PersonAspect { 

    public String Person.getCompleteName() {   
     return this.getFirstName() + " " + this.getLastName(); 
    } 
} 

使用aspectj-maven-plugin行家插件來編織該方面與所生成的代碼

<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjrt</artifactId> 
    <version>1.6.12</version> 
</dependency> 
<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId> 
    <version>1.6.12</version> 
</dependency> 
    .... 
<plugin> 
    <groupId>org.codehaus.mojo</groupId> 
    <artifactId>aspectj-maven-plugin</artifactId> 
    <version>1.2</version> 
    <dependencies> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjrt</artifactId> 
      <version>1.6.12</version> 
     </dependency> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjtools</artifactId> 
      <version>1.6.12</version> 
     </dependency> 
    </dependencies> 
    <executions> 
     <execution> 
      <goals> 
       <goal>compile</goal> 
       <goal>test-compile</goal> 
      </goals> 
     </execution> 
    </executions> 
    <configuration> 
     <source>6</source> 
     <target>6</target> 
    </configuration> 
</plugin> 

和結果:

@Test 
public void testPersonCompleteName() throws Exception { 

    Person person = Person.newBuilder() 
      .setFirstName("John").setLastName("Atanasoff").build(); 

    Assert.assertEquals("John Atanasoff", person.getCompleteName()); 
} 
1

我想先回答第一個quesion:
在最好的我的理解AVRO沒有內置存儲不hierarchial東西。它也沒有對象ID的符號。它可以存儲數組,原始類型的記錄或它們的任何組合。您所指的能夠訪問對象圖的能力是Java序列化的能力,因此要存儲一些圖,您應該向您介紹自己的對象ID並明確地將它們分配給某些字段。 您可以在這裏看看getSchema方法:http://www.java2s.com/Open-Source/Java/Database-DBMS/hadoop-0.20.1/org/apache/avro/reflect/ReflectData.java.htm 它相當簡單...這是AVRO通過java類生成模式的一種方式。
關於第二個問題 - 我不認爲修改生成的代碼是個好主意。我建議使用所有想要添加的方法/數據創建類,並將AVRO生成的「數據」類作爲其中的成員。
同時,我認爲技術上擴展生成的類應該沒問題。

0

除了試圖解決這些問題的Avro,或者可能無法工作(我的猜測是擴展生成的類不會工作,無論你如何嘗試),你可以考慮使用普通的JSON(除非你對Avro有特殊要求)。 許多庫支持任意的POJO映射;有些(如Jackson)也支持基於對象ID的序列化(2.0.0)。