2012-03-27 49 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)。