Hadoop 之管理 Avro

全面解析大数据框架Hadoop主要模块 hadoop Common::包括Hadoop常用的工具类,由原来的Hadoop core部分更名而来。主要包括系统配置工具Configuration、远程过程调用RPC、序列化机制和Hadoop抽象文件系统FileSystem等。它们为在通用硬件上搭建云计算环境提供基本的服务,并为运行在该平台上的软件开发提供了所需的API。来源:大数据资讯平台 Hadoop Distrib... 阅读详情


Hadoop 之管理 Avro



Apache Avro 是一个中立语言的(language-neutral) 数据序列化系统。该项目由 Doug Cutting (the creator of Hadoop) 创建,旨在解决 Hadoop Writables 的
主要不足:缺乏语言可移植性。拥有一个可以被多种语言处理的数据格式比只绑定到单一语言上的数据格式更易于与更广泛的应用共享数据集。 Avro 目前可以被
C, C++, C#, Java, JavaScript, Perl, PHP, Python, and Ruby 语言处理。

但为什么要创建一个新的数据序列化系统? Avro 具有一系列特性,它们一起形成了与其他系统的不同,例如,Apache Thrift or Google’s Protocol Buffers .
与这些系统及其他系统类似, Avro 数据描述使用了一种语言独立的架构(a language-independent schema)。但与其他系统不同的是,在 Avro 中代码生成是可选的,
这意味着可以对遵循一个指定模式(schema)的数据进行读写操作,即使在此之前代码从没看到过这个特定的数据模式。为此, Avro 假定数据模式总是存在的(schema
is always present) ———— 在读取数据和写入数据时都存在(at both read and write time) ———— 这样可以形成一个非常紧凑的编码,因为编码的值不需要与一个
字段标识符绑定。

Avro schemas 通常写成 JSON 格式,数据通常用一个二进制格式编码,但也有其他选项。有一个称为 Avro IDL 的高级别的语言(a higher-level language called
Avro IDL) 用于程序员们使用更熟悉的 C-like 类的语言来写 Avro schemas 。还有一个基于 JSON 的数据编码器(a JSON-based data encoder), 对于人类是可读的,
对构造原型和调试 Avro 数据很有用。

Avro 规范(Avro specification)精确定义了所有实现必须支持的二进制数据格式,也定义了一些 Avro 实现应该支持的一些其他特性。但规范中没有定义 API 规范:
实现对 API 拥有全方位的控制能力,可以根据需要操作 Avro 数据并给出相应的 API, 因为每个 API 都是语言相关的。事实上,只要有一种二进制格式就足够了。

Avro 具有丰富的模式解析(schema resolution) 能力。在精心定义的约束条件下,用于读取数据的模式不需要与用于写入数据的模式相同。这就是 Avro 支持 模式
演变的机制(This is the mechanism by which Avro supports schema evolution)。例如,通过在用于读取老数据的模式中声明,一个新的,可选的的字段可以加入
到一个记录中(record)。新客户端和旧的客户端一样能够读取老的数据,而新客户端可以使用新字段写入新的数据。相反,如果旧的客户端看到新编码的数据,它会
优雅地忽略新字段并继续处理就像它对旧的数据格式所做的一样。

Avro 为顺序的对象规范了一个对象容器格式(object container format), 类似于 Hadoop 的顺序文件。一个 Avro datafile 有一个元数据节(metadata section)
模式存储在其中,使文件成为自描述的(self-describing)。 Avro datafiles 支持压缩和可切分,这是 MapReduce 数据输入格式至关重要的特性。事实上,Avro
datafile 的支持远远超出 MapReduce:本书中所有的数据处理框架(Pig, Hive, Crunch, Spark) 都可以读写 Avro datafiles 。

Avro 也可用于 RPC

*
*
*

1. Avro 数据类型与模式 (Avro Data Types and Schemas)
--------------------------------------------------------------------------------------------------------------------------------------------------
Avro 定义了少量的基本数据类型,可以通过模式(by writing schemas)的方式用于建立应用程序特定的(application-specific)数据结构。为了互操作性,实现必须
支持所有的 Avro 类型。

Avro 基本数据类型列于下表。每种基本类型可以通过使用 type 属性使用更冗长的形式,例如:
    { "type": "null" }

    
                                    Avro primitive types

            +===========+===========================================================+===========+
            |    类型    |                描述                                        |    Schema    |
            +-----------+-----------------------------------------------------------+-----------+
            | null        | The absence of a value                                    | "null"    |
            +-----------+-----------------------------------------------------------+-----------+
            | boolean    | A binary value                                            | "boolean"    |
            +-----------+-----------------------------------------------------------+-----------+
            | int        | 32-bit signed integer                                        | "int"        |
            +-----------+-----------------------------------------------------------+-----------+
            | long        | 64-bit signed integer                                        | "long"    |
            +-----------+-----------------------------------------------------------+-----------+
            | float        | Single-precision (32-bit) IEEE 754 floating-point number    | "float"    |
            +-----------+-----------------------------------------------------------+-----------+
            | double    | Double-precision (64-bit) IEEE 754 floating-point number    | "double"    |
            +-----------+-----------------------------------------------------------+-----------+
            | bytes        | Sequence of 8-bit unsigned bytes                            | "bytes"    |
            +-----------+-----------------------------------------------------------+-----------+
            | string    | Sequence of Unicode characters                            | "string"    |
            +-----------+-----------------------------------------------------------+-----------+

Avro 也定义了复杂类型,如下表:


                                            Avro complex types
                                    
