zoukankan      html  css  js  c++  java
  • hadoop深入研究:(十八)——Avro schema兼容

    转载请写明来源地址:http://blog.csdn.net/lastsweetop/article/details/9900129

    所有源码在github上,https://github.com/lastsweetop/styhadoop

     

    兼容条件

    在实际的应用中,因为应用版本的问题经常遇到读和写的schema不相同的情况,幸运的是avro已经提供了相关的解决方案。

    下面图示说明:

     

    record兼容

    在hadoop的实际应用中,更多是以record的形式进行交互,接下来我们重点讲解下record的兼容。
    首先从读写schema的角度取考虑,读写schema的不同无外乎就两种,读的schema比写的schema多了一个field,读的schema比写的schema少了一个field,这两种情况处理起来都很简单。
    先看下写的schema:
    {
        "type":"record",
        "name":"com.sweetop.styhadoop.StringPair",
        "doc":"A pair of strings",
        "fields":[
            {"name":"left","type":"string"},
            {"name":"right","type":"string"}
        ]
    }

    增加了field的情况

    增加了field后的schema
    {
        "type":"record",
        "name":"com.sweetop.styhadoop.StringPair",
        "doc":"A pair of strings",
        "fields":[
            {"name":"left","type":"string"},
            {"name":"right","type":"string"},
            {"name":"description","type":"string","default":""}
        ]
    }
    用增加了field的schema取读数据。new GenericDatumReader<GenericRecord>(null, newSchema),第一个参数为写的schema,第二个参数为读的schema,
    由于读的是avro datafile,schema已经在文件的头部指定,所以写的schema可以忽略掉。
        @Test
        public void testAddField() throws IOException {
            //将schema从newStringPair.avsc文件中加载
            Schema.Parser parser = new Schema.Parser();
            Schema newSchema = parser.parse(getClass().getResourceAsStream("/addStringPair.avsc"));
    
            File file = new File("data.avro");
            DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(null, newSchema);
            DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader);
            for (GenericRecord record : dataFileReader) {
                System.out.println("left=" + record.get("left") + ",right=" + record.get("right") + ",description="
                        + record.get("description"));
            }
        }
    

    输出结果为
    left=L,right=R,description=
    left=L,right=R,description=
    description用默认值空字符串代替

    减少了field的情况

    减少了field的schema
    {
        "type":"record",
        "name":"com.sweetop.styhadoop.StringPair",
        "doc":"A pair of strings",
        "fields":[
            {"name":"left","type":"string"}
        ]
    }
    用减少了field的schema取读取
        @Test
        public void testRemoveField() throws IOException {
            //将schema从StringPair.avsc文件中加载
            Schema.Parser parser = new Schema.Parser();
            Schema newSchema = parser.parse(getClass().getResourceAsStream("/removeStringPair.avsc"));
    
            File file = new File("data.avro");
            DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(null, newSchema);
            DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader);
            for (GenericRecord record : dataFileReader) {
                System.out.println("left=" + record.get("left"));
            }
        }
    输出结果为:
    left=L
    left=L
    删除的field被忽略掉

    新旧版本schema

    如果从新旧版本的角度取考虑。
    新版本schema比旧版本schema增加了一个字段
    1.新版本取读旧版本的数据,使用新版本schema里新增field的默认值
    2.旧版本读新版本的数据,新版本schema里新增field被旧版本的忽略掉
    新版本schema比旧版半schema较少了一个字段
    1.新版本读旧版本的数据,减少的field被新版本忽略掉
    2.旧版本读新版本的数据,旧版本的schema使用起被删除field的默认值,如果没有就会报错,那么升级旧版本

    别名

    别名是另一个用于schema兼容的方法,可以将写的schema的field名字转换成读的schema的field,记住并不是加了aliases字段。
    而是将写的filed的name属性变为aliases,读的时候只认name属性。
    来看下加了别名的schema
    {
        "type":"record",
        "name":"com.sweetop.styhadoop.StringPair",
        "doc":"A pair of strings",
        "fields":[
            {"name":"first","type":"string","aliases":["left"]},
            {"name":"second","type":"string","aliases":["right"]}
        ]
    }
    使用别名schema去读数据,这里不能再用left,right,而要用first,second
        @Test
        public void testAliasesField() throws IOException {
            //将schema从StringPair.avsc文件中加载
            Schema.Parser parser = new Schema.Parser();
            Schema newSchema = parser.parse(getClass().getResourceAsStream("/aliasesStringPair.avsc"));
    
            File file = new File("data.avro");
            DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(null, newSchema);
            DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader);
            for (GenericRecord record : dataFileReader) {
                System.out.println("first=" + record.get("first")+",second="+record.get("second"));
            }
        }
    输出结果
    first=L,second=R
    first=L,second=R
  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/james1207/p/3278408.html
Copyright © 2011-2022 走看看