2012-03-27 3 views
4

Я ищу использование AVRO на hadoop. Но я обеспокоен сериализацией больших структур данных и тем, как добавлять методы в классы (data-).Как 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.

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

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

ответ

3

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

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

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

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

использовать Maven и avro-maven-plugin для создания источников 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. Источники создаются в целевых/сгенерированных источниках/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()); 
} 
1

Я пытаюсь ответить на первое quesion первым:
В мере моего понимания AVRO не построено, чтобы сохранить что-то не иерархическое. Он также не имеет обозначений идентификаторов объектов. Он может хранить массивы, записи примитивных типов или любые их комбинации. Возможность трассировать граф объекта, на который вы ссылаетесь, является способностью Java Serialization, в которой 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.
Что касается второго вопроса - я не думаю, что это хорошая идея, чтобы изменить сгенерированный код. Я бы предложил создать класс со всеми методами/данными, которые вы хотите добавить, и поместить в него AV-класс с «данными».
В то же время, я думаю, что технически расширяемые сгенерированные классы должны быть в порядке.

0

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

Смежные вопросы