+===========+=======================================================================================+===========================================+
|    类型    |                                描述                                                    |    Schema example                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| array        | An ordered collection of objects. All objects in a particular array must have the        | {                                            |
|            | same schema.                                                                            |    "type": "array",                        |
|            |                                                                                        |    "items": "long"                            |
|            |                                                                                        | }                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| map        | An unordered collection of key-value pairs. Keys must be strings and values may be    | {                                            |
|            | any type, although within a particular map, all values must have the same schema.        |    "type": "map",                            |
|            |                                                                                        |    "values":"string"                        |
|            |                                                                                        | }                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| record    | A collection of named fields of any type.                                                | {                                            |
|            |                                                                                        |    "type": "record",                        |
|            |                                                                                        |    "name": "WeatherRecord",                |
|            |                                                                                        |    "doc": "A weather reading.",            |
|            |                                                                                        |    "fields": [                                |
|            |                                                                                        |    {"name":"year", "type":"int"},            |
|            |                                                                                        |    {"name":"temperature","type": "int"},    |
|            |                                                                                        |    {"name":"stationId","type": "string"}]    |
|            |                                                                                        | }                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| enum        | A set of named values.                                                                | {                                            |
|            |                                                                                        |    "type": "enum",                            |
|            |                                                                                        |    "name":"Cutlery",                        |
|            |                                                                                        |    "doc": "An eating utensil.",            |
|            |                                                                                        |    "symbols":                                |
|            |                                                                                        |    ["KNIFE", "FORK","SPOON"]                |
|            |                                                                                        | }                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| fixed        | A fixed number of 8-bit unsigned bytes.                                                | {                                            |
|            |                                                                                        |    "type": "fixed",                        |
|            |                                                                                        |    "name":"Md5Hash",                        |
|            |                                                                                        |    "size": 16                                |
|            |                                                                                        | }                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
| union        | A union of schemas. A union is represented by a JSON array, where each element in the    | [                                            |
|            | array is a schema. Data represented by a union must match one of the schemas in the    |    "null",                                    |
|            | union.                                                                                |    "string",                                |
|            |                                                                                        |     {"type": "map","values": "string"}         |
|            |                                                                                        | ]                                            |
+-----------+---------------------------------------------------------------------------------------+-------------------------------------------+
    
    
每种 Avro 语言 API 都有对应于每一个 Avro 类型语言特定的表现形式。例如, Avro 的 double 类型,在 C, C++ 以及 Java 中由 double 表示,在 Python 中由一个
float 表示,而在 Ruby 中由 Float 表示。

对于一种语言,可能有不止一种的表现形式,或者映射。所有语言都支持一个动态映射,即便运行前不知道该模式也可以使用。 Java 称之为通用映射(Generic mapping)

另外, Java 和 C++ 实现能为一个 Avro schema 生成代码来表示数据。代码生成(Code generation),在 Java 中称为特殊映射(Specific mapping) ,如果在读取或写入
数据之前有一个 schema 的拷贝能优化数据处理。生成的类也为用户代码提供了一个比通用映射更加面向问题域的API(a more domain-oriented API)。

Java 还有第三种映射,即反射映射(the Reflect mapping),使用反射机制将 Avro 类型映射为预先存在的 Java 类型。这种映射比通用和特殊映射慢,但可能是定义类型
的一个便利方法,因为 Avro 能自动推断一个 schema .

下表列举了 Java 的类型映射。如表所示,特殊映射与通用映射相同,除非特别标注(并且反射映射与特殊映射相同,除非特别说明)。特殊映射与通用映射只在 record,
enum, 以及 fixed 类型上不同,它们都有生成的类(类名由 name 和可选的 namespace 属性控制)。
    
    
                    Avro Java type mappings
                    
+===========+===============================================+===========================================+===========================================+
| Avro 类型    | Generic Java mapping                            | Specific Java mapping                        | Reflect Java mapping                        |
+-----------+-----------------------------------------------+-------------------------------------------+-------------------------------------------+
| null        | null type                                                                                                                                |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| boolean    | boolean                                                                                                                                |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| int        | int                                                                                        | byte, short, int                            |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| long        | long                                                                                                                                    |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| float        | float                                                                                                                                    |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| double    | double                                                                                                                                |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| bytes        | java.nio.ByteBuffer                                                                        | Array of bytes                            |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| string    | org.apache.avro.util.Utf8 or java.lang.String                                             | java.lang.String                            |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| array        | org.apache.avro.generic.GenericArray                                                        | Array or java.util.Collection                |
+-----------+-------------------------------------------------------------------------------------------+-------------------------------------------+
| map        | java.util.Map                                                                                |                                            |
+-----------+-----------------------------------------------+-------------------------------------------+-------------------------------------------+
| record    | org.apache.avro.generic.GenericRecord            | Generated class implementing                | Arbitrary user class with constructor;    |
|            |                                                | org.apache.avro.specific.SpecificRecord    | all inherited instance fields are used    |
+-----------+-----------------------------------------------+-------------------------------------------+-------------------------------------------+
| enum        | java.lang.String                                | Generated Java enum                        | Arbitrary Java enum                        |
+-----------+-----------------------------------------------+-------------------------------------------+-------------------------------------------+
| fixed        | org.apache.avro.generic.GenericFixed            | Generated class implementing                | org.apache.avro.generic.GenericFixed        |
|            |                                                | org.apache.avro.specific.SpecificFixed    |                                            |
+-----------+-----------------------------------------------+-------------------------------------------+-------------------------------------------+
| union        | java.lang.Object                                                                                                                        |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------+

    
    NOTE:
    ------------------------------------------------------------------------------------------------------------------------------------------------
    Avro string 能被表示为 Java String 或者 the Avro Utf8 Java 类型。使用 Utf8 是因为效率:因为它是可变的,一个 Utf8 实例可以重用读取或写入一系列值。
    同时,Java String 在对象创建时解码 UTF-8,而 Avro Utf8 是延迟解码的,在有些情况下能提升性能。
    
    Utf8 实现了 Java’s java.lang.CharSequence 接口,提供一些与 Java 类库的互操作性。其他情况,可能有必要把 Utf8 实例转换为 String 对象,通过调用它的
    toString() method .
    
    Utf8 是通用映射和特殊映射的默认类型,但对于一个特定的映射使用 String 类型也是可以的。有很多方法可以做到这一点,第一种方法是在 schema 中使用
    String 设置 avro.java.string 属性:
    
        { "type": "string", "avro.java.string": "String" }
        
    或者,对于特殊映射,可以生成具有基于 String 的 getter 和 setter 的类。如果使用 Avro Maven 插件,这可以通过设置配置属性 stringType 为 String 。
    
    最后,注意 Java 反射映射总是使用 String 对象,因其设计用于 Java 兼容性,而不是考虑性能。
    

*
*
*
    
2. 内存中的序列化和反序列化 (In-Memory Serialization and Deserialization)
--------------------------------------------------------------------------------------------------------------------------------------------------
Avro 为序列化和反序列化提供了 API, 这对集成 Avro 到现有系统中很有用,例如一个已定义好了分帧格式的消息系统。其他情况,可以考虑使用 Avro datafile 格式。    
    
写一个 Java 程序用来从流中读取和写出到流。以一个简单的 Avro schema 开始,表示一对字符串作为一条记录:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings.",
        "fields": [
        {"name": "left", "type": "string"},
        {"name": "right", "type": "string"}
        ]
    }

如果这个 schema 保存到一个类路径上文件(a file on the classpath), 名为 StringPair.avsc(.avsc is the conventional extension for an Avro schema)。可以
使用下面两行代码载入:

    Schema.Parser parser = new Schema.Parser();
    Schema schema = parser.parse(getClass().getResourceAsStream("StringPair.avsc"));

可以使用 Generic API 创建一个 Avro record 实例:

    GenericRecord datum = new GenericData.Record(schema);
    datum.put("left", "L");
    datum.put("right", "R");

