Apache Avro
定义:
avro是apache的一个子项目,是一个高性能序列化数据传输框架,采用json格式,数据结构丰富。
解决的问题是:
在海量数据传输过程中,能够提升数据传输性能
应用场景:
接收数据,发送kafka:
(1)序列化数据传输
只传输具体数据,不传输schema
{“name”:“xiaoli”,“age”:“20”,“address”:"北京}
类似于这种:xiaoli,20,北京
(2)序列化存储
本身就是字节数据,省去了将数据转换成字节数据存储的操作
- 优点
- 高性能序列化数据传输
- api友好
- 采用通用数据交互格式:json
- 数据结构丰富
- 8种基本:byte ,int ,float,double,boolean,null,string,long
- 6种复杂类型:record(组合),map,union,fix,array等
项目中主要使用的复杂类型是record
复杂类型record介绍
定义一个avro文件,通过schema定义数据结构:
{"namespace":"cn.itcast", =》 类路径
"name":"User", => 类名称
"type":"record", =》具体的复杂类型名称
“fileds”:[
{"name":"name","type":["string","null"]},
{"name":"age","type":["int","null"]},
{"name":"address","type":["string","null"]}
]
}
必选属性: (1)name:类名称
(2) “type”:“record”, =》具体的复杂类型名称
(3)“fileds” =》 包含具体的属性字段,可以包含多个,在这个数组里面,每一个字段的属性名称name和属性类型type,也是必须填写的。
可选择属性:“namespace”:“cn.itcast”, =》 类路径(命名空间)
avro案例
编写schema文件
user.avsc
{
"namespace":"cn.itcast",
"name":"User",
"type":"record",
"fields":[
{"name":"name","type":["string","null"]},
{"name":"age","type":["int","null"]},
{"name":"name","type":["string","null"]}
]
}
属性字段类型,只能是小写
编译schema
有两种方式:
-
在iead中使用maven的package打包编译
-
命令行
- java -jar avro-tools-1.8.1.jar compile schema user.avsc ./
导入依赖:
<dependencies>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--maven编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!--Avro编译插件-->
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<!--Avro源文件-->
<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
<!--Avro编译生成文件-->
<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
案例编写
package cn.itcast;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.specific.SpecificDatumReader;
import java.io.File;
import java.io.IOException;
/**
* @Date 2021
* 需求:使用avro对封装数据实现序列化和反序列化操作
*/
public class AvroDemo {
public static void main(String[] args) throws IOException {
/**
* 开发步骤:
* 1.新建bean对象
* 2.封装数据
* 3.序列化操作
* 4.反序列化操作
*/
//1.新建bean对象
User user = new User();
//2.封装数据
user.setName("蓝轩宇");
user.setAge(18);
user.setAddress("斗罗大陆");
User user1 = new User("唐三", 20000, "圣魂村");
User user2 = User.newBuilder()
.setName("胡烈那")
.setAge(20)
.setAddress("武魂殿")
.build();
// 3.序列化操作
// //定义schema
// SpecificDatumWriter<User> datumWriter = new SpecificDatumWriter<>(User.class);
SpecificDatumWriter<User> userSpecificDatumWriter1 = new SpecificDatumWriter<>(user.getSchema());
// DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(datumWriter);
// //设置输出路径
// //shchema和数据分离
// dataFileWriter.create(user.getSchema(),new File("test.avro"));
// //序列化数据
// dataFileWriter.append(user);
// dataFileWriter.append(user1);
// dataFileWriter.append(user2);
// //关流
// dataFileWriter.close();
//4.反序列化操作
//定义schema
SpecificDatumReader<User> datumReader = new SpecificDatumReader<>(User.class);
//读取序列化数据
DataFileReader<User> fileReader = new DataFileReader<>(new File("test.avro"), datumReader);
for (User user3 : fileReader) {
//打印明文数据
System.out.println(user3);
}
}
}