4

我正在考虑在 hadoop 上使用 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 类以添加方法?

(还添加返回例如朋友计数的方法)

4

3 回答 3

3

关于第二个问题:如何包装/扩展生成的 AVRO java 类以添加方法?

您可以使用 AspectJ 将新方法注入现有/生成的类。只有在编译时才需要 AspectJ。方法如下所示。

将 Person 记录定义为 Avro IDL ( person.avdl ):

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

使用 maven 和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() = firstName + 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 maven 插件来编织这个切面和生成的代码

<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());
}
于 2012-03-28T22:20:28.690 回答
2

我试图首先回答第一个问题:
据我所知,AVRO 并不是为了存储非分层的东西而构建的。它也没有对象 ID 的表示法。它可以存储数组、原始类型的记录或它们的任何组合。遍历您所指的对象图的能力是 Java 序列化的能力,其中 AVRO 系带
因此要存储一些图,您应该介绍自己的对象 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 生成的“数据”类作为成员放入其中。
同时,我认为从技术上扩展生成的类应该没问题。

于 2012-03-27T21:21:01.397 回答
0

除了尝试使用 Avro 解决这些问题,这可能会或可能不起作用(我的猜测是,无论您如何尝试扩展生成的类都不会很好地工作),您可以考虑使用纯 JSON(除非您对 Avro 有特定要求)。许多库支持任意 POJO 映射;有些(如Jackson)还支持基于 Object Id 的序列化(使用 2.0.0)。

于 2012-04-24T05:33:18.897 回答