下一步,序列化记录到一个 output stream:

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
    Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);
    writer.write(datum, encoder);
    encoder.flush();
    out.close();
    
这里有两个重要的对象:DatumWriter 和 Encoder 。一个 DatumWriter 将数据对象转换成一个 Encoder 可以理解的类型,Encoder 之后写出到 output stream. 这里
使用了一个 GenericDatumWriter, 传递 GenericRecord 的字段给 Encoder .

GenericDatumWriter 需要把 schema 传递过来,因为它依据这个 schema 来确定数据对象里的值来写出到数据流。在调用 writer 的 write() method 之后,刷新encoder,
然后关闭输出流。

可以反转这个过程,从字节缓存中读取对象:

    DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema);
    Decoder decoder = DecoderFactory.get().binaryDecoder(out.toByteArray(),    null);
    GenericRecord result = reader.read(null, decoder);
    
    assertThat(result.get("left").toString(), is("L"));
    assertThat(result.get("right").toString(), is("R"));

从 result.get("left") and result.get("right") 返回的对象是 Utf8 类型, 因此这里通过调用 toString() 方法转换为 Java String 对象。


    
    The Specific API
    ------------------------------------------------------------------------------------------------------------------------------------------------
    看下等价的使用 Specific API 的代码。可以通过使用 Avro Maven 插件编译从 schema 文件生成 StringPair class 。相关 POM :
    
    <project>
        ...
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.avro</groupId>
                    <artifactId>avro-maven-plugin</artifactId>
                    <version>${avro.version}</version>
                    <executions>
                        <execution>
                            <id>schemas</id>
                            <phase>generate-sources</phase>
                            <goals>
                                <goal>schema</goal>
                            </goals>
                            <configuration>
                                <includes>
                                    <include>StringPair.avsc</include>
                                </includes>
                                <stringType>String</stringType>
                                <sourceDirectory>src/main/resources</sourceDirectory>
                                <outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        ...
    </project>

    作为 Maven 的备选方案,可以使用 Avro’s Ant task
    org.apache.avro.specific.SchemaTask ,或 Avro command-line tools 用于为 schema 生成 Java 代码。
    
    在序列化和反序列化代码中,作为替代 GenericRecord 构造 StringPair 实例,使用一个 SpecificDatumWriter 写出到数据流,并
    使用一个 SpecificDatumReader 读回对象:
    
    StringPair datum = new StringPair();
    datum.setLeft("L");
    datum.setRight("R");
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DatumWriter<StringPair> writer = new SpecificDatumWriter<StringPair>(StringPair.class);
    Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);
    writer.write(datum, encoder);
    encoder.flush();
    out.close();
    
    DatumReader<StringPair> reader =
    new SpecificDatumReader<StringPair>(StringPair.class);
    Decoder decoder = DecoderFactory.get().binaryDecoder(out.toByteArray(), null);
    StringPair result = reader.read(null, decoder);

    assertThat(result.getLeft(), is("L"));
    assertThat(result.getRight(), is("R"));
    
*
*
*

3. Avro 数据文件 (Avro Datafiles)
--------------------------------------------------------------------------------------------------------------------------------------------------    
Avro 的对象容器文件格式用于存储 Avro 对象序列(sequences of Avro objects). 它非常类似于 Hadoop 的 sequence 文件格式设计。它们主要的区别在于 Avro
Datafiles 为跨语言可移植设计的,因此,例如可以用 Python 写入一个文件而使用 C 语言中读出。

一个 datafile 有一个文件头包含元数据(metadata), 其中含有 Avro schema 和一个同步标记(sync marker), 后跟一系列的(可选压缩的)数据块,数据块中包含已序列
化的 Avro 对象。数据块由文件中唯一的一个同步标记分隔,在定位到文件中任意的一个点之后,可以快速地与一个数据块边界重新同步,例如一个 HDFS 数据块边界。
因此,Avro Datafiles 是可切分的,这使它对高效的 MapReduce 处理易于控制。

把 Avro 对象写入一个数据文件与写入到一个流中类似。使用一个 DatumWriter, 但不使用 Encoder, 使用 DatumWriter 创建一个 DataFileWriter 实例。然后创建一个
新的数据文件(which, by convention, has a .avro extension) 并把对象追加到文件:

    File file = new File("data.avro");
    DatumWriter<GenericRecord> writer =
    new GenericDatumWriter<GenericRecord>(schema);
    DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(writer);
    dataFileWriter.create(schema, file);
    dataFileWriter.append(datum);
    dataFileWriter.close();

写入数据文件的对象必须遵循文件的 schema, 否则,调用 append() method 时会抛出异常。

这个例子演示了写入到一个本地文件(java.io.File in the previous snippet), 但实际上通过调用 DataFileWriter 的重载 create() method,可以写入到任何
java.io.OutputStream . 例如写到 HDFS 上的一个文件,通过调用 FileSystem 的 Create() 方法得到一个 OutputStream 。

从一个数据文件中读回对象与之前从一个 in-memory 流中读取对象类似,一个重要的区别是:不需要指定一个 schema, 因为它可以从文件的元数据中读取。实际
上,可以从 DataFileReader 实例上得到 schema, 使用 getSchema() 方法,并且可以验证它是写入原始对象使用的 schema :

    DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>();
    DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader);
    assertThat("Schema is the same", schema, is(dataFileReader.getSchema()));
    
DataFileReader 是一个常规的 Java 迭代器,因此可以通过调用它的 hasNext() and next() methods 从头至尾迭代它的数据对象:

    assertThat(dataFileReader.hasNext(), is(true));
    GenericRecord result = dataFileReader.next();
    assertThat(result.get("left").toString(), is("L"));
    assertThat(result.get("right").toString(), is("R"));
    assertThat(dataFileReader.hasNext(), is(false));
    
然而,不是使用通常的 next() 方法,而应优先使用它带有一个对象返回实例的重载形式(in this case, GenericRecord),因为它会重用这个对象,为含有很多对象的文件
节约了对象分配和垃圾回收的开销。下面是习惯用法:

    GenericRecord record = null;
    while (dataFileReader.hasNext()) {
        record = dataFileReader.next(record);
        // process record
    }
    
如果对象重用不重要,可以使用如下比较短的形式:
    
    for (GenericRecord record : dataFileReader) {
        // process record
    }

对于通常情况是,读取一个在 Hadoop 文件系统上的文件,使用一个 Hadoop Path 对象的 Avro 的 FsInput 来指定输入文件。 DataFileReader 实际上提供了随机访问
Avro 数据文件的能力(via its seek() and sync() methods),然而,大多数情况下,顺序的流访问就足够了,使用 DataFileStream . DataFileStream 可以从任何的
Java InputStream 中读取数据。



