Apache Avro使用入门指南

http://www.iteblog.com/archives/1008


 Avro有C, C++, C#, Java, PHP, Python, and Ruby等语言的实现,本文只简单介绍如何在Java中使用Avro进行数据的序列化(data serialization)。本文使用的是Avro 1.7.4,这是写这篇文章时最新版的Avro。读完本文,你将会学到如何使用Avro编译模式、如果用Avro序列化和反序列化数据。

一、准备项目需要的jar包

  文本的例子需要用到的Jar包有这四个:avro-1.7.1.jar、avro-tools-1.7.4.jar、 jackson-core-asl-1.8.8.jar、jackson-mapper-asl-1.8.8.jar,请先将这几个jar包下载好,并存放在一个地方(本文是存放在$HIVE_HOME/lib目录中)。如果你是用Maven,你可以在你项目的pom.xml文件中加入以下依赖:

01 <dependency>
02   <groupId>org.apache.avro</groupId>
03   <artifactId>avro</artifactId>
04   <version>1.7.4</version>
05 </dependency>
06  
07 <plugin>
08   <groupId>org.apache.avro</groupId>
09   <artifactId>avro-maven-plugin</artifactId>
10   <version>1.7.4</version>
11   <executions>
12     <execution>
13       <phase>generate-sources</phase>
14       <goals>
15         <goal>schema</goal>
16       </goals>
17       <configuration>
18         <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
19         <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
20       </configuration>
21     </execution>
22   </executions>
23 </plugin>
24 <plugin>
25   <groupId>org.apache.maven.plugins</groupId>
26   <artifactId>maven-compiler-plugin</artifactId>
27   <configuration>
28     <source>1.6</source>
29     <target>1.6</target>
30   </configuration>
31 </plugin>

  当然,如果你需要,你也可以在Avro源码中进行编译,获取avro-1.7.1.jar和avro-tools-1.7.4.jar。关于如何编译avro已经超出本文的范围。

二、定义模式(Schema)

  在avro中,它是用Json格式来定义模式的。模式可以由基础类型(null, boolean, int, long, float, double, bytes, and string)和复制类型(record, enum, array, map, union, and fixed)的数据组成。本文只是定义了一个简单的模式user.avsc:

01 {
02    "namespace""example.avro",
03    "type""record",
04    "name""User",
05    "fields": [
06       {
07          "name""name",
08          "type""string"
09       },
10       {
11          "name""favorite_number",
12          "type": [
13             "int",
14             "null"
15          ]
16       },
17       {
18          "name""favorite_color",
19          "type": [
20             "string",
21             "null"
22          ]
23       }
24    ]
25 }

  上面的模式是定义了一个用户的记录,在模式定义中,必须包含它的类型("type": "record")、一个名字("name": "User")以及fields。在本例中fields包括了name, favorite_number和favorite_color,上面的模式我们还定义了一个命名空间 ("namespace": "example.avro"),namespace可以名字一起使用,从而组成模式的全名(本例为example.avro.User)。

三、编译模式

  Avro可以允许我们根据模式的定义而生成相应的类,一旦我们定义好相关的类,我们程序中就不需要直接使用模式了。可以用avro-tools jar包来生成代码,语法如下:

1 java -jar $HIVE_HOME/lib/avro-tools-1.7.4.jar
2      compile schema
3      <schema file> <destination>

所以,在本例中我们可以这样来使用

1 java -jar $HIVE_HOME/lib/avro-tools-1.7.4.jar compile schema user.avsc .

  这时候,在当前目录下会生成example/avro/User.java类,细心的读者可能会发现example/avro不就是模式定义中的namespace么?的确是的。

  如果你直接用Avro Maven plugin,那么你就不需要手动的编译模式,因为Avro Maven plugin会自动给你编译好。

  现在我们已经生成好了一个User.java类,我们就可以用代码生成User,并用avro将它序列化存放到本地文件中,最后我们再将其反序列化。

四、如何使用

我们可以用下面的代码生成几个User:

01 User user1 = new User();
02 user1.setName("Alyssa");
03 user1.setFavoriteNumber(256);
04 // Leave favorite color null
05  
06 // Alternate constructor
07 User user2 = new User("Ben"7"red");
08  
09 // Construct via builder
10 User user3 = User.newBuilder()
11              .setName("Charlie")
12              .setFavoriteColor("blue")
13              .setFavoriteNumber(null)
14              .build();

从上面的列子中,我们可以看出,我们可以调用User的构造函数或者是builder来获取一个User实例。下面对上述的几个User进行序列化操作,并将序列化的数据存放到users.avro文件中:

1 // Serialize user1 and user2 to disk
2 File file = new File("users.avro");
3 DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
4 DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
5 dataFileWriter.create(user1.getSchema(), new File("users.avro"));
6 dataFileWriter.append(user1);
7 dataFileWriter.append(user2);
8 dataFileWriter.append(user3);
9 dataFileWriter.close();

运行完这个代码之后,将会在磁盘产生users.avro文件,里面是用avro序列化user的数据。我们可以对其进行反序列化,获取到原来的数据:

01 // Deserialize Users from disk
02 DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
03 DataFileReader<User> dataFileReader =
04                            new DataFileReader<User>(file, userDatumReader);
05 User user = null;
06 while (dataFileReader.hasNext()) {
07     // Reuse user object by passing it to next(). This saves us from
08     // allocating and garbage collecting many objects for files with
09     // many items.
10     user = dataFileReader.next(user);
11     System.out.println(user);
12 }

这段代码将会产生成以下的结果:

1 {"name""Alyssa""favorite_number"256"favorite_color"null}
2 {"name""Ben""favorite_number"7"favorite_color""red"}
3 {"name""Charlie""favorite_number"null"favorite_color""blue"}
五、一个完整的例子
01 import java.io.*;
02 import java.lang.*;
03 import org.apache.avro.io.DatumWriter;
04 import org.apache.avro.io.DatumReader;
05 import org.apache.avro.specific.SpecificDatumWriter;
06 import org.apache.avro.specific.SpecificDatumReader;
07 import org.apache.avro.file.DataFileWriter;
08 import org.apache.avro.file.DataFileReader;
09 import example.avro.User;
10  
11 public class Test {
12     public static void main(String args[]) {
13         User user1 = new User();
14         user1.setName("Alyssa");
15         user1.setFavoriteNumber(256);
16         // Leave favorite color null
17  
18         // Alternate constructor
19         User user2 = new User("Ben"7"red");
20  
21         // Construct via builder
22         User user3 = User.newBuilder()
23              .setName("Charlie")
24              .setFavoriteColor("blue")
25              .setFavoriteNumber(null)
26              .build();
27         //Serialize user1, user2 and user3 to disk
28         File file = new File("users.avro");
29         DatumWriter<User> userDatumWriter =
30                    new SpecificDatumWriter<User>(User.class);
31         DataFileWriter<User> dataFileWriter =
32                    new DataFileWriter<User>(userDatumWriter);
33         try {
34             dataFileWriter.create(user1.getSchema(), new File("users.avro"));
35             dataFileWriter.append(user1);
36             dataFileWriter.append(user2);
37             dataFileWriter.append(user3);
38             dataFileWriter.close();
39         catch (IOException e) {
40         }
41         //Deserialize Users from dist
42         DatumReader<User> userDatumReader =
43                              new SpecificDatumReader<User>(User.class);
44         DataFileReader<User> dataFileReader = null;
45         try {
46             dataFileReader = new DataFileReader<User>(file, userDatumReader);
47         catch (IOException e) {
48         }
49         User user = null;
50         try {
51             while (dataFileReader.hasNext()) {
52                 // Reuse user object by passing it to next(). This saves
53                 // us from allocating and garbage collecting many objects for
54                 // files with many items.
55                 user = dataFileReader.next(user);
56                 System.out.println(user);
57             }
58         catch (IOException e) {
59         }
60     }
61 }

编译上述代码:

1 javac -classpath /home/q/hive-0.11.0/lib/avro-1.7.1.jar
2                  :/home/q/hive-0.11.0/lib/avro-tools-1.7.4.jar
3                  :/home/q/hive-0.11.0/lib/jackson-core-asl-1.8.8.jar
4                  :/home/q/hive-0.11.0/lib/jackson-mapper-asl-1.8.8.jar
5                  example/avro/User.java Test.java

运行上述代码:

1 java  -classpath /home/q/hive-0.11.0/lib/avro-1.7.1.jar
2                  :/home/q/hive-0.11.0/lib/avro-tools-1.7.4.jar
3                  :/home/q/hive-0.11.0/lib/jackson-core-asl-1.8.8.jar
4                  :/home/q/hive-0.11.0/lib/jackson-mapper-asl-1.8.8.jar:User.jar:.
5                  Test
本博客文章除特别声明,全部都是原创!
尊重原创,转载请注明: 转载自过往记忆(http://www.iteblog.com/)
本文链接地址: 《Apache Avro使用入门指南》(http://www.iteblog.com/archives/1008)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值