Как Apache AVRO сериализует (большие) структуры данных - PullRequest
4 голосов
/ 27 марта 2012

Я смотрю на использование AVRO на hadoop. Но я обеспокоен сериализацией больших структур данных и тем, как добавлять методы в (data-) классы.

В примере (взято из 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 сериализацию полного социального графа пользователя facebook в этой модели?

[То есть, если я хочу сериализовать одного пользователя, включает ли сериализация всех его друзей и их друзей и т. Д.?]

Если ответ положительный, я бы предпочел хранить идентификаторы друзей, а не ссылки, чтобы искать их в своем приложении при необходимости. В этом случае я хотел бы иметь возможность добавить метод, который возвращает настоящих друзей вместо идентификаторов.

Как можно обернуть / расширить сгенерированные Java-классы AVRO для добавления методов?

(также для добавления методов, которые возвращают, например, количество друзей)

Ответы [ 3 ]

3 голосов
/ 29 марта 2012

Относительно второго вопроса: Как я могу обернуть / расширить сгенерированные Java-классы AVRO для добавления методов?

Вы можете использовать AspectJ для добавления новых методов в существующий / сгенерированный класс.AspectJ требуется только во время компиляции.Подход иллюстрируется ниже.

Определить запись Person как Avro IDL ( person.avdl ):

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

использовать maven и avro-maven-Плагин для генерации Java-источников из AVDL:

<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 / generate-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());
}
2 голосов
/ 28 марта 2012

Сначала я пытаюсь ответить на первый вопрос:
В моем понимании AVRO не создан для хранения чего-то не иерархического. У этого также нет обозначения идентификаторов объекта. Он может хранить массивы, записи примитивных типов или любые их комбинации. Возможность перемещаться по графу объекта, на который вы ссылаетесь, способна к сериализации Java, что AVRO lacing
Таким образом, для хранения некоторого графика вы должны ввести свои собственные идентификаторы объектов и явно назначить их некоторым полям. Вы можете взглянуть на метод 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 голосов
/ 24 апреля 2012

Помимо попыток решить эти проблемы с Avro, которая может работать или не работать (я предполагаю, что расширение сгенерированного класса не будет работать хорошо независимо от того, как вы пытаетесь), вы можете рассмотреть возможность использования простого JSON (если у вас нет особых требований к Avro).Многие библиотеки поддерживают произвольные отображения POJO;а некоторые (например, Джексон ) также поддерживают сериализацию на основе Object Id (с 2.0.0).

...