*
*
*

4. 互操作性 (Interoperability)
--------------------------------------------------------------------------------------------------------------------------------------------------
为了演示 Avro 的语言互操作性,使用一种语言写入一个数据文件(Python),然后使用另一种语言读取(Java)



    1. Python API
    ----------------------------------------------------------------------------------------------------------------------------------------------
    下面的程序从标准输入读取逗号分隔的字符串,把它们作为 StringPair records 写入到一个 Avro datafile. 创建了一个 DatumWriter 和一个 DataFileWriter
    对象。注意,代码中嵌入了 Avro schema , 尽管可以从一个文件中读取获得相同的效果。
    
    Python 把 Avro records 表示为 dictionaries; 从标准输入读取的每一行被转化成一个 dict 对象,然后追加给 DataFileWriter.
    
        //A Python program for writing Avro record pairs to a datafile
        import os
        import string
        import sys
        from avro import schema
        from avro import io
        from avro import datafile
        if __name__ == '__main__':
        if len(sys.argv) != 2:
        sys.exit('Usage: %s <data_file>' % sys.argv[0])
        avro_file = sys.argv[1]
        writer = open(avro_file, 'wb')
        datum_writer = io.DatumWriter()
        schema_object = schema.parse("\
        { "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings.",
        "fields": [
        {"name": "left", "type": "string"},
        {"name": "right", "type": "string"}
        ]
        }")
        dfw = datafile.DataFileWriter(writer, datum_writer, schema_object)
        for line in sys.stdin.readlines():
        (left, right) = string.split(line.strip(), ',')
        dfw.append({'left':left, 'right':right});
        dfw.close()
    
    运行这个程序之前,需要为 Python 安装 Avro:

        % easy_install avro
    
    运行程序,指定要写入的文件名(pairs.avro),然后通过标准输入发送输入对,使用 Ctrl-D 标记文件结束:
    
        % python ch12-avro/src/main/py/write_pairs.py pairs.avro
        a,1
        c,2
        b,3
        b,2
        ^D
    
    
    2. Avro 工具集 (Avro Tools)
    ----------------------------------------------------------------------------------------------------------------------------------------------    
    下一步,使用 Avro 工具(written in Java) 来显示 pairs.avro 文件的内容。其 tojson command 将一个 Avro datafile 转换为 JSON 并打印到控制台:
    
        % java -jar $AVRO_HOME/avro-tools-*.jar tojson pairs.avro
        {"left":"a","right":"1"}
        {"left":"c","right":"2"}
        {"left":"b","right":"3"}
        {"left":"b","right":"2"}
    
    结果成功地在两个 Avro 实现之间(Python and Java)交换了复杂的数据。
    
    
    
*
*
*

5. Schema 解析 (Schema Resolution)
--------------------------------------------------------------------------------------------------------------------------------------------------
可以选择使用一种与写入数据时使用的 schema (the writer’s schema) 不同的 schema (the reader’s schema) 来将数据读回。这是一个强大的工具,因为它能够使
schema 演化(schema evolution). 为了演示,考虑为字符串对使用一个新的 schema, 添加一个 description 字段:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings with an added field.",
        "fields": [
        {"name": "left", "type": "string"},
        {"name": "right", "type": "string"},
        {"name": "description", "type": "string", "default": ""}
        ]
    }

可以使用这个 schema 读取之前我们序列化的数据,因为,至关重要地,给 description 字段一个默认值(the empty string), Avro 读取的记录中如果没有这样的字段
定义,会使用这个默认值。如果忽略这个 default 属性,当尝试读取旧格式的数据时会得到一个错误。

    NOTE
    ---------------------------------------------------------------------------------------------------------------------
    如果使用 null 作为默认值而不是 empty 的字符串,定义 description 字段应该使用一个带有 null Avro 类型的 union:
    
        {"name": "description", "type": ["null", "string"], "default": null}

当 reader 的 schema 不同于 writer 的 schema 时,使用 GenericDatumReader 有两个 schema 对象的构造器,reader 的和 writer 的,
按以下顺序:

    DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema, newSchema);
    Decoder decoder = DecoderFactory.get().binaryDecoder(out.toByteArray(),    null);
    GenericRecord result = reader.read(null, decoder);
    
    assertThat(result.get("left").toString(), is("L"));
    assertThat(result.get("right").toString(), is("R"));
    assertThat(result.get("description").toString(), is(""));

对于 datafiles ,有 writer 的 schema 存储在元数据中,我们只需要明确指定 reader 的 schema, 把 null 传递给 writer 的 schema:

    DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(null, newSchema);

另一种使用不同 reader schema 的常用场景是从 record 中移除字段(drop fields in a record),这种操作称为 projection. 在持有的记录中包含有当量的字段并且
只想读取其中很少的一部分时这种方法很有用。例如,下面的 schema 可以用于只读取一个 StringPair 的 right 字段:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "The right field of a pair of strings.",
        "fields": [
        {"name": "right", "type": "string"}
        ]
    }

    
Schema 解析的规则直接影响 Schema 如何从一个版本演变到下一版本,并在 Avro 规范中对所有的 Avro 类型阐明。下表从 reader 和 writer (or servers and clients)
角度展示一个 record 演化规则的概要:

    
                                    Schema resolution of records
                            
    +===========+===========+===========+=======================================================================================================+
    | 新 schema    | Writer    | Reader    |                                 操作                                                                    |
    +-----------+-----------+-----------+-------------------------------------------------------------------------------------------------------+
    | 添加        | Old        | New        | The reader uses the default value of the new field, since it is not written by the writer.            |
    |             +-----------+-----------+-------------------------------------------------------------------------------------------------------+
    | 字段        | New        | Old        | The reader does not know about the new field written by the writer, so it is ignored (projection)        |
    +-----------+-----------+-----------+-------------------------------------------------------------------------------------------------------+
    | 移除        | Old        | New        | The reader ignores the removed field (projection).                                                    |
    |             +-----------+-----------+-------------------------------------------------------------------------------------------------------+
    | 字段        | New        | Old        | The removed field is not written by the writer. If the old schema had a default defined for            |
    |            |            |            | the field, the reader uses this; otherwise, it gets an error. In this case, it is best to update the    |
    |            |            |            | reader’s schema, either at the same time as or before the writer’s.                                    |
    +-----------+-----------+-----------+-------------------------------------------------------------------------------------------------------+

另一个演化 Avro schema 有用的技术是使用名称别名(name aliases). 别名允许在 schema 中使用与原始写入数据时使用的 schema 中不同的名称来读取 Avro 数据。
例如,下面的 reader schema 用于新的字段名称 first 和 second 替代 left 和 right 读取 StringPair:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings with aliased field names.",
        "fields": [
        {"name": "first", "type": "string", "aliases": ["left"]},
        {"name": "second", "type": "string", "aliases": ["right"]}
        ]
    }

注意,别名用于转换(at read time) writer schema 到 reader schema, 但被别名的名称对 reader 是不可用的,在这个例子中, reader 不能使用字段名 left 和
right, 因为它们已经被转换为 first 和 second



*
*
*

6. 排序次序 (Sort Order)
--------------------------------------------------------------------------------------------------------------------------------------------------
Avro 为对象定义了排序次序。对于大多数 Avro 类型,正如我们所期望的那样,排序次序是它的自然顺序,例如,数值类型是按它们的数值升序排序。其类型有一点
巧妙,例如, 枚举类型按它们定义的符号值次序进行比较,而不是按符号字符串的值次序比较。

除了 record 类型外,所有均按照 Avro 规范中预先定义的规则进行排序,用户不能改写。对于 record 类型,可以通过为字段指定 order 属性(order attribute) 来
控制排序次序。可以取三个值其中之一:ascending (the default), descending (to reverse the order), 或者 ignore (so the field is skipped for comparison
purposes)。

举个例子,下面的 schema (SortedStringPair.avsc) 定义了一个有序的 StringPair record, 按 right 字段降序排序。 left 字段在排序时被忽略:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings, sorted by right field descending.",
        "fields": [
        {"name": "left", "type": "string", "order": "ignore"},
        {"name": "right", "type": "string", "order": "descending"}
        ]
    }

record 的字段按 reader schema 在文档中的次序两两比较,因此,指定一个合适的 reader schema, 可以对数据记录使用任意的次序。下面的 schema (
SwitchedStringPair.avsc)定义了一个先按 right 字段,然后按 left 字段排序的排序次序:

    {
        "type": "record",
        "name": "StringPair",
        "doc": "A pair of strings, sorted by right then left.",
        "fields": [
        {"name": "right", "type": "string"},
        {"name": "left", "type": "string"}
        ]
    }
    
Avro 实现高效的二进制比较操作。也就是说, Avro 不必将二进制数据反序列化成对象来执行比较,因为它能直接在字节流上执行比较操作。例如,在原始的 StringPair
schema(with no order attributes), Avro 实现二进制比较如下:

第一个字段(The first field), left, 是一个 UTF-8 编码的字符串, Avro 可以按词汇字节进行比较。如果不同,次序就确定了, Avro 可以就此结束比较过程。否则,
如果这两个字节序列相同,就比较两个第二个字段(right), 因为这个字段是另一个 UTF-8 字符串,因此再一次进行字节级别上的词汇比较。

注意,在此描述的比较功能,与为 Writable 类型在 Implementing a RawComparator for speed 写的二进制 comparator 具有完全相同的逻辑。最重要的是 Avro 为
我们提供了comparator, 因此我们不需要写以及维护这些代码。也可以通过改变 reader 的 schema, 很容易地改变排序次序。对于 SortedStringPair.avsc 和
SwitchedStringPair.avsc schema, Avro 使用的比较函数与刚刚描述的内容基本上是相同的。不同点是要考虑使用哪些字段,考虑字段使用的排序次序,以及使用升序
还是降序。    
    

*
*
*

7. Avro MapReduce
--------------------------------------------------------------------------------------------------------------------------------------------------
Avro 提供了很多类用于简化对 Avro 数据运行 MapReduce 程序,它们在 org.apache.avro.mapreduce 包中。

再次工作在气象数据集,查出每年最高气温的 MapReduce 程序,这次使用 Avro MapReduce API . 使用下面的 schema 表示气温记录:

    {
        "type": "record",
        "name": "WeatherRecord",
        "doc": "A weather reading.",
        "fields": [
        {"name": "year", "type": "int"},
        {"name": "temperature", "type": "int"},
        {"name": "stationId", "type": "string"}
        ]
    }
    
下面的程序读取文本输入,并写出到包含气温记录的 Avro 数据文件中作为输出。

// MapReduce program to find the maximum temperature, creating Avro output

public class AvroGenericMaxTemperature extends Configured implements Tool {
    private static final Schema SCHEMA = new Schema.Parser().parse(
        "{" +
        " \"type\": \"record\"," +
        " \"name\": \"WeatherRecord\"," +
        " \"doc\": \"A weather reading.\"," +
        " \"fields\": [" +
        " {\"name\": \"year\", \"type\": \"int\"}," +
        " {\"name\": \"temperature\", \"type\": \"int\"}," +
        " {\"name\": \"stationId\", \"type\": \"string\"}" +
        " ]" +
        "}"
    );
        
    public static class MaxTemperatureMapper extends Mapper<LongWritable, Text, AvroKey<Integer>, AvroValue<GenericRecord>> {
        private NcdcRecordParser parser = new NcdcRecordParser();
        private GenericRecord record = new GenericData.Record(SCHEMA);
        
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            parser.parse(value.toString());
            if (parser.isValidTemperature()) {
                record.put("year", parser.getYearInt());
                record.put("temperature", parser.getAirTemperature());
                record.put("stationId", parser.getStationId());
                context.write(new AvroKey<Integer>(parser.getYearInt()),
                new AvroValue<GenericRecord>(record));
            }
        }
    }

    public static class MaxTemperatureReducer extends Reducer<AvroKey<Integer>, AvroValue<GenericRecord>, AvroKey<GenericRecord>, NullWritable> {
        
        @Override
        protected void reduce(AvroKey<Integer> key, Iterable<AvroValue<GenericRecord>> values, Context context)
        throws IOException, InterruptedException {
            GenericRecord max = null;
            for (AvroValue<GenericRecord> value : values) {
                GenericRecord record = value.datum();
                if (max == null ||
                (Integer) record.get("temperature") > (Integer) max.get("temperature")) {
                    max = newWeatherRecord(record);
                }
            }
            context.write(new AvroKey(max), NullWritable.get());
        }
        
        private GenericRecord newWeatherRecord(GenericRecord value) {
            GenericRecord record = new GenericData.Record(SCHEMA);
            record.put("year", value.get("year"));
            record.put("temperature", value.get("temperature"));
            record.put("stationId", value.get("stationId"));
            return record;
        }
    }
    
    @Override
    public int run(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.printf("Usage: %s [generic options] <input> <output>\n",
            getClass().getSimpleName());
            ToolRunner.printGenericCommandUsage(System.err);
            return -1;
        }
        Job job = new Job(getConf(), "Max temperature");
        job.setJarByClass(getClass());
        job.getConfiguration().setBoolean(
        Job.MAPREDUCE_JOB_USER_CLASSPATH_FIRST, true);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        AvroJob.setMapOutputKeySchema(job, Schema.create(Schema.Type.INT));
        AvroJob.setMapOutputValueSchema(job, SCHEMA);
        AvroJob.setOutputKeySchema(job, SCHEMA);
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(AvroKeyOutputFormat.class);
        job.setMapperClass(MaxTemperatureMapper.class);
        job.setReducerClass(MaxTemperatureReducer.class);
        return job.waitForCompletion(true) ? 0 : 1;
    }
    
    public static void main(String[] args) throws Exception {
        int exitCode = ToolRunner.run(new AvroGenericMaxTemperature(), args);
        System.exit(exitCode);
    }
}

运行:
------------------------------------------------------------------------------------------------------
    % export HADOOP_CLASSPATH=avro-examples.jar
    % export HADOOP_USER_CLASSPATH_FIRST=true # override version of Avro in Hadoop
    % hadoop jar avro-examples.jar AvroGenericMaxTemperature \
    input/ncdc/sample.txt output

使用 Avro tools JAR 可以查看输出结果,工具将 Avro 数据文件内容以 JSON 格式输出:
    % java -jar $AVRO_HOME/avro-tools-*.jar tojson output/part-r-00000.avro
    {"year":1949,"temperature":111,"stationId":"012650-99999"}
    {"year":1950,"temperature":22,"stationId":"011990-99999"}


*
*
*

8. 使用 Avro MapReduce 排序 (Sorting Using Avro MapReduce)
--------------------------------------------------------------------------------------------------------------------------------------------------
使用 Avro 的排序能力并联合 MapReduce 写一个对 Avro 数据文件排序的程序。

// A MapReduce program to sort an Avro datafile
public class AvroSort extends Configured implements Tool {
    
    static class SortMapper<K> extends Mapper<AvroKey<K>, NullWritable, AvroKey<K>, AvroValue<K>> {
    
        @Override
        protected void map(AvroKey<K> key, NullWritable value, Context context) throws IOException, InterruptedException {
            context.write(key, new AvroValue<K>(key.datum()));
        }
    }
    
    static class SortReducer<K> extends Reducer<AvroKey<K>, AvroValue<K>, AvroKey<K>, NullWritable> {
    
        @Override
        protected void reduce(AvroKey<K> key, Iterable<AvroValue<K>> values, Context context) throws IOException, InterruptedException {
            for (AvroValue<K> value : values) {
                context.write(new AvroKey(value.datum()), NullWritable.get());
            }
        }
    }
    
    @Override
    public int run(String[] args) throws Exception {
        if (args.length != 3) {
            System.err.printf(
            "Usage: %s [generic options] <input> <output> <schema-file>\n",
            getClass().getSimpleName());
            ToolRunner.printGenericCommandUsage(System.err);
            return -1;
        }
        String input = args[0];
        String output = args[1];
        String schemaFile = args[2];
        Job job = new Job(getConf(), "Avro sort");
        job.setJarByClass(getClass());
        job.getConfiguration().setBoolean(
        Job.MAPREDUCE_JOB_USER_CLASSPATH_FIRST, true);
        FileInputFormat.addInputPath(job, new Path(input));
        FileOutputFormat.setOutputPath(job, new Path(output));
        AvroJob.setDataModelClass(job, GenericData.class);
        Schema schema = new Schema.Parser().parse(new File(schemaFile));
        AvroJob.setInputKeySchema(job, schema);
        AvroJob.setMapOutputKeySchema(job, schema);
        AvroJob.setMapOutputValueSchema(job, schema);
        AvroJob.setOutputKeySchema(job, schema);
        job.setInputFormatClass(AvroKeyInputFormat.class);
        job.setOutputFormatClass(AvroKeyOutputFormat.class);
        job.setOutputKeyClass(AvroKey.class);
        job.setOutputValueClass(NullWritable.class);
        job.setMapperClass(SortMapper.class);
        job.setReducerClass(SortReducer.class);
        return job.waitForCompletion(true) ? 0 : 1;
    }
    
    public static void main(String[] args) throws Exception {
        int exitCode = ToolRunner.run(new AvroSort(), args);
        System.exit(exitCode);
    }
}

程序使用 Java 中表示的通用类型参数 K 能够排序任何类型的 Avro records, 程序使用了 Generic Avro 映射,因而不需要任何代码生成。

排序操作发生在 MapReduce 的混洗阶段(shuffle),排序函数由传递给程序的 Avro schema 确定。

让我们使用这个程序来为之前创建的 pairs.avro 文件排序,使用 SortedStringPair.avsc schema 以 right 字段降序排序。
首先,使用 Avro tools JAR 观察输入文件的内容:

    % java -jar $AVRO_HOME/avro-tools-*.jar tojson input/avro/pairs.avro
    {"left":"a","right":"1"}
    {"left":"c","right":"2"}
    {"left":"b","right":"3"}
    {"left":"b","right":"2"}
    
然后运行排序:
    % hadoop jar avro-examples.jar AvroSort input/avro/pairs.avro output ch12-avro/src/main/resources/SortedStringPair.avsc
    
最后再检查输出结果:
    % java -jar $AVRO_HOME/avro-tools-*.jar tojson output/part-r-00000.avro
    {"left":"b","right":"3"}
    {"left":"b","right":"2"}
    {"left":"c","right":"2"}
    {"left":"a","right":"1"}
    
*
*
*

9. 其他语言的 Avro (Avro in Other Languages)
--------------------------------------------------------------------------------------------------------------------------------------------------
对于 Java 语言之外的语言和框架,有多种选择可以与 Avro 数据一起工作。

AvroAsTextInputFormat 设计用来允许 Hadoop 流式程序(Hadoop Streaming programs)读取 Avro 数据文件。文件中的每个数据都转换为一个字符串,数据的 JSON
格式表示,或者如果类型为 Avro bytes 仅仅表示为原始字节(raw bytes)。另一方面,可以指定 AvroTextOutputFormat 作为一个流式作业的输出格式来创建一个使用
bytes schema 的 Avro 数据文件,每个数据是由 tab 分隔的 key-value 对,写到流式输出(written from the Streaming output)。

对 Avro 进行处理,考虑使用其他框架也是有价值的,如 Pig, Hive, Crunch, and Spark, 因为通过指定恰当的存储格式,它们都能够读写 Avro datafiles 。


 

深入解析Apache Avro:高效数据序列化与RPC实战 Apache Avro 是一种语言中立、高效的数据序列化系统,采用紧凑的二进制格式存储数据,并通过 JSON 定义 Schema,实现数据结构与数据内容的分离。其核心优势在于强模式(Schema)驱动的设计,支持动态解析数据,无需生成代码即可跨语言读写。Avro 定义了一组基础的原始数据类型,这些类型构成了所有更复杂结构的基础。理解每种类型的语义、编码方式及其在不同场景下的使用限制,是设计高效 Avro Schema 的前提。record。 阅读详情

相关推荐

STM32H743实战(三)-- 时钟系统配置

本文详细讲解了STM32H743时钟系统的配置方法,重点解析了为何选择400MHz而非理论极限480MHz作为稳定运行的主频。通过STM32CubeIDE环境,手把手指导如何从外部晶振配置、电源电压设置到PLL锁相环参数调整,最终实现稳定可靠的400MHz系统时钟,并提供了代码验证与常见问题排查指南。

weixin_29164185的博客 368

avro的c语言api,理解 avro 及其解析模块:fastavro、pyavroc

8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?在我看来,avro 文件最大的特点无非是:便于实现并发。avro 是一种快速可压缩的二进制数据形式,对数据二进制序列化后可以节约数据存储空间和网络传输带宽使用,avro 文件总体上由文件头(Header)和数据块(Data Block)及同步标识(Synchronization marker)三部分组成。关于 avro ...

weixin_29346059的博客 894

JW01二氧化碳传感器实战:5分钟搞定Arduino环境监测系统(附完整代码)

本文详细介绍了如何使用JW01二氧化碳传感器与Arduino快速搭建环境监测系统。通过简单的硬件连接和完整的代码示例,读者可以在5分钟内实现CO2浓度实时监测,并了解数据解析、常见问题解决及进阶应用扩展。JW01传感器的高精度和易用性使其成为创客和嵌入式开发者的理想选择。

kite3的博客 383

Windows系统搭建Kafka C++ 客户端实现消息avro序列化发送

需求: 在原在水力发电厂在线监测VC++6.0软件中实现kafka C++客户端,将原始波形信号及计算指标点通过消息avro序列化发送给大数据平台侧kafka集群。 C++搭建kafka客户端用了我半个月的时间,avro序列化用了半个月的时间。相信好多人也是苦于没有系统性的参考耽误了好多工夫,我写这篇文档希望能给别人一些辅助。 开发准备工作: 本地装了一套kafka的环境: 序...

risen999的博客 2704

zemax混合式非序列模拟

注意不要点击左侧的非序列模式,那个时纯粹的非序列,会清除序列模式的数据。第2、4、6透镜材质为空气,是为了让光线进入到多重透镜内部。这时普通的优化方式会失败。平行光束经过多焦透镜时,会汇聚在不同焦距处。所以还需要控制能量的大小,进行优化。接下来用非序列模式设计一个多焦透镜。像面的孔径为圆形通光孔:0-1.2。透镜不同位置处有不同的聚焦位置。透镜的z轴位置相同,重合。

fendoudecheng的博客 3069

智能Agent如何重塑企业流程

在当今数字化时代,企业流程的效率和敏捷性至关重要。传统企业流程往往受限于人工操作,效率低下、成本高昂,难以适应快速变化的市场环境。智能Agent作为一种新兴技术,凭借其强大的智能化能力,正在逐渐改变企业流程的运作模式,为企业带来新的机遇和挑战。智能Agent是一种能够感知环境、自主决策、执行任务的软件实体。它可以模拟人类的智能行为,例如学习、推理、规划和沟通。通过将智能Agent嵌入到企业流程中,可以实现流程的自动化、优化和智能化,从而提高效率、降低成本、提升客户体验。8.1 研究成果总结。

AGI×大数据,开启智能时代的认知跃迁;解码AGI,赋能数据驱动的智能革命。 874

【AVRO】详解 AVRO 格式

本文对 avro 的格式定义、编码方式、以及实际存储的文件格式进行了详细说明,最后也以一个实际例子进行了对照说明。另外, 在官网中还涉及 rpc 的使用、mapreduce 的使用,这里就没有展开说明,有兴趣的可移步官网进行查阅。

Data · Model · Agent · Repeat 5954

看懂 SAP S/4HANA 产品主数据里的 GTIN:一串号码背后的全球商品识别与业务协同

SAP S/4HANA中的GTIN管理是企业供应链运营的关键环节。本文深入解析GTIN的业务内涵及其在SAP系统中的实现方式:1) GTIN是全球通用的商品标识码,不同于企业内部物料编码;2) SAP主数据中GTIN与计量单位强绑定,需为不同包装层级维护独立GTIN;3) 同一产品可能因渠道、供应商差异存在多个GTIN;4) GTIN贯穿零售POS、仓储管理、EDI订单等核心业务流程;5) 通过典型案例说明错误维护GTIN将导致收银异常、仓库作业低效等运营问题。文章强调GTIN管理需结合包装层级、计量单位等

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1433

avro格式详解

【Avro介绍】Apache Avro是hadoop中的一个子项目,也是一个数据序列化系统,其数据最终以二进制格式,采用行式存储的方式进行存储。Avro提供了:丰富的数据结构可压缩、快速的二进制数据格式一个用来存储持久化数据的容器文件远程过程调用与动态语言的简单集成,代码生成不需要读取或写入数据文件,也不需要使用或实现RPC协议。代码生成是一种可选的优化,只值得在静态类型语言中实现。基于以上这些优...

hncscwc的博客 6277

【即插即用模块】Transformer篇 | MICCAI 2025 | ReLULA:Q/K双ReLU线性注意力,既轻又准!

本文介绍了一种基于线性注意力的多实例学习模块(Lin-MIL),适用于高分辨率视觉任务。该模块通过转置计算顺序和使用ReLU激活,将计算复杂度从O(n²d)降至O(nd²),同时提升特征判别性。核心创新包括Q/K双ReLU激活、可学习温度系数和数值稳定归一化。实验表明,该模块在轻量化视觉任务中优于传统线性注意力和Mamba架构。代码实现了模块化矩阵乘法,支持即插即用替换ViT自注意力层。该模块特别适合计算病理学等需要处理大量图像补丁的任务。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 140

银河麒麟桌面系统 必会操作 | 加装双系统(麒麟桌面系统+Windows系统)的详细方法(含常见故障和解决方法)

装好麒麟桌面操作系统的电脑上、再加装Windows 操作系统的详细方法;和在已经装好Windows系统的电脑上、再加装麒麟桌面操作系统的详细方法;含加装双系统过程中常见问题的解决方法。

qq_33216613的博客 2422

Avro介绍

Avro介绍 Apache Avro是一个数据序列化系统。 Avro所提供的属性: 1.丰富的数据结构2.使用快速的压缩二进制数据格式3.提供容器文件用于持久化数据4.远程过程调用RPC5.简单的动态语言结合功能,Avro 和动态语言结合后,读写数据文件和使...

asdzxc4567的博客 840

以宠辱之戒写 SAP Fiori Elements,把标准能力当成身体,把扩展冲动当成大患

SAP Fiori Elements开发中常面临业务方追求"独特页面"的压力,但过度自定义会破坏框架价值。老子"宠辱若惊"的智慧提醒开发者:不应因用户称赞或批评而动摇架构原则。标准模板的价值在于确保业务语义、交互规范和后端服务的一致性。扩展应遵循官方API,将业务逻辑放在ABAP/CDS层而非前端控制器。成熟项目会平衡标准与定制,使用annotation表达UI行为,仅在必要时通过受支持的extension points进行增强,保持系统的长期可维护性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1000

[环境] hadoop 开发环境maven管理

贴一下整理的maven管理配置(待补充) [code="pom.xml"] 4.0.0 com.sanss.hadoop parent 1.0.0 pom SANSSHadoop :: Module :: Parent ...

iteye_20264的博客 136

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Hadoop权威指南(第三版)笔记

第一章: 为什么不用数据库对大量硬盘上的大规模数据进行批量分享,而要用map reduce呢? 关乎计算机硬盘的发展趋势:寻址时间的提升远不敌传输速率的提升。寻址是导致硬盘操作延迟的主要原因。 另,M/R对半结构、非结构话数据更有效。 第二章: 气象数据集 详细实战解析 第四章: 序列化:将结构化对象转化为字节流以便在网络上传输或写到磁盘,经常出现在进程间通信和永久存储。 Hado...

476

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Hadoop最全的入门介绍

目录 Hadoop家族概述 Hadoop Hadoop介绍 HDFS 概述 节点介绍 文件读写 MapReduce 概述 原理过程分析 管理框架 YARN 失败处理 HBase 概述 内部原理 服务器 特点 存储特性 基本命令 配置教程 Hadoop家族概述 Hadoop:分布式计算开源框架,提供了一个分布式文件系统子项目(HDFS)和支持MapReduce分...

HJ 856

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Hadoop2 学习手册(三)

数据不只存在于某个时间点。特别是对于长期运行的生产工作流,您可能会在 Hadoop 集群中获取大量数据。需求很少会长时间保持不变,因此除了新逻辑之外,您可能还会看到该数据的格式发生了变化,或者需要使用多个数据源来提供在应用中处理的数据集。我们使用术语数据生命周期管理来描述一种处理数据收集、存储和转换的方法,该方法可确保数据处于需要的位置,采用其需要的格式,并允许数据和系统随时间演变。当然,我们可以将块放在一起,并使用类似 cron 的东西来进行简单的作业调度,但请记住,我们需要一个考虑到可靠性的接收管道。

龙哥盟 837

hadoop入门系列之二【hadoop项目以及结构】

Hadoop核心体系结构介绍

u014548782的专栏 4788

Hadoop组件

Pig、Hive和Mahout等工具则提供了更高层次的功能,使开发者更容易利用Hadoop的强大功能。Hive:一个数据仓库工具,可将结构化的数据文件映射为一张数据库表,并提供SQL样式的查询能力。Map/Reduce:Hadoop的核心计算模型,将大任务分解为小任务并在集群上的多台计算机上并行运行。HDFS(Hadoop Distributed File System):Hadoop的分布式文件系统,设计用来存储非常大的文件,具有高容错性和高吞吐量的特点。的大数据处理框架,由。

qq_41081716的博客 998

Hadoop 基本概念

一、Hadoop 简介 Hadoop 是一个由 Apache 基金会所开发的分布式系统基础架构,它可以使用户在不了解分布式底层细节的情況下开发分布式程序,充分利用集群的威力进行高速运算和存储。 从其定义就可以发现,它解決了两大问题:大数据存储、大数据分析。也就是 Hadoop 的两大核心:HDFS 和 MapReduce。 HDFS(Hadoop Distributed File S...

weixin_30916125的博客 449

Apache Hadoop的核心组件

Haddoop Common:常见的使用工具,用来支持其他Hadoop模块。 Hadoop Distributed File System(HDFS):分布式文件系统,它提供对应用程序数据的高吞吐量访问。 Hadoop YARN:一个作业调度和集群资源管理框架。 Hadoop MapReduce:基于YARN的大型数据集并行处理系统。 Ambari:一个基于Web的工具,用于配置、管理和监控Apache Hadoop集群,支持Hadoop HDFS、Hadoop MapReduce、Hive、HCa

rabies的博客 805

【Hadoop深度探索一】初识hadoop

Apache Hadoop工程已发展成一个可靠的(reliable),轻量的(scalable),分布式计算(distributed computing)的开源软件。 Apach Hadoop软件库是一个...

ciyunti3476的博客 124

2、hadoop子项目

##Pig---hadoop客户端 Pig是一个基于Hadoop的大规模数据分析平台,它提供的SQL-LIKE语言叫Pig Latin,该语言的编译器会把类SQL的数据分析请求转换为一系列经过优化处理的MapReduce运算。Pig为复杂的海量数据并行计算提供了一个简单的操作和编程接口。 http://guoyunsky.iteye.com/blog/1317084 http://blac...

nickfover的专栏 213

Hadoop学习-生态体系(ecosystem)概览

0. 大背景 全球No.1搜索引擎公司谷歌(Google)面临每天海量搜索引擎数据的问题,经过长时间的实践积累, 谷歌形成了自己的大数据框架,但是并没有开源,而是发表了一篇论文,阐述了自己的思想,在论文中 提到了MapReduce的方法。这篇论文,被Doug Cutting也就是后来的Hadoop之父所关注,引起了他极大的兴趣。 因为,这个时候,他正在致力于一个项目,该项目需要多任务并行处...

weixin_33743703的博客 136

Apache Avro 使用教程

Apache Avro 使用教程 项目介绍 Apache Avro 是一个数据序列化系统,设计用于支持数据交换和服务间通信。它提供了一种紧凑、快速、跨语言的数据存储和传输方式。Avro 支持动态类型系统,并且可以通过 JSON 来定义这些类型和数据模式。这使得它在处理多语言环境中的数据时特别有用。GitHub仓库 提供了该项目的一个具体实现或相关工具,虽然此处链接指向的是一个特定用户的fork,...

gitblog_00709的博客 927

Hadoop ecosystem自己的理解

Avro : Avro is a data serialization framework that is useful in Hadoop and other systems. The framework allows one to define schema which is language independent so that data can be interchanged bet

sinat_19371493的专栏 615
上一篇: Ambari 操作指南 (Ambari Operations) 之六
下一篇: Hadoop 之 ZooKeeper (一)
devalone
博客等级 码龄17年 108粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值